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 3d555dc
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 53 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

69 changes: 32 additions & 37 deletions attestation-service/verifier/src/se/ibmse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ use crate::TeeEvidenceParsedClaim;
use anyhow::{anyhow, bail, Context, Result};
use core::result::Result::Ok;
use log::{debug, info, warn};
use openssl::ec::EcKey;
use openssl::encrypt::{Decrypter, Encrypter};
use openssl::pkey::{PKey, Private, Public};
use openssl::rsa::{Padding, Rsa};
use openssl::rsa::Padding;
use pv::attest::{
AdditionalData, AttestationFlags, AttestationItems, AttestationMeasAlg, AttestationMeasurement,
AttestationRequest, AttestationVersion,
Expand All @@ -33,10 +34,10 @@ const DEFAULT_SE_CERTIFICATE_REVOCATION_LISTS_ROOT: &str =
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";
"/run/confidential-containers/ibmse/ec/encrypt_key.pem";

const DEFAULT_SE_MEASUREMENT_ENCR_KEY_PUBLIC: &str =
"/run/confidential-containers/ibmse/rsa/encrypt_key.pub";
"/run/confidential-containers/ibmse/ec/encrypt_key.pub";

macro_rules! env_or_default {
($env:literal, $default:ident) => {
Expand All @@ -51,9 +52,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 +63,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 +100,7 @@ pub struct SeAttestationClaims {
tag: [u8; 16],
}

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

#[derive(Debug)]
pub struct RealSeVerifier {
rsa_private_key: PKey<Private>,
rsa_public_key: PKey<Public>,
pub struct VERIFIER {
private_key: PKey<Private>,
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",
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 private_key = EcKey::private_key_from_pem(&priv_contents)?;
let private_key = PKey::from_ec_key(private_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)?;
let rsa = EcKey::public_key_from_pem(&pub_contents)?;
let public_key = PKey::from_ec_key(rsa)?;

Ok(Self {
rsa_private_key,
rsa_public_key,
private_key,
public_key,
})
}

fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>> {
let mut decrypter = Decrypter::new(&self.rsa_private_key)?;
let mut decrypter = Decrypter::new(&self.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);
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)?;
let mut encrypter = Encrypter::new(&self.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 +183,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 +202,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 +217,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 +245,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 3d555dc

Please sign in to comment.