Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions openhcl/openhcl_attestation_protocol/src/igvm_attest/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,17 @@ pub mod runtime_claims {
}
}

/// Supported hardware sealing policy
#[derive(Clone, Copy, Debug, Deserialize, Serialize, MeshPayload)]
pub enum HardwareSealingPolicy {
#[serde(rename = "none")]
None,
#[serde(rename = "hash")]
Hash,
#[serde(rename = "signer")]
Signer,
}

/// VM configuration to be included in the `RuntimeClaims`.
#[derive(Clone, Debug, Deserialize, Serialize, MeshPayload)]
#[serde(rename_all = "kebab-case")]
Expand All @@ -441,6 +452,8 @@ pub mod runtime_claims {
pub tpm_enabled: bool,
/// Whether the TPM states is persisted
pub tpm_persisted: bool,
/// Hardware sealing policy
pub hardware_sealing_policy: HardwareSealingPolicy,
/// Whether certain vPCI devices are allowed through the device filter
pub filtered_vpci_devices_allowed: bool,
/// VM id
Expand Down
42 changes: 32 additions & 10 deletions openhcl/openhcl_attestation_protocol/src/vmgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,14 @@ pub struct SecurityProfile {
pub agent_data: [u8; AGENT_DATA_MAX_SIZE],
}

/// The header, IV, and last 256 bits of HMAC are fixed for this version.
/// The ciphertext is allowed to grow, though secrets should stay
/// in the same position to allow downlevel versions to continue to understand
/// that portion of the data.
pub const HW_KEY_VERSION: u32 = 1; // using AES-CBC-HMAC-SHA256
/// VMGS hardware key protector entry that includes the metadata of
/// local hardware sealing with AES-CBC-HMAC-SHA256.
///
/// Version 1 is incompatible with newer versions.
/// Version 2 or newer is forward-compatible if header.mix_measurement is not set.
pub const HW_KEY_PROTECTOR_VERSION_1: u32 = 1;
pub const HW_KEY_PROTECTOR_VERSION_2: u32 = 2;
pub const HW_KEY_PROTECTOR_CURRENT_VERSION: u32 = HW_KEY_PROTECTOR_VERSION_2;

/// The size of the `FileId::HW_KEY_PROTECTOR` entry in the VMGS file.
pub const HW_KEY_PROTECTOR_SIZE: usize = size_of::<HardwareKeyProtector>();
Expand All @@ -105,18 +108,22 @@ pub struct HardwareKeyProtectorHeader {
pub length: u32,
/// TCB version obtained from the hardware
pub tcb_version: u64,
/// Reserved
pub _reserved: [u8; 8],
/// Whether to mix the measurement in hardware key derivation
/// Only supported in version 2 and above
pub mix_measurement: u8,
/// Reserved bytes for future use
pub _reserved: [u8; 7],
}

impl HardwareKeyProtectorHeader {
/// Create a `HardwareKeyProtectorHeader` instance.
pub fn new(version: u32, length: u32, tcb_version: u64) -> Self {
pub fn new(version: u32, length: u32, tcb_version: u64, mix_measurement: u8) -> Self {
Self {
version,
length,
tcb_version,
_reserved: [0u8; 8],
mix_measurement,
_reserved: [0; 7],
}
}
}
Expand All @@ -131,7 +138,7 @@ pub struct HardwareKeyProtector {
pub iv: [u8; AES_CBC_IV_LENGTH],
/// Encrypted key
pub ciphertext: [u8; AES_GCM_KEY_LENGTH],
/// HMAC-SHA-256 of [`header`, `iv`, `ciphertext`]
/// HMAC-SHA-256 of [header, iv, ciphertext]
pub hmac: [u8; HMAC_SHA_256_KEY_LENGTH],
}

Expand All @@ -145,3 +152,18 @@ pub struct GuestSecretKey {
/// the guest secret key to be provisioned to vTPM
pub guest_secret_key: [u8; GUEST_SECRET_KEY_MAX_SIZE],
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn hardware_key_protector_header_new() {
let h = HardwareKeyProtectorHeader::new(2, 104, 0x1234, 1);
assert_eq!(h.version, 2);
assert_eq!(h.length, 104);
assert_eq!(h.tcb_version, 0x1234);
assert_eq!(h.mix_measurement, 1);
assert_eq!(h._reserved, [0; 7]);
}
}
1 change: 1 addition & 0 deletions openhcl/tee_call/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ x86defs.workspace = true
static_assertions.workspace = true
thiserror.workspace = true
zerocopy.workspace = true

[lints]
workspace = true
34 changes: 29 additions & 5 deletions openhcl/tee_call/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,23 @@ pub struct GetAttestationReportResult {
pub tcb_version: Option<u64>,
}

/// Key derivation policy
#[derive(Debug, Clone, Copy)]
pub struct KeyDerivationPolicy {
/// The TCB version to use for key derivation.
pub tcb_version: u64,
/// Whether to mix measurement into the key derivation.
pub mix_measurement: bool,
}

/// Trait that defines the get attestation report interface for TEE.
// TODO VBS: Implement the trait for VBS
pub trait TeeCall: Send + Sync {
/// Get the hardware-backed attestation report.
///
/// # Arguments
/// * `report_data` - The report data to include in the attestation report.
///
/// Returns the attestation report result.
fn get_attestation_report(
&self,
report_data: &[u8; REPORT_DATA_SIZE],
Expand All @@ -80,10 +93,18 @@ pub trait TeeCall: Send + Sync {
}

/// Optional sub-trait that defines get derived key interface for TEE.
///
/// # Arguments
/// * `policy` - The key derivation policy to use.
///
/// Returns the derived key.
pub trait TeeCallGetDerivedKey: TeeCall {
/// Get the derived key that should be deterministic based on the hardware and software
/// configurations.
fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; HW_DERIVED_KEY_LENGTH], Error>;
fn get_derived_key(
&self,
policy: KeyDerivationPolicy,
) -> Result<[u8; HW_DERIVED_KEY_LENGTH], Error>;
}

/// Implementation of [`TeeCall`] for SNP
Expand Down Expand Up @@ -119,7 +140,10 @@ impl TeeCall for SnpCall {

impl TeeCallGetDerivedKey for SnpCall {
/// Get the derived key from /dev/sev-guest.
fn get_derived_key(&self, tcb_version: u64) -> Result<[u8; HW_DERIVED_KEY_LENGTH], Error> {
fn get_derived_key(
&self,
policy: KeyDerivationPolicy,
) -> Result<[u8; HW_DERIVED_KEY_LENGTH], Error> {
let dev = sev_guest_device::SevGuestDevice::open().map_err(Error::OpenDevSevGuest)?;

// Derive a key mixing in following data:
Expand All @@ -128,7 +152,7 @@ impl TeeCallGetDerivedKey for SnpCall {
// - TcbVersion (do not derive same key on older TCB that might have a bug)
let guest_field_select = x86defs::snp::GuestFieldSelect::default()
.with_guest_policy(true)
.with_measurement(true)
.with_measurement(policy.mix_measurement)
.with_tcb_version(true);

let derived_key = dev
Expand All @@ -137,7 +161,7 @@ impl TeeCallGetDerivedKey for SnpCall {
guest_field_select.into(),
0, // VMPL 0
0, // default guest svn to 0
tcb_version,
policy.tcb_version,
)
.map_err(Error::GetSnpDerivedKey)?;

Expand Down
Loading
Loading