Skip to content

Commit

Permalink
Support ML-KEM for CoVE TAP (#81)
Browse files Browse the repository at this point in the history
* Add ML-KEM algorithm to TAP CoVE utils

---------

Signed-off-by: Wojciech Ozga <woz@zurich.ibm.com>
  • Loading branch information
wojciechozga authored Feb 13, 2025
1 parent 80e7cd1 commit ff38403
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 47 deletions.
8 changes: 6 additions & 2 deletions security-monitor/rust-crates/riscv_cove_tap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]}
Expand All @@ -17,4 +21,4 @@ thiserror-no-std = "2.0"

[features]
parser = []
serializer = []
serializer = ["rand"]
10 changes: 9 additions & 1 deletion security-monitor/rust-crates/riscv_cove_tap/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
}
55 changes: 36 additions & 19 deletions security-monitor/rust-crates/riscv_cove_tap/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// SPDX-FileCopyrightText: 2023 IBM Corporation
// SPDX-FileContributor: Wojciech Ozga <woz@zurich.ibm.com>, 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,
Expand All @@ -19,7 +18,7 @@ impl AttestationPayloadParser {
})
}

pub fn parse_and_verify(&mut self) -> Result<AttestationPayload, TapError> {
pub fn parse_and_verify(&mut self, decapsulation_key: &Vec<u8>) -> Result<AttestationPayload, TapError> {
if self.read_u32()? != ACE_MAGIC_TAP_START {
return Err(TapError::InvalidMagicStart());
}
Expand All @@ -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()?;
Expand All @@ -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<u8>) -> Result<(), TapError> {
use aes_gcm::{AeadInPlace, Aes256Gcm, Key, KeyInit, Tag, Nonce};

let nonce_size = self.read_u16()? as usize;
Expand All @@ -88,8 +103,10 @@ impl AttestationPayloadParser {
let tag = self.read_exact(tag_size)?;
let payload_size = self.read_u16()? as usize;

let key: Key<Aes256Gcm> = symmetric_key.into();
let cipher = Aes256Gcm::new(&key);
if symmetric_key.len() != 32 {
return Err(TapError::InvalidTskSize());
}
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::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) };
Expand Down
21 changes: 14 additions & 7 deletions security-monitor/rust-crates/riscv_cove_tap/src/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ impl AttestationPayloadSerializer {
Self {}
}

pub fn serialize(&self, mut payload: AttestationPayload) -> Result<Vec<u8>, TapError> {
pub fn serialize(&self, lockboxes: Vec<Lockbox>, mut payload: AttestationPayload) -> Result<Vec<u8>, 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();

Expand All @@ -32,16 +32,23 @@ impl AttestationPayloadSerializer {
Ok(result)
}

fn serialize_lockboxes(&self, payload: &mut AttestationPayload) -> Result<Vec<u8>, TapError> {
fn serialize_lockboxes(&self, mut lockboxes: Vec<Lockbox>) -> Result<Vec<u8>, 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)
}
Expand Down
85 changes: 81 additions & 4 deletions security-monitor/rust-crates/riscv_cove_tap/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,111 @@ 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<Lockbox>,
pub digests: Vec<Digest>,
pub secrets: Vec<Secret>,
}

pub struct Lockbox {
pub name: u64,
pub algorithm: LockboxAlgorithm,
pub value: Vec<u8>,
pub esk: Vec<u8>,
pub nonce: Vec<u8>,
pub tag: Vec<u8>,
pub tsk: Vec<u8>
}

impl Lockbox {
#[cfg(feature = "serializer")]
pub fn new(lockbox_algorithm: LockboxAlgorithm, encapsulation_key: &Vec<u8>, tsk: &Vec<u8>) -> Result<Self, TapError> {
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<Self, TapError> {
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<u8>, tsk: &Vec<u8>) -> Result<(Vec<u8>, Vec<u8>, Vec<u8>, Vec<u8>), 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::<EncapsulationKey::<MlKem1024Params>>::try_from(encapsulation_key.as_slice())?;
let ek = <MlKem1024 as KemCore>::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<Aes256Gcm> = Key::<Aes256Gcm>::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<u8>, esk: Vec<u8>, nonce: Vec<u8>, tag: Vec<u8>, mut tsk: Vec<u8>) -> Result<Vec<u8>, 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::<DecapsulationKey::<MlKem1024Params>>::try_from(decapsulation_key.as_slice())?;
let dk = <MlKem1024 as KemCore>::DecapsulationKey::from_bytes(&dk_bytes);
let sk = match dk.decapsulate(&m) {
Ok(v) => v,
Err(_) => return Err(TapError::KemError())
};

let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Loading

0 comments on commit ff38403

Please sign in to comment.