diff --git a/Cargo.lock b/Cargo.lock index c73a590f24..8dd3534e60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13160,6 +13160,7 @@ name = "sgx-api-lite" version = "0.1.0" dependencies = [ "aes 0.8.1", + "bitflags 2.0.2", "cmac", ] diff --git a/crates/phactory/api/proto b/crates/phactory/api/proto index 8c1b23f60b..da0b252238 160000 --- a/crates/phactory/api/proto +++ b/crates/phactory/api/proto @@ -1 +1 @@ -Subproject commit 8c1b23f60bfba5b33d11d7223dfcbe9a0ef76501 +Subproject commit da0b25223851b2b0be6eef765a7a315b65ac9028 diff --git a/crates/phactory/pal/src/lib.rs b/crates/phactory/pal/src/lib.rs index 1479eba5f8..fedd6b0dff 100644 --- a/crates/phactory/pal/src/lib.rs +++ b/crates/phactory/pal/src/lib.rs @@ -1,8 +1,8 @@ //! Platform abstraction layer for Trusted Execution Environments +use core::time::Duration; use std::fmt::Debug; use std::path::Path; -use core::time::Duration; use phala_types::AttestationProvider; @@ -11,12 +11,26 @@ pub use phactory_api::prpc::MemoryUsage; pub trait ErrorType: Debug + Into {} impl> ErrorType for T {} +pub struct UnsealedData { + pub data: Vec, + pub svn: Vec, +} + pub trait Sealing { type SealError: ErrorType; type UnsealError: ErrorType; - fn seal_data(&self, path: impl AsRef, data: &[u8]) -> Result<(), Self::SealError>; - fn unseal_data(&self, path: impl AsRef) -> Result>, Self::UnsealError>; + fn current_svn(&self) -> Result, Self::SealError>; + fn seal_data( + &self, + path: impl AsRef, + data: &[u8], + svn: Option<&[u8]>, + ) -> Result<(), Self::SealError>; + fn unseal_data( + &self, + path: impl AsRef, + ) -> Result, Self::UnsealError>; } pub trait RA { diff --git a/crates/phactory/src/lib.rs b/crates/phactory/src/lib.rs index ffd9df0c7c..0776cafe6b 100644 --- a/crates/phactory/src/lib.rs +++ b/crates/phactory/src/lib.rs @@ -338,14 +338,21 @@ impl Phactory { predefined_identity_key: Option, ) -> Result { let data = if let Some(identity_sk) = predefined_identity_key { - self.save_runtime_data(genesis_block_hash, para_id, identity_sk, false, true)? + self.save_runtime_data(genesis_block_hash, para_id, identity_sk, false, true, None)? } else { match Self::load_runtime_data(&self.platform, &self.args.sealing_path) { Ok(data) => data, Err(Error::PersistentRuntimeNotFound) => { warn!("Persistent data not found."); let identity_sk = new_sr25519_key(); - self.save_runtime_data(genesis_block_hash, para_id, identity_sk, true, false)? + self.save_runtime_data( + genesis_block_hash, + para_id, + identity_sk, + true, + false, + None, + )? } Err(err) => return Err(anyhow!("Failed to load persistent data: {}", err)), } @@ -375,6 +382,7 @@ impl Phactory { sr25519_sk: sr25519::Pair, trusted_sk: bool, dev_mode: bool, + svn: Option<&[u8]>, ) -> Result { // Put in PresistentRuntimeData let sk = sr25519_sk.dump_secret_key(); @@ -392,7 +400,7 @@ impl Phactory { info!("Length of encoded slice: {}", encoded_vec.len()); let filepath = PathBuf::from(&self.args.sealing_path).join(RUNTIME_SEALED_DATA_FILE); self.platform - .seal_data(filepath, &encoded_vec) + .seal_data(filepath, &encoded_vec, svn) .map_err(Into::into) .context("Failed to seal runtime data")?; info!("Persistent Runtime Data V2 saved"); @@ -401,22 +409,31 @@ impl Phactory { } /// Loads the persistent runtime data from the sealing path - fn persistent_runtime_data(&self) -> Result { - Self::load_runtime_data(&self.platform, &self.args.sealing_path) + fn load_persistent_runtime_data_with_svn( + &self, + ) -> Result<(PersistentRuntimeData, Vec), Error> { + Self::load_runtime_data_with_svn(&self.platform, &self.args.sealing_path) } fn load_runtime_data( platform: &Platform, sealing_path: &str, ) -> Result { + Self::load_runtime_data_with_svn(platform, sealing_path).map(|(data, _)| data) + } + + fn load_runtime_data_with_svn( + platform: &Platform, + sealing_path: &str, + ) -> Result<(PersistentRuntimeData, Vec), Error> { let filepath = PathBuf::from(sealing_path).join(RUNTIME_SEALED_DATA_FILE); - let data = platform + let pal::UnsealedData { data, svn } = platform .unseal_data(filepath) .map_err(Into::into)? .ok_or(Error::PersistentRuntimeNotFound)?; let data: RuntimeDataSeal = Decode::decode(&mut &data[..]).map_err(Error::DecodeError)?; match data { - RuntimeDataSeal::V1(data) => Ok(data), + RuntimeDataSeal::V1(data) => Ok((data, svn)), } } @@ -840,7 +857,7 @@ fn new_sr25519_key() -> sr25519::Pair { } // TODO.kevin: Move to phactory-api when the std ready. -fn generate_random_iv() -> aead::IV { +pub fn generate_random_iv() -> aead::IV { let mut nonce_vec = [0u8; aead::IV_BYTES]; let rand = ring::rand::SystemRandom::new(); rand.fill(&mut nonce_vec).unwrap(); diff --git a/crates/phactory/src/prpc_service.rs b/crates/phactory/src/prpc_service.rs index 7b4ad1d551..884029868f 100644 --- a/crates/phactory/src/prpc_service.rs +++ b/crates/phactory/src/prpc_service.rs @@ -29,8 +29,9 @@ use phala_pallets::utils::attestation::{validate as validate_attestation_report, use phala_types::contract::contract_id_preimage; use phala_types::{ contract, messaging::EncryptedKey, wrap_content_to_sign, AttestationReport, - ChallengeHandlerInfo, EncryptedWorkerKey, HandoverChallenge, SignedContentType, - VersionedWorkerEndpoints, WorkerEndpointPayload, WorkerPublicKey, WorkerRegistrationInfoV2, + ChallengeHandlerInfo, EncryptedWorkerKeyV0, EncryptedWorkerKeyV1, HandoverChallenge, + SignedContentType, VersionedWorkerEndpoints, WorkerEndpointPayload, WorkerPublicKey, + WorkerRegistrationInfoV2, }; use sp_application_crypto::UncheckedFrom; use tracing::{error, info}; @@ -1637,7 +1638,9 @@ impl PhactoryApi for Rpc // Share the key with attestation let ecdh_pubkey = challenge_handler.ecdh_pubkey; let iv = crate::generate_random_iv(); - let runtime_data = phactory.persistent_runtime_data().map_err(from_display)?; + let (runtime_data, svn) = phactory + .load_persistent_runtime_data_with_svn() + .map_err(from_display)?; let (my_identity_key, _) = runtime_data.decode_keys(); let (ecdh_pubkey, encrypted_key) = key_share::encrypt_secret_to( &my_identity_key, @@ -1652,21 +1655,22 @@ impl PhactoryApi for Rpc encrypted_key, iv, }; - let runtime_state = phactory.runtime_state()?; - let genesis_block_hash = runtime_state.genesis_block_hash; - let encrypted_worker_key = EncryptedWorkerKey { + let genesis_block_hash = runtime_data.genesis_block_hash; + let encrypted_worker_key = EncryptedWorkerKeyV1 { genesis_block_hash, - para_id: runtime_state.para_id, + para_id: runtime_data.para_id, dev_mode, encrypted_key, + svn, }; - let worker_key_hash = sp_core::hashing::blake2_256(&encrypted_worker_key.encode()); + let encoded_worker_key = encrypted_worker_key.encode(); + let payload_hash = sp_core::hashing::blake2_256(&encoded_worker_key); let attestation = if !dev_mode && in_sgx { Some(create_attestation_report_on( &phactory.platform, attestation_provider, - &worker_key_hash, + &payload_hash, phactory.args.ra_timeout, phactory.args.ra_max_retries, )?) @@ -1675,10 +1679,11 @@ impl PhactoryApi for Rpc None }; - Ok(pb::HandoverWorkerKey::new( - encrypted_worker_key, + Ok(pb::HandoverWorkerKey { attestation, - )) + encoded_worker_key_v0: None, + encoded_worker_key_v1: Some(encoded_worker_key), + }) } // WorkerKey Handover Client @@ -1741,12 +1746,37 @@ impl PhactoryApi for Rpc async fn handover_receive(&mut self, request: pb::HandoverWorkerKey) -> RpcResult<()> { let mut phactory = self.lock_phactory(false, true)?; - let encrypted_worker_key = request.decode_worker_key().map_err(from_display)?; - - let dev_mode = encrypted_worker_key.dev_mode; + let received_key; + let payload_hash; + match ( + &request.encoded_worker_key_v0, + &request.encoded_worker_key_v1, + ) { + (None, None) => return Err(from_display("No worker key found")), + (Some(_), Some(_)) => return Err(from_display("Both v0 and v1 worker key found")), + (Some(encoded), None) => { + payload_hash = sp_core::hashing::blake2_256(encoded); + let v0 = EncryptedWorkerKeyV0::decode(&mut &encoded[..]) + .map_err(|_| from_display("Decode worker key failed"))?; + received_key = EncryptedWorkerKeyV1 { + genesis_block_hash: v0.genesis_block_hash, + para_id: v0.para_id, + dev_mode: v0.dev_mode, + encrypted_key: v0.encrypted_key, + // If the version of the key is v0, it must from pRuntime v2.0 or v2.1, which never load the + // keys with a different svn. Thus, we can safely set the svn to current svn. + svn: phactory.platform.current_svn().map_err(from_debug)?, + }; + } + (None, Some(encoded)) => { + payload_hash = sp_core::hashing::blake2_256(encoded); + received_key = EncryptedWorkerKeyV1::decode(&mut &encoded[..]) + .map_err(|_| from_display("Decode worker key failed"))?; + } + } + let dev_mode = received_key.dev_mode; // verify RA report if !dev_mode { - let worker_key_hash = sp_core::hashing::blake2_256(&encrypted_worker_key.encode()); let raw_attestation = request .attestation .ok_or_else(|| from_display("Server attestation not found"))?; @@ -1755,7 +1785,7 @@ impl PhactoryApi for Rpc .map_err(|_| from_display("Decode server attestation failed"))?; validate_attestation_report( attn_to_validate, - &worker_key_hash, + &payload_hash, now(), false, vec![], @@ -1766,7 +1796,7 @@ impl PhactoryApi for Rpc info!("Skip server RA report check for dev mode key"); } - let encrypted_key = encrypted_worker_key.encrypted_key; + let encrypted_key = received_key.encrypted_key; let my_ecdh_key = phactory .handover_ecdh_key .as_ref() @@ -1782,11 +1812,12 @@ impl PhactoryApi for Rpc // only seal if the key is successfully updated phactory .save_runtime_data( - encrypted_worker_key.genesis_block_hash, - encrypted_worker_key.para_id, + received_key.genesis_block_hash, + received_key.para_id, sr25519::Pair::restore_from_secret_key(&secret), false, // we are not sure whether this key is injected dev_mode, + Some(&received_key.svn), ) .map_err(from_display)?; diff --git a/crates/phactory/src/system/master_key.rs b/crates/phactory/src/system/master_key.rs index 061789a014..3ca760bf59 100644 --- a/crates/phactory/src/system/master_key.rs +++ b/crates/phactory/src/system/master_key.rs @@ -7,7 +7,7 @@ use sp_core::sr25519; use phala_crypto::sr25519::{Signature, Signing, Sr25519SecretKey}; -use crate::pal::Sealing; +use crate::pal::{Sealing, UnsealedData}; /// Master key filepath pub const MASTER_KEY_FILE: &str = "master_key.seal"; @@ -66,7 +66,7 @@ pub fn seal( info!("Seal master key to {}", filepath.as_path().display()); // TODO.shelven: seal with identity key so the newly handovered pRuntime do not need to do an extra sync to get master // key - sys.seal_data(filepath, &data.encode()) + sys.seal_data(filepath, &data.encode(), None) .expect("Seal master key failed"); } @@ -84,7 +84,7 @@ pub fn try_unseal( ) -> Vec { let filepath = master_key_file_path(&sealing_path); info!("Unseal master key from {}", filepath.as_path().display()); - let sealed_data = match sys + let UnsealedData { data, .. } = match sys .unseal_data(&filepath) .expect("Unseal master key failed") { @@ -96,7 +96,7 @@ pub fn try_unseal( }; let versioned_data = - MasterKeySeal::decode(&mut &sealed_data[..]).expect("Failed to decode sealed master key"); + MasterKeySeal::decode(&mut &data[..]).expect("Failed to decode sealed master key"); #[allow(clippy::infallible_destructuring_match)] let secrets = match versioned_data { diff --git a/crates/phala-types/src/lib.rs b/crates/phala-types/src/lib.rs index f922e3714b..4586c0a548 100644 --- a/crates/phala-types/src/lib.rs +++ b/crates/phala-types/src/lib.rs @@ -530,13 +530,22 @@ pub struct ChallengeHandlerInfo { } #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)] -pub struct EncryptedWorkerKey { +pub struct EncryptedWorkerKeyV0 { pub genesis_block_hash: H256, pub para_id: u32, pub dev_mode: bool, pub encrypted_key: messaging::EncryptedKey, } +#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)] +pub struct EncryptedWorkerKeyV1 { + pub genesis_block_hash: H256, + pub para_id: u32, + pub dev_mode: bool, + pub encrypted_key: messaging::EncryptedKey, + pub svn: Vec, +} + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, TypeInfo)] pub struct WorkerRegistrationInfo { pub version: u32, diff --git a/crates/sgx-api-lite/Cargo.toml b/crates/sgx-api-lite/Cargo.toml index 880b2325ad..3c1b5e928b 100644 --- a/crates/sgx-api-lite/Cargo.toml +++ b/crates/sgx-api-lite/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] cmac = "0.7.1" aes = "0.8.1" +bitflags = "2" diff --git a/crates/sgx-api-lite/src/egetkey.rs b/crates/sgx-api-lite/src/egetkey.rs new file mode 100644 index 0000000000..e31460b75c --- /dev/null +++ b/crates/sgx-api-lite/src/egetkey.rs @@ -0,0 +1,115 @@ +//! This file is copied from crate sgx_isa which is part of Fortanix, we can not directly use +//! sgx_isa because it requires compilation target=fortanix-sgx. + +#![allow(dead_code)] +#![allow(clippy::enum_variant_names)] + +use bitflags::bitflags; +use core::arch::asm; +use core::mem::MaybeUninit; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u16)] +enum Keyname { + Einittoken = 0, + Provision = 1, + ProvisionSeal = 2, + Report = 3, + Seal = 4, +} + +bitflags! { + #[repr(C)] + struct Keypolicy: u16 { + const MRENCLAVE = 0b0000_0001; + const MRSIGNER = 0b0000_0010; + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u32)] +enum Enclu { + EReport = 0, + EGetkey = 1, + EEnter = 2, + EResume = 3, + EExit = 4, + EAccept = 5, + EModpe = 6, + EAcceptcopy = 7, +} + +#[repr(align(16))] +struct Align16(T); + +#[repr(align(512))] +struct Align512(T); + +/// Call the `EGETKEY` instruction to obtain a 128-bit secret key. +fn egetkey(request: &Align512<[u8; 512]>) -> Result, u32> { + unsafe { + let mut out = MaybeUninit::uninit(); + let error; + + asm!( + // rbx is reserved by LLVM + "xchg %rbx, {0}", + "enclu", + "mov {0}, %rbx", + inout(reg) request => _, + inlateout("eax") Enclu::EGetkey as u32 => error, + in("rcx") out.as_mut_ptr(), + options(att_syntax, nostack), + ); + + match error { + 0 => Ok(out.assume_init()), + err => Err(err), + } + } +} + +#[repr(C, align(512))] +struct Keyrequest { + keyname: u16, + keypolicy: Keypolicy, + isvsvn: u16, + _reserved1: u16, + cpusvn: [u8; 16], + attributemask: [u64; 2], + keyid: [u8; 32], + miscmask: u32, + _reserved2: [u8; 436], +} + +impl Keyrequest { + fn copy(&self) -> [u8; 512] { + unsafe { *(self as *const Keyrequest as *const [u8; 512]) } + } + + fn egetkey(&self) -> Result, u32> { + egetkey(&Align512(self.copy())) + } +} + +/// Derive a MRENCLAVE sealing key with the given `isvsvn`, `cpusvn` and `keyid`. +pub fn get_mrenclave_sealing_key( + isvsvn: u16, + cpusvn: [u8; 16], + keyid: [u8; 32], +) -> Result<[u8; 16], u32> { + let request = Keyrequest { + keyname: Keyname::Seal as u16, + keypolicy: Keypolicy::MRENCLAVE, + isvsvn, + _reserved1: 0, + cpusvn, + // Less mask to prevent the derived key changes during system upgrade. + attributemask: [0x03, 0x00], + keyid, + miscmask: 0, + _reserved2: [0; 436], + }; + let key = request.egetkey()?; + Ok(key.0) +} diff --git a/crates/sgx-api-lite/src/lib.rs b/crates/sgx-api-lite/src/lib.rs index 5a74b70d62..d3de42572b 100644 --- a/crates/sgx-api-lite/src/lib.rs +++ b/crates/sgx-api-lite/src/lib.rs @@ -25,8 +25,10 @@ use std::mem::{size_of, zeroed}; pub use sys::sgx_report_data_t as ReportData; pub use sys::sgx_report_t as Report; pub use sys::sgx_target_info_t as TargetInfo; +pub use egetkey::get_mrenclave_sealing_key; mod sys; +mod egetkey; #[repr(C, align(512))] struct SgxAligned(T); diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index 05dee62d03..b2a99cfeed 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -6132,6 +6132,7 @@ dependencies = [ "phactory-pal", "phala-allocator", "phala-clap-parsers", + "phala-crypto", "phala-git-revision", "phala-rocket-middleware", "phala-sanitized-logger", @@ -7281,6 +7282,7 @@ name = "sgx-api-lite" version = "0.1.0" dependencies = [ "aes", + "bitflags 2.0.2", "cmac", ] diff --git a/standalone/pruntime/Cargo.toml b/standalone/pruntime/Cargo.toml index 2783039e0a..e61487fc42 100644 --- a/standalone/pruntime/Cargo.toml +++ b/standalone/pruntime/Cargo.toml @@ -39,6 +39,7 @@ phala-rocket-middleware = { path = "../../crates/phala-rocket-middleware" } phala-types = { path = "../../crates/phala-types", features = ["enable_serde", "sgx"] } phala-git-revision = { path = "../../crates/phala-git-revision" } phala-clap-parsers = { path = "../../crates/phala-clap-parsers" } +phala-crypto = { path = "../../crates/phala-crypto" } sgx-api-lite = { path = "../../crates/sgx-api-lite" } tracing = "0.1" hex_fmt = "0.3.0" diff --git a/standalone/pruntime/gramine-build/pruntime.manifest.template b/standalone/pruntime/gramine-build/pruntime.manifest.template index e6fe19f531..02c12ca1aa 100644 --- a/standalone/pruntime/gramine-build/pruntime.manifest.template +++ b/standalone/pruntime/gramine-build/pruntime.manifest.template @@ -45,10 +45,9 @@ path = "/lib" uri = "file:{{ libdir }}" [[fs.mounts]] +type = "chroot" path = "/data/protected_files" uri = "file:{{ seal_dir }}" -type = "encrypted" -key_name = "_sgx_mrenclave" [[fs.mounts]] type = "chroot" @@ -89,4 +88,5 @@ allowed_files = [ "file:/etc/resolv.conf", "file:Rocket.toml", "file:{{ storage_dir }}/", + "file:{{ seal_dir }}/", ] diff --git a/standalone/pruntime/src/pal_gramine.rs b/standalone/pruntime/src/pal_gramine.rs index ebb36142e3..e5c1b30443 100644 --- a/standalone/pruntime/src/pal_gramine.rs +++ b/standalone/pruntime/src/pal_gramine.rs @@ -1,9 +1,11 @@ use anyhow::anyhow; -use parity_scale_codec::Encode; +use parity_scale_codec::{Decode, Encode}; use std::alloc::System; use tracing::info; -use phactory_pal::{AppInfo, AppVersion, Machine, MemoryStats, MemoryUsage, Sealing, RA}; +use phactory_pal::{ + AppInfo, AppVersion, Machine, MemoryStats, MemoryUsage, Sealing, UnsealedData, RA, +}; use phala_allocator::StatSizeAllocator; use std::io::ErrorKind; use std::str::FromStr as _; @@ -16,28 +18,106 @@ use phala_types::AttestationProvider; #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] pub(crate) struct GraminePlatform; +#[derive(Encode, Decode)] +struct Svn { + isvsvn: u16, + cpusvn: [u8; 16], +} + +#[derive(Encode, Decode)] +struct SealedData { + svn: Svn, + iv: [u8; 12], + data: Vec, +} + +fn get_sealing_key(isvsvn: u16, cpusvn: [u8; 16]) -> anyhow::Result<[u8; 32]> { + const KEY_ID: [u8; 32] = *b"pruntime-sealed-data-key-id\0\0\0\0\0"; + let key128 = sgx_api_lite::get_mrenclave_sealing_key(isvsvn, cpusvn, KEY_ID) + .or(Err(anyhow!("Failed to get sealing key")))?; + // phala_crypto API uses AES256, so extend the key to 256 bits + let mut key256 = [0; 32]; + key256[..16].copy_from_slice(&key128[..]); + Ok(key256) +} + +fn sgx_current_svn() -> anyhow::Result { + let this_target_info = + sgx_api_lite::target_info().or(Err(anyhow!("Failed to get target info")))?; + let report = sgx_api_lite::report(&this_target_info, &[0; 64]) + .or(Err(anyhow!("Failed to get SGX report")))?; + let isvsvn = report.body.isv_svn; + let cpusvn = report.body.cpu_svn.svn; + Ok(Svn { isvsvn, cpusvn }) +} + +fn sgx_seal_data(data: &[u8], svn: Svn) -> anyhow::Result { + let key = + get_sealing_key(svn.isvsvn, svn.cpusvn).or(Err(anyhow!("Failed to get sealing key")))?; + let iv = phactory::generate_random_iv(); + let mut data = data.to_vec(); + phala_crypto::aead::encrypt(&iv, &key, &mut data).or(Err(anyhow!("Failed to encrypt data")))?; + Ok(SealedData { svn, iv, data }) +} + +fn sgx_unseal_data(data: &SealedData) -> anyhow::Result> { + let key = get_sealing_key(data.svn.isvsvn, data.svn.cpusvn) + .or(Err(anyhow!("Failed to get sealing key")))?; + let mut enccypted_data = data.data.clone(); + let decrypted = phala_crypto::aead::decrypt(&data.iv, &key, &mut enccypted_data[..]) + .or(Err(anyhow!("Failed to decrypt sealed data",)))?; + Ok(decrypted.to_vec()) +} + impl Sealing for GraminePlatform { - type SealError = std::io::Error; - type UnsealError = std::io::Error; + type SealError = anyhow::Error; + type UnsealError = anyhow::Error; fn seal_data( &self, path: impl AsRef, data: &[u8], + svn: Option<&[u8]>, ) -> Result<(), Self::SealError> { - std::fs::write(path, data)?; + if !is_gramine() { + std::fs::write(path, data)?; + return Ok(()); + } + info!("Sealing data to {:?}", path.as_ref()); + let svn = match svn { + Some(svn) => Svn::decode(&mut &svn[..])?, + None => sgx_current_svn()?, + }; + let data = sgx_seal_data(data, svn)?; + let encoded = data.encode(); + std::fs::write(path, encoded)?; Ok(()) } fn unseal_data( &self, path: impl AsRef, - ) -> Result>, Self::UnsealError> { + ) -> Result, Self::UnsealError> { match std::fs::read(path) { Err(err) if matches!(err.kind(), ErrorKind::NotFound) => Ok(None), - other => other.map(Some), + Ok(data) => { + if !is_gramine() { + return Ok(Some(UnsealedData { data, svn: vec![] })); + } + let sealed_data = SealedData::decode(&mut &data[..])?; + let data = sgx_unseal_data(&sealed_data)?; + Ok(Some(UnsealedData { + data, + svn: sealed_data.svn.encode(), + })) + } + Err(err) => Err(err.into()), } } + + fn current_svn(&self) -> Result, Self::SealError> { + Ok(sgx_current_svn()?.encode()) + } } impl RA for GraminePlatform { @@ -193,6 +273,7 @@ pub(crate) fn print_target_info() { "isv_prod_id : 0x{:?}", HexFmt(report.body.isv_prod_id.to_ne_bytes()) ); + println!("cpu_svn : 0x{}", HexFmt(&report.body.cpu_svn.svn)); } else { println!("Running in Native mode"); }