diff --git a/Cargo.lock b/Cargo.lock index b684d41342..b72df7a1aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4403,19 +4403,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" -dependencies = [ - "indexmap 2.2.6", - "itoa", - "ryu", - "serde", - "unsafe-libyaml", -] - [[package]] name = "serial_test" version = "0.9.0" @@ -5337,12 +5324,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.7.1" @@ -5457,7 +5438,6 @@ dependencies = [ "jsonwebkey", "jsonwebtoken", "kbs-types 0.6.0", - "lazy_static", "log", "openssl", "rstest", @@ -5466,7 +5446,6 @@ dependencies = [ "serde", "serde_json", "serde_with", - "serde_yaml", "serial_test", "sev", "shadow-rs", diff --git a/attestation-service/verifier/Cargo.toml b/attestation-service/verifier/Cargo.toml index c4cb428893..8dc16e0a71 100644 --- a/attestation-service/verifier/Cargo.toml +++ b/attestation-service/verifier/Cargo.toml @@ -13,7 +13,7 @@ az-tdx-vtpm-verifier = [ "az-tdx-vtpm", "openssl", "tdx-verifier" ] snp-verifier = [ "asn1-rs", "openssl", "sev", "x509-parser" ] csv-verifier = [ "openssl", "csv-rs", "codicon" ] cca-verifier = [ "ear", "jsonwebtoken", "veraison-apiclient" ] -se-verifier = [ "openssl" ] +se-verifier = [ "openssl", "pv", "serde_with", "tokio/sync" ] [dependencies] anyhow.workspace = true @@ -34,16 +34,15 @@ hex.workspace = true jsonwebkey = "0.3.5" jsonwebtoken = { workspace = true, default-features = false, optional = true } kbs-types.workspace = true -lazy_static = "1.4.0" log.workspace = true openssl = { version = "0.10.55", optional = true } -pv = { version = "0.10.0", package = "s390_pv" } +pv = { version = "0.10.0", package = "s390_pv", optional = true } scroll = { version = "0.11.0", default-features = false, features = ["derive"], optional = true } serde.workspace = true serde_json.workspace = true -serde_with.workspace = true -serde_yaml = "0.9.0" +serde_with = { workspace = true, optional = true } sev = { version = "3.1.1", features = ["openssl", "snp"], optional = true } +tokio = { workspace = true, optional = true, default-features = false } intel-tee-quote-verification-rs = { git = "https://github.com/intel/SGXDataCenterAttestationPrimitives", tag = "DCAP_1.21", optional = true } strum.workspace = true veraison-apiclient = { git = "https://github.com/chendave/rust-apiclient", branch = "token", optional = true } diff --git a/attestation-service/verifier/src/lib.rs b/attestation-service/verifier/src/lib.rs index 6e57e5b739..f0e2e7a289 100644 --- a/attestation-service/verifier/src/lib.rs +++ b/attestation-service/verifier/src/lib.rs @@ -112,7 +112,6 @@ pub fn to_verifier(tee: &Tee) -> Result> { } } } - } } @@ -168,16 +167,13 @@ pub trait Verifier { ) -> Result; /// Generate the supplemental challenge - /// + /// /// Some TEE like IBM SE need a `challenge` generated on verifier side /// and pass it to attester side. This challenge is used by attester to /// generate the evidence /// /// A optional `tee_parameters` comes from the attester side as the input. - async fn generate_supplemental_challenge( - &self, - _tee_parameters: String, - ) -> Result { + async fn generate_supplemental_challenge(&self, _tee_parameters: String) -> Result { Ok(String::new()) } } diff --git a/attestation-service/verifier/src/se/ibmse.rs b/attestation-service/verifier/src/se/ibmse.rs index 5666a32bc3..2328de346a 100644 --- a/attestation-service/verifier/src/se/ibmse.rs +++ b/attestation-service/verifier/src/se/ibmse.rs @@ -3,80 +3,84 @@ // SPDX-License-Identifier: Apache-2.0 // -extern crate lazy_static; -use anyhow::{anyhow, bail, Result}; +use crate::TeeEvidenceParsedClaim; +use anyhow::{anyhow, bail, Context, Result}; +use core::result::Result::Ok; use log::{debug, info, warn}; -use openssl::{ - encrypt::{Decrypter, Encrypter}, - pkey::{PKey, Private, Public}, - rsa::{Padding, Rsa}, -}; -use pv::{ - attest::{ - AdditionalData, AttestationFlags, AttestationItems, AttestationMeasAlg, - AttestationMeasurement, AttestationRequest, AttestationVersion, - }, - misc::{open_file, read_certs, read_file}, - request::{BootHdrTags, CertVerifier, HkdVerifier, ReqEncrCtx, Request, SymKeyType}, - uv::ConfigUid, +use openssl::encrypt::{Decrypter, Encrypter}; +use openssl::pkey::{PKey, Private, Public}; +use openssl::rsa::{Padding, Rsa}; +use pv::attest::{ + AdditionalData, AttestationFlags, AttestationItems, AttestationMeasAlg, AttestationMeasurement, + AttestationRequest, AttestationVersion, }; +use pv::misc::{open_file, read_certs}; +use pv::request::{BootHdrTags, CertVerifier, HkdVerifier, ReqEncrCtx, Request, SymKeyType}; +use pv::uv::ConfigUid; use serde::{Deserialize, Serialize}; -use serde_json; use serde_with::{base64::Base64, serde_as}; -use std::{fs::File, io::Read, sync::Mutex}; +use std::{env, fs}; -lazy_static::lazy_static! { - static ref PUB_KEY_FILE_CONTENTS: Mutex>> = Mutex::new(None); - static ref PRI_KEY_FILE_CONTENTS: Mutex>> = Mutex::new(None); -} +const DEFAULT_SE_HOST_KEY_DOCUMENTS_ROOT: &str = "/run/confidential-containers/ibmse/hkds"; -fn get_cached_file_or_read(filename: &str, content_ref: &Mutex>>) -> Result> { - let mut guard = content_ref.lock().map_err(|_| anyhow!("Failed to acquire lock"))?; - - if let Some(contents) = guard.as_ref().cloned() { - info!("Reading key_file contents from cache."); - Ok(contents) - } else { - info!("Reading key_file contents from file."); - let mut file = File::open(filename)?; - let mut contents = vec![]; - file.read_to_end(&mut contents)?; - *guard = Some(contents.clone()); - Ok(contents) - } -} +const DEFAULT_SE_CERTIFICATES_ROOT: &str = "/run/confidential-containers/ibmse/certs"; -fn encrypt_measurement_key(key: &[u8], rsa_public_key: &PKey) -> Result> { - info!("encrypt_measurement_key."); - let mut encrypter = Encrypter::new(rsa_public_key)?; - encrypter.set_rsa_padding(Padding::PKCS1)?; +const DEFAULT_SE_CERTIFICATE_ROOT_CA: &str = "/run/confidential-containers/ibmse/certs/ca"; - let buffer_len = encrypter.encrypt_len(key)?; - let mut encrypted_hmac_key = vec![0; buffer_len]; - let len = encrypter.encrypt(key, &mut encrypted_hmac_key)?; - encrypted_hmac_key.truncate(len); +const DEFAULT_SE_CERTIFICATE_REVOCATION_LISTS_ROOT: &str = + "/run/confidential-containers/ibmse/crls"; - Ok(encrypted_hmac_key) +const DEFAULT_SE_IMAGE_HEADER_FILE: &str = "/run/confidential-containers/ibmse/hdr/hdr.bin"; + +const DEFAULT_SE_MEASUREMENT_ENCR_KEY_PRIVATE: &str = + "/run/confidential-containers/ibmse/rsa/encrypt_key.pem"; + +const DEFAULT_SE_MEASUREMENT_ENCR_KEY_PUBLIC: &str = + "/run/confidential-containers/ibmse/rsa/encrypt_key.pub"; + +macro_rules! env_or_default { + ($env:literal, $default:ident) => { + match env::var($env) { + Ok(env_path) => env_path, + Err(_) => $default.into(), + } + }; } -fn decrypt_measurement_key(key: &[u8], rsa_private_key: &PKey) -> Result> { - info!("decrypt_measurement_key."); - let mut decrypter = Decrypter::new(rsa_private_key)?; - decrypter.set_rsa_padding(Padding::PKCS1)?; +fn list_files_in_folder(dir: &str) -> Result> { + let mut file_paths = Vec::new(); - let buffer_len = decrypter.decrypt_len(key)?; - let mut decrypted_hmac_key = vec![0; buffer_len]; - let decrypted_len = decrypter.decrypt(key, &mut decrypted_hmac_key)?; - decrypted_hmac_key.truncate(decrypted_len); + for entry in fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); - Ok(decrypted_hmac_key) + if path.is_file() { + if let Some(path_str) = path.to_str() { + file_paths.push(path_str.to_string()); + } + } + } + + Ok(file_paths) } #[serde_as] -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct UserData { +#[derive(Debug, Serialize, Deserialize)] +pub struct SeAttestationResponse { #[serde_as(as = "Base64")] - image_btph: Vec, + measurement: Vec, + #[serde_as(as = "Base64")] + additional_data: Vec, + #[serde_as(as = "Base64")] + user_data: Vec, + #[serde_as(as = "Base64")] + cuid: ConfigUid, + #[serde_as(as = "Base64")] + encr_measurement_key: Vec, + #[serde_as(as = "Base64")] + encr_request_nonce: Vec, + #[serde_as(as = "Base64")] + image_hdr_tags: BootHdrTags, } #[repr(C)] @@ -111,94 +115,72 @@ pub struct SeAttestationRequest { image_hdr_tags: BootHdrTags, } -impl SeAttestationRequest { - pub fn create( - hkds: &Vec, - certs: &Vec, - crls: &Vec, - root_ca_path: Option, - image_hdr_tags: &mut BootHdrTags, - pub_key_file: &str, - ) -> Result { - let att_version = AttestationVersion::One; - let meas_alg = AttestationMeasAlg::HmacSha512; - - let mut att_flags = AttestationFlags::default(); - att_flags.set_image_phkh(); - att_flags.set_attest_phkh(); - let mut arcb = AttestationRequest::new(att_version, meas_alg, att_flags)?; - let verifier = CertVerifier::new(certs.as_slice(), crls.as_slice(), root_ca_path, false)?; +#[derive(Debug)] +pub struct RealSeVerifier { + rsa_private_key: PKey, + rsa_public_key: PKey, +} - for hkd in hkds { - let hk = read_file(hkd, "host-key document")?; - let certs = read_certs(&hk)?; - if certs.is_empty() { - warn!("The host key document in '{hkd}' contains empty certificate!"); - } - if certs.len() != 1 { - warn!("The host key document in '{hkd}' contains more than one certificate!") - } - let c = certs - .first() - .ok_or(anyhow!("File does not contain a X509 certificate"))?; - verifier.verify(c)?; - arcb.add_hostkey(c.public_key()?); - } - let encr_ctx = ReqEncrCtx::random(SymKeyType::Aes256)?; - let request_blob = arcb.encrypt(&encr_ctx)?; - let contents = get_cached_file_or_read(pub_key_file, &PUB_KEY_FILE_CONTENTS)?; - let rsa = Rsa::public_key_from_pem(&contents)?; - let rsa_public_key = &PKey::from_rsa(rsa)?; +impl RealSeVerifier { + pub fn new() -> Result { + let pri_key_file = env_or_default!( + "SE_MEASUREMENT_ENCR_KEY_PRIVATE", + DEFAULT_SE_MEASUREMENT_ENCR_KEY_PRIVATE + ); + let priv_contents = fs::read(pri_key_file)?; + let rsa_private_key = Rsa::private_key_from_pem(&priv_contents)?; + let rsa_private_key = PKey::from_rsa(rsa_private_key)?; - let conf_data = arcb.confidential_data(); - let encr_measurement_key = - encrypt_measurement_key(conf_data.measurement_key(), rsa_public_key)?; - let binding = conf_data - .nonce() - .clone() - .ok_or(anyhow!("Failed to get nonce binding"))?; - let nonce = binding.value(); - let encr_request_nonce = encrypt_measurement_key(nonce, rsa_public_key)?; + let pub_key_file = env_or_default!( + "SE_MEASUREMENT_ENCR_KEY_PUBLIC", + DEFAULT_SE_MEASUREMENT_ENCR_KEY_PUBLIC + ); + let pub_contents = fs::read(pub_key_file)?; + let rsa = Rsa::public_key_from_pem(&pub_contents)?; + let rsa_public_key = PKey::from_rsa(rsa)?; Ok(Self { - request_blob, - measurement_size: meas_alg.exp_size(), - additional_size: arcb.flags().expected_additional_size(), - encr_measurement_key, - encr_request_nonce, - image_hdr_tags: *image_hdr_tags, + rsa_private_key, + rsa_public_key, }) } -} -#[serde_as] -#[derive(Debug, Serialize, Deserialize)] -pub struct SeAttestationResponse { - #[serde_as(as = "Base64")] - measurement: Vec, - #[serde_as(as = "Base64")] - additional_data: Vec, - #[serde_as(as = "Base64")] - user_data: Vec, - #[serde_as(as = "Base64")] - cuid: ConfigUid, - #[serde_as(as = "Base64")] - encr_measurement_key: Vec, - #[serde_as(as = "Base64")] - encr_request_nonce: Vec, - #[serde_as(as = "Base64")] - image_hdr_tags: BootHdrTags, -} + fn decrypt(&self, ciphertext: &[u8]) -> Result> { + let mut decrypter = Decrypter::new(&self.rsa_private_key)?; + decrypter.set_rsa_padding(Padding::PKCS1)?; + + let buffer_len = decrypter.decrypt_len(ciphertext)?; + let mut decrypted_hmac_key = vec![0; buffer_len]; + let decrypted_len = decrypter.decrypt(ciphertext, &mut decrypted_hmac_key)?; + decrypted_hmac_key.truncate(decrypted_len); + + Ok(decrypted_hmac_key) + } -impl SeAttestationResponse { - pub fn verify(&self, priv_key_file: &str) -> Result { - let contents = get_cached_file_or_read(priv_key_file, &PRI_KEY_FILE_CONTENTS)?; + fn encrypt(&self, text: &[u8]) -> Result> { + let mut encrypter = Encrypter::new(&self.rsa_public_key)?; + encrypter.set_rsa_padding(Padding::PKCS1)?; + + let buffer_len = encrypter.encrypt_len(text)?; + let mut encrypted_hmac_key = vec![0; buffer_len]; + let len = encrypter.encrypt(text, &mut encrypted_hmac_key)?; + encrypted_hmac_key.truncate(len); + + Ok(encrypted_hmac_key) + } + + pub fn evaluate(&self, evidence: &[u8]) -> Result { + info!("IBM SE verify API called."); - let rsa = Rsa::private_key_from_pem(&contents)?; - let rsa_private_key = &PKey::from_rsa(rsa)?; + // evidence is serialized SeAttestationResponse String bytes + let se_response: SeAttestationResponse = serde_json::from_slice(evidence)?; - let meas_key = decrypt_measurement_key(&self.encr_measurement_key, rsa_private_key)?; - let nonce = decrypt_measurement_key(&self.encr_request_nonce, rsa_private_key)?; + let meas_key = self + .decrypt(&se_response.encr_measurement_key) + .context("decrypt Measurement Key")?; + let nonce = self + .decrypt(&se_response.encr_request_nonce) + .context("decrypt Request Nonce")?; if nonce.len() != 16 { bail!("The nonce vector must have exactly 16 elements."); @@ -207,31 +189,32 @@ impl SeAttestationResponse { let nonce_array: [u8; 16] = nonce .try_into() .map_err(|_| anyhow!("Failed to convert nonce from Vec to [u8; 16]."))?; - let meas_key = &PKey::hmac(&meas_key)?; + + let meas_key = PKey::hmac(&meas_key)?; let items = AttestationItems::new( - &self.image_hdr_tags, - &self.cuid, - Some(&self.user_data), + &se_response.image_hdr_tags, + &se_response.cuid, + Some(&se_response.user_data), Some(&nonce_array), - Some(&self.additional_data), + Some(&se_response.additional_data), ); let measurement = - AttestationMeasurement::calculate(items, AttestationMeasAlg::HmacSha512, meas_key)?; + AttestationMeasurement::calculate(items, AttestationMeasAlg::HmacSha512, &meas_key)?; - if !measurement.eq_secure(&self.measurement) { - debug!("Recieved: {:?}", self.measurement); + if !measurement.eq_secure(&se_response.measurement) { + debug!("Recieved: {:?}", se_response.measurement); debug!("Calculated: {:?}", measurement.as_ref()); warn!("Attestation measurement verification failed. Calculated and received attestation measurement are not equal."); bail!("Failed to verify the measurement!"); } - + // TODO check self.user_data.image_btph with previous saved value let mut att_flags = AttestationFlags::default(); att_flags.set_image_phkh(); att_flags.set_attest_phkh(); - let add_data = AdditionalData::from_slice(&self.additional_data, &att_flags)?; + let add_data = AdditionalData::from_slice(&se_response.additional_data, &att_flags)?; debug!("additional_data: {:?}", add_data); let image_phkh = add_data .image_public_host_key_hash() @@ -243,60 +226,86 @@ impl SeAttestationResponse { // TODO image_phkh and attestation_phkh with previous saved value let claims = SeAttestationClaims { - cuid: self.cuid, - user_data: self.user_data.clone(), + cuid: se_response.cuid, + user_data: se_response.user_data.clone(), version: AttestationVersion::One as u32, image_phkh: image_phkh.to_vec(), attestation_phkh: attestation_phkh.to_vec(), - tag: *self.image_hdr_tags.tag(), + tag: *se_response.image_hdr_tags.tag(), }; - Ok(claims) + + serde_json::to_value(claims).context("build json value from the se claims") } -} -pub fn create( - hkds: &Vec, - certs: &Vec, - crls: &Vec, - ca: String, - se_img_hdr: &str, - pub_key_file: &str, -) -> Result { - info!("IBM SE create API called."); - debug!("hkds: {:#?}", hkds); - debug!("certs: {:#?}", certs); - debug!("ca: {:#?}", ca); - debug!("se_img_hdr: {:#?}", se_img_hdr); - debug!("pub_key_file: {:#?}", pub_key_file); - - let mut hdr_file = open_file(se_img_hdr)?; - let mut image_hdr_tags = BootHdrTags::from_se_image(&mut hdr_file)?; - let root_ca = Some(ca); - - let se_request = SeAttestationRequest::create( - hkds, - certs, - crls, - root_ca, - &mut image_hdr_tags, - pub_key_file, - )?; - - let challenge = serde_json::to_string(&se_request)?; - debug!("challenge json: {:#?}", challenge); - - Ok(challenge) -} + pub async fn generate_supplemental_challenge(&self, _tee_parameters: String) -> Result { + let se_certificate_root = + env_or_default!("SE_CERTIFICATES_ROOT", DEFAULT_SE_CERTIFICATES_ROOT); + let certs = list_files_in_folder(&se_certificate_root)?; -pub fn verify(response: &[u8], priv_key_file: &str) -> Result { - info!("IBM SE verify API called."); - // response is serialized SeAttestationResponse String bytes - let response_str = std::str::from_utf8(response)?; - debug!("SeAttestationResponse json: {:#?}", response_str); - let se_response: SeAttestationResponse = serde_json::from_str(response_str)?; + let crl_root = env_or_default!( + "SE_CERTIFICATE_REVOCATION_LISTS_ROOT", + DEFAULT_SE_CERTIFICATE_REVOCATION_LISTS_ROOT + ); + let crls = list_files_in_folder(&crl_root)?; + + let root_ca_path = + env_or_default!("SE_CERTIFICATE_ROOT_CA", DEFAULT_SE_CERTIFICATE_ROOT_CA); + let verifier = + CertVerifier::new(certs.as_slice(), crls.as_slice(), Some(root_ca_path), false)?; + + let mut arcb = AttestationRequest::new( + AttestationVersion::One, + AttestationMeasAlg::HmacSha512, + AttestationFlags::default(), + )?; + + let hkds_root = env_or_default!( + "DEFAULT_SE_HOST_KEY_DOCUMENTS_ROOT", + DEFAULT_SE_HOST_KEY_DOCUMENTS_ROOT + ); + let hkds = list_files_in_folder(&hkds_root)?; + for hkd in &hkds { + let hk = std::fs::read(hkd).context("read host-key document")?; + let certs = read_certs(&hk)?; + if certs.is_empty() { + warn!("The host key document in '{hkd}' contains empty certificate!"); + } + if certs.len() != 1 { + warn!("The host key document in '{hkd}' contains more than one certificate!") + } + let c = certs + .first() + .ok_or(anyhow!("File does not contain a X509 certificate"))?; + verifier.verify(c)?; + arcb.add_hostkey(c.public_key()?); + } + + let encr_ctx = ReqEncrCtx::random(SymKeyType::Aes256)?; + let request_blob = arcb.encrypt(&encr_ctx)?; + let conf_data = arcb.confidential_data(); + let encr_measurement_key = + self.encrypt(conf_data.measurement_key())?; + let nonce = conf_data + .nonce() + .as_ref() + .ok_or(anyhow!("Failed to get nonce binding"))? + .value(); + let encr_request_nonce = self.encrypt(nonce)?; - let claims = se_response.verify(priv_key_file)?; - debug!("claims json: {:#?}", claims); + let se_img_hdr = env_or_default!("SE_IMAGE_HEADER_FILE", DEFAULT_SE_IMAGE_HEADER_FILE); + let mut hdr_file = open_file(se_img_hdr)?; + let image_hdr_tags = BootHdrTags::from_se_image(&mut hdr_file)?; - Ok(claims) + let se_attestation_request = SeAttestationRequest { + request_blob, + measurement_size: AttestationMeasAlg::HmacSha512.exp_size(), + additional_size: arcb.flags().expected_additional_size(), + encr_measurement_key, + encr_request_nonce, + image_hdr_tags, + }; + + let challenge = serde_json::to_string(&se_attestation_request)?; + Ok(challenge) + } } diff --git a/attestation-service/verifier/src/se/mod.rs b/attestation-service/verifier/src/se/mod.rs index 8293cd4c02..54bc22fa50 100644 --- a/attestation-service/verifier/src/se/mod.rs +++ b/attestation-service/verifier/src/se/mod.rs @@ -3,136 +3,43 @@ // SPDX-License-Identifier: Apache-2.0 // -use super::*; -use crate::se::ibmse::SeAttestationClaims; -use crate::{InitDataHash, ReportData}; +use anyhow::Result; use async_trait::async_trait; -use core::result::Result::Ok; -use std::{env, fs}; +use ibmse::RealSeVerifier; +use log::warn; +use tokio::sync::OnceCell; -pub mod ibmse; - -const DEFAULT_SE_HOST_KEY_DOCUMENTS_ROOT: &str = "/run/confidential-containers/ibmse/hkds"; -const DEFAULT_SE_CERTIFICATES_ROOT: &str = "/run/confidential-containers/ibmse/certs"; -const DEFAULT_SE_CERTIFICATE_ROOT_CA: &str = "/run/confidential-containers/ibmse/certs/ca"; -const DEFAULT_SE_CERTIFICATE_REVOCATION_LISTS_ROOT: &str = "/run/confidential-containers/ibmse/crls"; -const DEFAULT_SE_IMAGE_HEADER_FILE: &str = "/run/confidential-containers/ibmse/hdr/hdr.bin"; -const DEFAULT_SE_MEASUREMENT_ENCR_KEY_PRIVATE: &str = - "/run/confidential-containers/ibmse/rsa/encrypt_key.pem"; -const DEFAULT_SE_MEASUREMENT_ENCR_KEY_PUBLIC: &str = - "/run/confidential-containers/ibmse/rsa/encrypt_key.pub"; - -fn get_hkds_root() -> String { - if let Ok(env_path) = env::var("SE_HOST_KEY_DOCUMENTS_ROOT") { - return env_path; - } - DEFAULT_SE_HOST_KEY_DOCUMENTS_ROOT.into() -} - -fn get_certs_root() -> String { - if let Ok(env_path) = env::var("SE_CERTIFICATES_ROOT") { - return env_path; - } - DEFAULT_SE_CERTIFICATES_ROOT.into() -} - -fn get_root_ca_file() -> String { - if let Ok(env_path) = env::var("SE_CERTIFICATE_ROOT_CA") { - return env_path; - } - DEFAULT_SE_CERTIFICATE_ROOT_CA.into() -} - -fn get_crls_root() -> String { - if let Ok(env_path) = env::var("SE_CERTIFICATE_REVOCATION_LISTS_ROOT") { - return env_path; - } - DEFAULT_SE_CERTIFICATE_REVOCATION_LISTS_ROOT.into() -} - -fn get_img_hdr_file() -> String { - if let Ok(env_path) = env::var("SE_IMAGE_HEADER_FILE") { - return env_path; - } - DEFAULT_SE_IMAGE_HEADER_FILE.into() -} - -fn get_encrypt_priv_keyfile() -> String { - if let Ok(env_path) = env::var("SE_MEASUREMENT_ENCR_KEY_PRIVATE") { - return env_path; - } - DEFAULT_SE_MEASUREMENT_ENCR_KEY_PRIVATE.into() -} - -fn get_encrypt_pub_keyfile() -> String { - if let Ok(env_path) = env::var("SE_MEASUREMENT_ENCR_KEY_PUBLIC") { - return env_path; - } - DEFAULT_SE_MEASUREMENT_ENCR_KEY_PUBLIC.into() -} - -fn list_files_in_folder(dir: &str) -> Result> { - let mut file_paths = Vec::new(); +use crate::{InitDataHash, ReportData, TeeEvidenceParsedClaim, Verifier}; - for entry in fs::read_dir(dir)? { - let entry = entry?; - let path = entry.path(); - - if path.is_file() { - if let Some(path_str) = path.to_str() { - file_paths.push(path_str.to_string()); - } - } - } +pub mod ibmse; - Ok(file_paths) -} +static ONCE: OnceCell = OnceCell::const_new(); #[derive(Debug, Default)] -pub struct SeVerifier {} +pub struct SeVerifier; #[async_trait] impl Verifier for SeVerifier { async fn evaluate( &self, evidence: &[u8], - expected_report_data: &ReportData, - expected_init_data_hash: &InitDataHash, + _expected_report_data: &ReportData, + _expected_init_data_hash: &InitDataHash, ) -> Result { - verify_evidence(evidence, expected_report_data, expected_init_data_hash).await + let se_verifier = ONCE + .get_or_try_init(|| async { RealSeVerifier::new() }) + .await?; + warn!("IBM SE does not support initdata."); + se_verifier.evaluate(evidence) } async fn generate_supplemental_challenge( &self, _tee_parameters: String, ) -> Result { - let hkds = list_files_in_folder(&get_hkds_root())?; - let certs = list_files_in_folder(&get_certs_root())?; - let crls = list_files_in_folder(&get_crls_root())?; - // challenge is Serialized SeAttestationRequest, attester uses it to do perform action - // attester then generates and return Serialized SeAttestationResponse - ibmse::create( - &hkds, - &certs, - &crls, - get_root_ca_file(), - &get_img_hdr_file(), - &get_encrypt_pub_keyfile(), - ) + let se_verifier = ONCE + .get_or_try_init(|| async { RealSeVerifier::new() }) + .await?; + se_verifier.generate_supplemental_challenge(_tee_parameters) } } - -async fn verify_evidence( - evidence: &[u8], - _expected_report_data: &ReportData<'_>, - _expected_init_data_hash: &InitDataHash<'_>, -) -> Result { - // evidence is serialized SeAttestationResponse String bytes - let mut se_claims = ibmse::verify(evidence, &get_encrypt_priv_keyfile())?; - se_generate_parsed_claim(&mut se_claims).map_err(|e| anyhow!("error from se Verifier: {:?}", e)) -} - -fn se_generate_parsed_claim(se_claims: &mut SeAttestationClaims) -> Result { - let v = serde_json::to_value(se_claims).context("build json value from the se claims")?; - Ok(v as TeeEvidenceParsedClaim) -}