Skip to content

Commit

Permalink
Verifier: Add IBM Secure Execution verifier driver framework fix comm…
Browse files Browse the repository at this point in the history
…ents

Signed-off-by: Qi Feng Huo <[email protected]>
  • Loading branch information
Qi Feng Huo committed Jun 7, 2024
1 parent 567fbe3 commit d503b63
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 40 deletions.
6 changes: 3 additions & 3 deletions attestation-service/docs/parsed_claims.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ Note: The TD Report and TD Quote are fetched during early boot in this TEE. Kern

## IBM Secure Execution (SE)
- `se.version`: The version this quote structure.
- `se.cuid`: The config uid.
- `se.hdr.tag`: SE header tag (seht)
- `se.cuid`: The unique ID of the attested guest (configuration uniqe ID).
- `se.hdr.tag`: SE header tag.
- `se.image.phkh`: SE image public host key hash
- `se.attestation.phkh`: SE attestation public host key hash
- `se.user_data`: Custom attestation key owner data.
- `se.user_data`: Optional custom attestation owner data, could be key:value pairs collected on guest.

## AMD SEV-SNP

Expand Down
1 change: 0 additions & 1 deletion attestation-service/verifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,3 @@ assert-json-diff.workspace = true
rstest.workspace = true
serial_test.workspace = true
tokio.workspace = true

42 changes: 18 additions & 24 deletions attestation-service/verifier/src/se/ibmse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ fn list_files_in_folder(dir: &str) -> Result<Vec<String>> {
let mut file_paths = Vec::new();

for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();

let path = entry?.path();
if path.is_file() {
if let Some(path_str) = path.to_str() {
file_paths.push(path_str.to_string());
Expand All @@ -64,6 +62,7 @@ fn list_files_in_folder(dir: &str) -> Result<Vec<String>> {
Ok(file_paths)
}

#[repr(C)]
#[serde_as]
#[derive(Debug, Serialize, Deserialize)]
pub struct SeAttestationResponse {
Expand Down Expand Up @@ -100,6 +99,7 @@ pub struct SeAttestationClaims {
tag: [u8; 16],
}

#[repr(C)]
#[serde_as]
#[derive(Debug, Serialize, Deserialize)]
pub struct SeAttestationRequest {
Expand All @@ -116,12 +116,12 @@ pub struct SeAttestationRequest {
}

#[derive(Debug)]
pub struct RealSeVerifier {
pub struct VERIFIER {
rsa_private_key: PKey<Private>,
rsa_public_key: PKey<Public>,
}

impl RealSeVerifier {
impl VERIFIER {
pub fn new() -> Result<Self> {
let pri_key_file = env_or_default!(
"SE_MEASUREMENT_ENCR_KEY_PRIVATE",
Expand Down Expand Up @@ -150,23 +150,23 @@ impl RealSeVerifier {
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);
let mut decrypted = vec![0; buffer_len];
let decrypted_len = decrypter.decrypt(ciphertext, &mut decrypted)?;
decrypted.truncate(decrypted_len);

Ok(decrypted_hmac_key)
Ok(decrypted)
}

fn encrypt(&self, text: &[u8]) -> Result<Vec<u8>> {
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);
let mut encrypted = vec![0; buffer_len];
let len = encrypter.encrypt(text, &mut encrypted)?;
encrypted.truncate(len);

Ok(encrypted_hmac_key)
Ok(encrypted)
}

pub fn evaluate(&self, evidence: &[u8]) -> Result<TeeEvidenceParsedClaim> {
Expand All @@ -182,13 +182,9 @@ impl RealSeVerifier {
.decrypt(&se_response.encr_request_nonce)
.context("decrypt Request Nonce")?;

if nonce.len() != 16 {
bail!("The nonce vector must have exactly 16 elements.");
}

let nonce_array: [u8; 16] = nonce
.try_into()
.map_err(|_| anyhow!("Failed to convert nonce from Vec<u8> to [u8; 16]."))?;
.map_err(|_| anyhow!("Failed to convert nonce from Vec<u8> to [u8; 16], It must have exactly 16 elements."))?;

let meas_key = PKey::hmac(&meas_key)?;
let items = AttestationItems::new(
Expand All @@ -205,12 +201,9 @@ impl RealSeVerifier {
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();
Expand All @@ -223,8 +216,6 @@ impl RealSeVerifier {
.attestation_public_host_key_hash()
.ok_or(anyhow!("Failed to get attestation_public_host_key_hash."))?;

// TODO image_phkh and attestation_phkh with previous saved value

let claims = SeAttestationClaims {
cuid: se_response.cuid,
user_data: se_response.user_data.clone(),
Expand Down Expand Up @@ -253,10 +244,13 @@ impl RealSeVerifier {
let verifier =
CertVerifier::new(certs.as_slice(), crls.as_slice(), Some(root_ca_path), false)?;

let mut attestation_flags = AttestationFlags::default();
attestation_flags.set_image_phkh();
attestation_flags.set_attest_phkh();
let mut arcb = AttestationRequest::new(
AttestationVersion::One,
AttestationMeasAlg::HmacSha512,
AttestationFlags::default(),
attestation_flags,
)?;

let hkds_root = env_or_default!(
Expand Down
11 changes: 5 additions & 6 deletions attestation-service/verifier/src/se/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@

use anyhow::Result;
use async_trait::async_trait;
use ibmse::RealSeVerifier;
use log::warn;
use ibmse::VERIFIER;
use tokio::sync::OnceCell;

use crate::{InitDataHash, ReportData, TeeEvidenceParsedClaim, Verifier};

pub mod ibmse;

static ONCE: OnceCell<RealSeVerifier> = OnceCell::const_new();
static ONCE: OnceCell<VERIFIER> = OnceCell::const_new();

#[derive(Debug, Default)]
pub struct SeVerifier;
Expand All @@ -27,9 +26,9 @@ impl Verifier for SeVerifier {
_expected_init_data_hash: &InitDataHash,
) -> Result<TeeEvidenceParsedClaim> {
let se_verifier = ONCE
.get_or_try_init(|| async { RealSeVerifier::new() })
.get_or_try_init(|| async { VERIFIER::new() })
.await?;
warn!("IBM SE does not support initdata.");
// IBM SE does not support ReportData and InitDataHash so far.
se_verifier.evaluate(evidence)
}

Expand All @@ -38,7 +37,7 @@ impl Verifier for SeVerifier {
_tee_parameters: String,
) -> Result<String> {
let se_verifier = ONCE
.get_or_try_init(|| async { RealSeVerifier::new() })
.get_or_try_init(|| async { VERIFIER::new() })
.await?;
se_verifier.generate_supplemental_challenge(_tee_parameters).await
}
Expand Down
7 changes: 1 addition & 6 deletions kbs/src/api/src/attestation/coco/grpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,8 @@ impl Attest for GrpcClientPool {
async fn generate_challenge(&self, tee: Tee, tee_parameters: String) -> Result<Challenge> {
let nonce = match tee {
Tee::Se => {
let tee = serde_json::to_string(&tee)
.context("CoCo AS client: serialize tee type failed.")?
.trim_end_matches('"')
.trim_start_matches('"')
.to_string();
let mut inner = HashMap::new();
inner.insert(String::from("tee"), tee);
inner.insert(String::from("tee"), String::from("se"));
inner.insert(String::from("tee_params"), tee_parameters);
let req = tonic::Request::new(ChallengeRequest { inner });

Expand Down

0 comments on commit d503b63

Please sign in to comment.