From ff384032719379990745da7dcf7c625678d0ad1d Mon Sep 17 00:00:00 2001 From: Wojciech Ozga Date: Thu, 13 Feb 2025 20:20:28 +0100 Subject: [PATCH] Support ML-KEM for CoVE TAP (#81) * Add ML-KEM algorithm to TAP CoVE utils --------- Signed-off-by: Wojciech Ozga --- .../rust-crates/riscv_cove_tap/Cargo.toml | 8 +- .../rust-crates/riscv_cove_tap/src/error.rs | 10 ++- .../rust-crates/riscv_cove_tap/src/parser.rs | 55 +++++++----- .../riscv_cove_tap/src/serializer.rs | 21 +++-- .../rust-crates/riscv_cove_tap/src/spec.rs | 85 ++++++++++++++++++- .../promote_to_confidential_vm.rs | 9 +- tools/cove_tap_tool/src/generate.rs | 31 ++++--- 7 files changed, 172 insertions(+), 47 deletions(-) diff --git a/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml b/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml index 0815436..dd81f27 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml +++ b/security-monitor/rust-crates/riscv_cove_tap/Cargo.toml @@ -7,7 +7,11 @@ edition = "2021" [dependencies] #rsa = "0.9" # to create lockboxes: encrypt symetric key using public keys of target TEEs -#rand = "0.8" # to generate symmetric key used to encrypted payload + +rand = {version = "0.8", optional=true} + +hybrid-array = "=0.2.0-rc.9" +ml-kem = {version = "=0.2.0", default-features=false, features = [] } # for symmetric encryption of payload aes-gcm = {version="0.10.3", default-features = false, features=["aes", "alloc"]} @@ -17,4 +21,4 @@ thiserror-no-std = "2.0" [features] parser = [] -serializer = [] \ No newline at end of file +serializer = ["rand"] \ No newline at end of file diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/error.rs b/security-monitor/rust-crates/riscv_cove_tap/src/error.rs index 4b92ffd..a74e233 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/error.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/error.rs @@ -18,5 +18,13 @@ pub enum TapError { #[error("Invalid size of the TAP")] InvalidSize(), #[error("Aes error {0}")] - AesError(#[from] aes_gcm::Error) + AesError(#[from] aes_gcm::Error), + #[error("Key from slice error")] + KeyCreationError(#[from] core::array::TryFromSliceError), + #[error("KEM error")] + KemError(), + #[error("Could not find valid lockbox for this system")] + NoLockboxFound(), + #[error("Invalid size of TSK")] + InvalidTskSize(), } diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs b/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs index 39dbc99..cc732d6 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/parser.rs @@ -1,11 +1,10 @@ // SPDX-FileCopyrightText: 2023 IBM Corporation // SPDX-FileContributor: Wojciech Ozga , IBM Research - Zurich // SPDX-License-Identifier: Apache-2.0 - pub use crate::error::TapError; use alloc::vec::Vec; -use alloc::vec; use crate::spec::*; +use alloc::vec; pub struct AttestationPayloadParser { pub pointer: *const u8, @@ -19,7 +18,7 @@ impl AttestationPayloadParser { }) } - pub fn parse_and_verify(&mut self) -> Result { + pub fn parse_and_verify(&mut self, decapsulation_key: &Vec) -> Result { if self.read_u32()? != ACE_MAGIC_TAP_START { return Err(TapError::InvalidMagicStart()); } @@ -28,25 +27,42 @@ impl AttestationPayloadParser { // return Err(TapError::InvalidSize()); // } let number_of_lockboxes = self.read_u16()?; - let mut lockboxes = vec![]; + if usize::from(number_of_lockboxes) > MAX_NUMBER_OF_LOCKBOXES { + return Err(TapError::InvalidSize()); + } + + let mut symmetric_key = vec![]; for _ in 0..number_of_lockboxes { - let size = self.read_u16()? as usize; - let name = self.read_u64()?; + let _size = self.read_u16()? as usize; + // TODO: decide based on the lockbox name if this lockbox is intended for this device or not + let _name = self.read_u64()?; let algorithm = LockboxAlgorithm::from_u16(self.read_u16()?)?; - let value = self.read_exact(size-10)?; - lockboxes.push(Lockbox { - name, - algorithm, - value - }); + let esk_size = self.read_u16()? as usize; + let esk = self.read_exact(esk_size)?; + let nonce_size = self.read_u16()? as usize; + let nonce = self.read_exact(nonce_size)?; + let tag_size = self.read_u16()? as usize; + let tag = self.read_exact(tag_size)?; + let tsk_size = self.read_u16()? as usize; + let tsk = self.read_exact(tsk_size)?; + match algorithm.decode(decapsulation_key, esk, nonce, tag, tsk) { + Ok(mut tsk) => { + symmetric_key.append(&mut tsk); + break; + } + Err(e) => { + return Err(e) + } + }; + } + if symmetric_key.is_empty() { + return Err(TapError::NoLockboxFound()); } - // TODO: recover symmetric key - let symmetric_key = [0u8; 32]; let payload_encryption_algorithm = PayloadEncryptionAlgorithm::from_u16(self.read_u16()?)?; match payload_encryption_algorithm { PayloadEncryptionAlgorithm::Debug => {}, - PayloadEncryptionAlgorithm::AesGcm256 => self.decrypt_aes_gcm_256(symmetric_key)?, + PayloadEncryptionAlgorithm::AesGcm256 => self.decrypt_aes_gcm_256(&symmetric_key)?, } let number_of_digests = self.read_u16()?; @@ -73,13 +89,12 @@ impl AttestationPayloadParser { } Ok(AttestationPayload { - lockboxes, digests, secrets, }) } - fn decrypt_aes_gcm_256(&mut self, symmetric_key: [u8; 32]) -> Result<(), TapError> { + fn decrypt_aes_gcm_256(&mut self, symmetric_key: &Vec) -> Result<(), TapError> { use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Tag, Nonce}; let nonce_size = self.read_u16()? as usize; @@ -88,8 +103,10 @@ impl AttestationPayloadParser { let tag = self.read_exact(tag_size)?; let payload_size = self.read_u16()? as usize; - let key: Key = symmetric_key.into(); - let cipher = Aes256Gcm::new(&key); + if symmetric_key.len() != 32 { + return Err(TapError::InvalidTskSize()); + } + let cipher = Aes256Gcm::new(Key::::from_slice(symmetric_key.as_slice())); let nonce = Nonce::from_slice(&nonce); let tag = Tag::from_slice(&tag); let mut data_slice = unsafe{ core::slice::from_raw_parts_mut(self.pointer as *mut u8, payload_size) }; diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs b/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs index 43297ef..892a525 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs @@ -15,11 +15,11 @@ impl AttestationPayloadSerializer { Self {} } - pub fn serialize(&self, mut payload: AttestationPayload) -> Result, TapError> { + pub fn serialize(&self, lockboxes: Vec, mut payload: AttestationPayload) -> Result, TapError> { let digests = self.serialize_digests(&mut payload)?; let secrets = self.serialize_secrets(&mut payload)?; let mut encrypted_part = self.encrypt_aes_gcm_256(digests, secrets)?; - let mut lockboxes = self.serialize_lockboxes(&mut payload)?; + let mut lockboxes = self.serialize_lockboxes(lockboxes)?; let total_size = lockboxes.len() + encrypted_part.len(); @@ -32,16 +32,23 @@ impl AttestationPayloadSerializer { Ok(result) } - fn serialize_lockboxes(&self, payload: &mut AttestationPayload) -> Result, TapError> { + fn serialize_lockboxes(&self, mut lockboxes: Vec) -> Result, TapError> { // TODO: sanity check: lockboxes < 1024 let mut result = vec![]; - result.append(&mut (payload.lockboxes.len() as u16).to_le_bytes().to_vec()); - for mut lockbox in payload.lockboxes.drain(..) { - let entry_size = lockbox.value.len() + 10; + result.append(&mut (lockboxes.len() as u16).to_le_bytes().to_vec()); + for mut lockbox in lockboxes.drain(..) { + let entry_size = lockbox.esk.len() + lockbox.nonce.len() + lockbox.tag.len() + lockbox.tsk.len() + 18; result.append(&mut (entry_size as u16).to_le_bytes().to_vec()); result.append(&mut (lockbox.name as u64).to_le_bytes().to_vec()); result.append(&mut (lockbox.algorithm as u16).to_le_bytes().to_vec()); - result.append(&mut lockbox.value); + result.append(&mut (lockbox.esk.len() as u16).to_le_bytes().to_vec()); + result.append(&mut lockbox.esk); + result.append(&mut (lockbox.nonce.len() as u16).to_le_bytes().to_vec()); + result.append(&mut lockbox.nonce); + result.append(&mut (lockbox.tag.len() as u16).to_le_bytes().to_vec()); + result.append(&mut lockbox.tag); + result.append(&mut (lockbox.tsk.len() as u16).to_le_bytes().to_vec()); + result.append(&mut lockbox.tsk); } Ok(result) } diff --git a/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs b/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs index 6538be0..f73c913 100644 --- a/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs +++ b/security-monitor/rust-crates/riscv_cove_tap/src/spec.rs @@ -9,9 +9,9 @@ pub const ACE_FOOTER_SIZE: usize = 8; pub const ACE_MAGIC_TAP_START: u32 = 0xACE0ACE0; pub const ACE_MAGIC_TAP_END: u32 = 0xACE1ACE1; pub const ACE_MAX_TAP_SIZE: usize = 4096; // size of the 4KiB page +pub const MAX_NUMBER_OF_LOCKBOXES: usize = 1024; pub struct AttestationPayload { - pub lockboxes: Vec, pub digests: Vec, pub secrets: Vec, } @@ -19,24 +19,101 @@ pub struct AttestationPayload { pub struct Lockbox { pub name: u64, pub algorithm: LockboxAlgorithm, - pub value: Vec, + pub esk: Vec, + pub nonce: Vec, + pub tag: Vec, + pub tsk: Vec +} + +impl Lockbox { + #[cfg(feature = "serializer")] + pub fn new(lockbox_algorithm: LockboxAlgorithm, encapsulation_key: &Vec, tsk: &Vec) -> Result { + let (esk, nonce, tag, tsk) = lockbox_algorithm.encode(encapsulation_key, tsk)?; + Ok(Self { + name: 0, + algorithm: lockbox_algorithm, + esk, + nonce, + tag, + tsk + }) + } } #[repr(u16)] #[derive(Debug)] pub enum LockboxAlgorithm { Debug = 0, - Rsa2048Sha256Oasp = 1, + MlKem1024Aes256 = 1, } impl LockboxAlgorithm { pub fn from_u16(value: u16) -> Result { match value { 0 => Ok(Self::Debug), - 1 => Ok(Self::Rsa2048Sha256Oasp), + 1 => Ok(Self::MlKem1024Aes256), v => Err(TapError::UnsupportedLockboxAlgorithm(v)), } } + + #[cfg(feature = "serializer")] + pub fn encode(&self, encapsulation_key: &Vec, tsk: &Vec) -> Result<(Vec, Vec, Vec, Vec), TapError> { + use alloc::vec; + match self { + LockboxAlgorithm::Debug => { + Ok((vec![], vec![], vec![], tsk.to_vec())) + } + LockboxAlgorithm::MlKem1024Aes256 => { + use rand::rngs::OsRng; + use ml_kem::{MlKem1024, KemCore, MlKem1024Params, Encoded, EncodedSizeUser, kem::{Encapsulate, EncapsulationKey}}; + + let ek_bytes = Encoded::>::try_from(encapsulation_key.as_slice())?; + let ek = ::EncapsulationKey::from_bytes(&ek_bytes); + let (esk, aes_key) = match ek.encapsulate(&mut OsRng) { + Ok(v) => v, + Err(_) => return Err(TapError::KemError()) + }; + + use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, AeadCore}; + let mut tsk = tsk.to_vec(); + let key: &Key = Key::::from_slice(aes_key.as_slice()); + let cipher = Aes256Gcm::new(&key); + let nonce = Aes256Gcm::generate_nonce(&mut OsRng); + let nonce = aes_gcm::Nonce::from_slice(&nonce); + let tag = cipher.encrypt_in_place_detached(&nonce, b"", &mut tsk)?; + + Ok((esk.to_vec(), nonce.as_slice().to_vec(), tag.as_slice().to_vec(), tsk)) + } + } + } + + #[cfg(feature = "parser")] + pub fn decode(&self, decapsulation_key: &Vec, esk: Vec, nonce: Vec, tag: Vec, mut tsk: Vec) -> Result, TapError> { + match self { + LockboxAlgorithm::Debug => { + Ok(tsk) + }, + LockboxAlgorithm::MlKem1024Aes256 => { + use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Tag, Nonce}; + use hybrid_array::Array; + use ml_kem::{MlKem1024, KemCore, MlKem1024Params, Encoded, EncodedSizeUser,kem::{Decapsulate, DecapsulationKey}}; + + let m = Array::try_from(esk.as_slice())?; + let dk_bytes = Encoded::>::try_from(decapsulation_key.as_slice())?; + let dk = ::DecapsulationKey::from_bytes(&dk_bytes); + let sk = match dk.decapsulate(&m) { + Ok(v) => v, + Err(_) => return Err(TapError::KemError()) + }; + + let cipher = Aes256Gcm::new(Key::::from_slice(sk.as_slice())); + let nonce = Nonce::from_slice(&nonce); + let tag = Tag::from_slice(&tag); + cipher.decrypt_in_place_detached(nonce, b"", &mut tsk, &tag).unwrap(); + Ok(tsk) + } + } + } } pub struct Digest { diff --git a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs index e4b62de..a9969d3 100644 --- a/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs +++ b/security-monitor/src/non_confidential_flow/handlers/cove_host_extension/promote_to_confidential_vm.rs @@ -168,9 +168,14 @@ impl PromoteToConfidentialVm { // that fit within 2MiB ensure!(total_size.div_ceil(PageSize::Size2MiB.in_bytes()) == 1, Error::AuthBlobInvalidSize())?; let large_page = Self::relocate(memory_protector, &attestation_payload_address, total_size, true)?; - // TODO: we should parse to the blob key that will allow to unlock the lockbox. + // TODO: replace the hardcoded decapsulation key with a key or interface to device-specific decapsulation key + let test_decapsulation_key = "673751CBB596541131C66398662CB4B0EB80796A88B28144A5BBC854F80D4B35BE0AB241E4795F8FBBA814F50FA80498CBE8BF68A0A583A4C5981B41DF0667DB614A628C3060697438E62C8D36026EE29C96B673BF1A194EE49481351F4D1748DD01CD023142F01057142B741CBA8302E432F88C63D0B4B5767AC3A5A59AFA3A321E65B1D1511807A06E16A04B2F1070E465586D4A9B68E2B42D57A356FA7BB3D04E51B193FF4C757CFA0F15924EA6E49AFB83B2919C985869ADA544338F44AE96A874C425AF87BC73F3CB0FD2627B1539B1F19A77E36B7FC817851D39BD8A069A6C2202C17469D421A588E65DAF450030B6674EC1C734AA25414B119E61B26EFC90DF81059D2B9599414F93692BF45A4B1C5CC09EDB37B1B1433026AEA6B0200722B819C7BC061C53A4304992FCA2AEE2324A324AB91C3E5D562096B8A141756940F15A2800C274EA4F65817E639C5D2A278C6A294F9DB331F84CCB0A10309F530A06EB962573C86005C15BFC7531A143026396721297E25CB655A294964B2FE531905F2802376B8ACE35AE3E2814BAB7062BC1A840657DBFCB5F41BB55475697849A31E2222E995518CA7640AD4B9CEE9820984138BE0510FFD6AC225393A5F0CB030528CD2A0610E78A5CF1B073039A6D143068C53DBD15A1D4446DA7B310EE795D1FB31B2F97008F83BDF348A593A3BDCBB571907B36D0978162C253E6F50106C463149834ABFB0707D8AB4A4BABC323598A085B309764B7C32C9DB0C9F2D52EF2F00BACE7846868C33B82AFA430A4C2F67B698A60526A161CD62115DCA767C203E3E2CC787031A73B5B7DBA1EEE5AB04B77BB569B952D9A15D198779804197D23C18E5B055F5C8087D742F64418D6505E70418ABFC6B1BF7BB3DE286599F4676CF87946D65144998AFAE1C689449E3F349FD0809AFB856DDE4A94A2C0258D56432F40C3DA812D3FD3B72259A61D2882E0F50B355121E564C6BD33366F32BF4A5996B9998961354925A2BACDF48056118453AC3792A7879B71579ADB65F5D83B1ED6C8C49836DE379DAA027E62B96F683C1688935CB3FCCD64329267273E60C6CD59BA1B7FC911E2662527ECCB7A474E5EF00CA9F789A3838E889242E7FB2B08F3790613C4EED3C912EC4EB029B971096B384727697B4DDC3B698C9A6DA6971FA4C574ECD18EB1C84C0C5790153AA6B9DB61D8BAC0A680A37ED623582A7E8C0885EBB35AF341477764368E0647B14553672316D0B90317C5B53AA747E61B4750DB9E63CC3712900005CA24226B523E0A179582C85968C107857BB41521B7342B13DCAC462A53BE38446F2142519667B48B1C68FCAFA4D3C7E3E5AFF163C41F2C1B4DBAC5456C30776078E7C3A713819F6B9ACA55D77D60637183A723035730F94285C42AC3587637F66AC30F2C4039E60420967576E27B96C8C004D9585F33939AC44F0D195B35D472FC219076F12D0984AC844728D5D2266BB5CD8B325DDA497B4F397BFE722C9D7684201A921F502271985CB3F31C04884C090B063631253DC454537031F2C82C10A1722DE6C556464DC9D64389DA37E469480C921065C79A30C83C867C952B30548A6B5BDFEB6EA6247480F163B427B17CF94889220FE934564DAB90F5B6A11648870B654495A6691AE21FEA86BDC8C49093FA07E926AF3ABA0E7CEC21F613B49986C6C8A139EDA70B7ED8211A3215E8C43EF8C151AE61740EF83B48276033614B58E9CEB992233CD21DFF70C7A6F7171707A2ADD37ACBF136A4EB4A79517FD0C8AFF0B5126435C3100331F208A546C9A4044A8F0503C8ADE9506A018B4CA7C6E8D70120017D38B13B52786A85A540D81B8E71C376B796A7215ABF065086D3C80EE94B8F09E2A3BA13B82583B825388E87BA010AF507173563789A1DCD088907C52BD7FC1C6930605F060F37978211C10FB5717E3FA291D20B5D43FB74CD4711394B0027E41C52B523797470532CBE123C92950720E5E255256577D4E156EBD4C698D813405C61430B978694ACDE78031E74BA1D8517DAE2346F008411231FCCE7BFF75BC361E691E776049004097B36490D876288701B2D3A1743AB8753D47AC6200E2DA7458D3A059681233872794E6720186B20108B1D1033971CE19ED67A2A28E499A360A4AD86AE4194034F202F8FA3626FE75F307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983D48BA34134BAB88D635D8CF8FF5D686058FA68B6C2FEEAA5FA4DE65757086C0125E937BCC0D02FAA8988AE7169DF07F6A771E6E7FE3AB65E965C63C3E40ED909"; + let decapsulation_key = (0..test_decapsulation_key.len()) + .step_by(2) + .map(|i| test_decapsulation_key.get(i..i + 2).and_then(|sub| u8::from_str_radix(sub, 16).ok()).unwrap()) + .collect(); let mut parser = unsafe { AttestationPayloadParser::from_raw_pointer(large_page.address().to_ptr(), total_size)? }; - let attestation_payload = parser.parse_and_verify()?; + let attestation_payload = parser.parse_and_verify(&decapsulation_key)?; // Clean up, deallocate pages PageAllocator::release_pages(alloc::vec![large_page.deallocate()]); Ok(Some(attestation_payload)) diff --git a/tools/cove_tap_tool/src/generate.rs b/tools/cove_tap_tool/src/generate.rs index b69f7ef..f76f369 100644 --- a/tools/cove_tap_tool/src/generate.rs +++ b/tools/cove_tap_tool/src/generate.rs @@ -28,14 +28,25 @@ pub fn generate_tap( Error::InvalidParameter(format!("Confidential VM TAP supports max 1024 lockboxes")) )?; - // let symmetric_key = [0u8; 32]; + let symmetric_key = vec![0u8; 32]; + let lockbox_algorithm = LockboxAlgorithm::MlKem1024Aes256; + let test_encapsulation_key = "307A4CEA4148219B958EA0B7886659235A4D1980B192610847D86EF32739F94C3B446C4D81D89B8B422A9D079C88B11ACAF321B014294E18B296E52F3F744CF9634A4FB01DB0D99EF20A633A552E76A0585C6109F018768B763AF3678B4780089C1342B96907A29A1C11521C744C2797D0BF2B9CCDCA614672B45076773F458A31EF869BE1EB2EFEB50D0E37495DC5CA55E07528934F6293C4168027D0E53D07FACC6630CB08197E53FB193A171135DC8AD9979402A71B6926BCDCDC47B93401910A5FCC1A813B682B09BA7A72D2486D6C799516465C14729B26949B0B7CBC7C640F267FED80B162C51FD8E09227C101D505A8FAE8A2D7054E28A78BA8750DECF9057C83979F7ABB084945648006C5B28804F34E73B238111A65A1F500B1CC606A848F2859070BEBA7573179F36149CF5801BF89A1C38CC278415528D03BDB943F96280C8CC52042D9B91FAA9D6EA7BCBB7AB1897A3266966F78393426C76D8A49578B98B159EBB46EE0A883A270D8057CD0231C86906A91DBBADE6B2469581E2BCA2FEA8389F7C74BCD70961EA5B934FBCF9A6590BF86B8DB548854D9A3FB30110433BD7A1B659CA8568085639237B3BDC37B7FA716D482A25B54106B3A8F54D3AA99B5123DA96066904592F3A54EE23A7981AB608A2F4413CC658946C6D7780EA765644B3CC06C70034AB4EB351912E7715B56755D09021571BF340AB92598A24E811893195B96A1629F8041F58658431561FC0AB15292B913EC473F04479BC145CD4C563A286235646CD305A9BE1014E2C7B130C33EB77CC4A0D9786BD6BC2A954BF3005778F8917CE13789BBB962807858B67731572B6D3C9B4B5206FAC9A7C8961698D88324A915186899B29923F08442A3D386BD416BCC9A100164C930EC35EAFB6AB35851B6C8CE6377366A175F3D75298C518D44898933F53DEE617145093379C4659F68583B2B28122666BEC57838991FF16C368DD22C36E780C91A3582E25E19794C6BF2AB42458A8DD7705DE2C2AA20C054E84B3EF35032798626C248263253A71A11943571340A978CD0A602E47DEE540A8814BA06F31414797CDF6049582361BBABA387A83D89913FE4C0C112B95621A4BDA8123A14D1A842FB57B83A4FBAF33A8E552238A596AAE7A150D75DA648BC44644977BA1F87A4C68A8C4BD245B7D00721F7D64E822B085B901312EC37A8169802160CCE1160F010BE8CBCACE8E7B005D7839234A707868309D03784B4273B1C8A160133ED298184704625F29CFA086D13263EE5899123C596BA788E5C54A8E9BA829B8A9D904BC4BC0BBEA76BC53FF811214598472C9C202B73EFF035DC09703AF7BF1BABAAC73193CB46117A7C9492A43FC95789A924C5912787B2E2090EBBCFD3796221F06DEBF9CF70E056B8B9161D6347F47335F3E1776DA4BB87C15CC826146FF0249A413B45AA93A805196EA453114B524E310AEDAA46E3B99642368782566D049A726D6CCA910993AED621D0149EA588A9ABD909DBB69AA22829D9B83ADA2209A6C2659F2169D668B9314842C6E22A74958B4C25BBDCD293D99CB609D866749A485DFB56024883CF5465DBA0363206587F45597F89002FB8607232138E03B2A894525F265370054B48863614472B95D0A2303442E378B0DD1C75ACBAB971A9A8D1281C79613ACEC6933C377B3C578C2A61A1EC181B101297A37CC5197B2942F6A0E4704C0EC63540481B9F159DC255B59BB55DF496AE54217B7689BD51DBA0383A3D72D852FFCA76DF05B66EECCBD47BC53040817628C71E361D6AF889084916B408A466C96E7086C4A60A10FCF7537BB94AFBCC7D437590919C28650C4F2368259226A9BFDA3A3A0BA1B5087D9D76442FD786C6F81C68C0360D7194D7072C4533AEA86C2D1F8C0A27696066F6CFD11003F797270B32389713CFFA093D991B63844C385E72277F166F5A3934D6BB89A4788DE28321DEFC7457AB484BD30986DC1DAB3008CD7B22F69702FABB9A1045407DA4791C3590FF599D81D688CFA7CC12A68C50F51A1009411B44850F9015DC84A93B17C7A207552C661EA9838E31B95EAD546248E56BE7A5130505268771199880A141771A9E47ACFED590CB3AA7CB7C5F74911D8912C29D6233F4D53BC64139E2F55BE75507DD77868E384AEC581F3F411DB1A742972D3EBFD3315C84A5AD63A0E75C8BCA3E3041E05D9067AFF3B1244F763E7983"; + let encapsulation_key = (0..test_encapsulation_key.len()) + .step_by(2) + .map(|i| { + test_encapsulation_key + .get(i..i + 2) + .and_then(|sub| u8::from_str_radix(sub, 16).ok()) + .unwrap() + }) + .collect(); let mut lockboxes = vec![]; - lockboxes.push(Lockbox { - name: 0u64, - algorithm: LockboxAlgorithm::Debug, - value: [0xFF; 16].to_vec(), - }); + lockboxes.push(Lockbox::new( + lockbox_algorithm, + &encapsulation_key, + &symmetric_key, + )?); let mut digests = vec![]; for (pcr_id, pcr_value) in pcrs.into_iter() { @@ -58,14 +69,10 @@ pub fn generate_tap( secrets.push(secret); } - let tap = AttestationPayload { - lockboxes, - digests, - secrets, - }; + let tap = AttestationPayload { digests, secrets }; let serializer = AttestationPayloadSerializer::new(); - let serialized = serializer.serialize(tap)?; + let serialized = serializer.serialize(lockboxes, tap)?; // write the entire TAP to the output file let mut output = OpenOptions::new()