oasis_core_runtime/common/sgx/
mod.rs1pub mod egetkey;
4pub mod ias;
5pub mod pcs;
6pub mod seal;
7
8use anyhow::Result;
9use chrono::prelude::*;
10
11use crate::common::time::{insecure_posix_time, update_insecure_posix_time};
12
13pub const MAX_QUOTE_AGE: i64 = 24 * 60 * 60; impl_bytes!(MrEnclave, 32, "Enclave hash (MRENCLAVE).");
17impl_bytes!(MrSigner, 32, "Enclave signer hash (MRSIGNER).");
18
19#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, cbor::Encode, cbor::Decode)]
21pub struct EnclaveIdentity {
22 pub mr_enclave: MrEnclave,
23 pub mr_signer: MrSigner,
24}
25
26impl EnclaveIdentity {
27 pub fn current() -> Option<Self> {
29 cfg_if::cfg_if! {
30 if #[cfg(target_env = "sgx")] {
31 let report = sgx_isa::Report::for_self();
33 Some(EnclaveIdentity {
34 mr_enclave: MrEnclave(report.mrenclave),
35 mr_signer: MrSigner(report.mrsigner),
36 })
37 } else if #[cfg(feature = "tdx")] {
38 let report = crate::common::tdx::report::get_report(&[0; 64]).expect("failed to get report");
40 Some(report.as_enclave_identity())
41 } else if #[cfg(feature = "debug-mock-sgx")] {
42 Some(Self::fortanix_test(std::env::var("OASIS_MOCK_MRENCLAVE").unwrap().parse().unwrap()))
45 } else {
46 None
48 }
49 }
50 }
51
52 pub fn fortanix_test(mr_enclave: MrEnclave) -> Self {
54 Self {
55 mr_enclave,
56 mr_signer: MrSigner::from(
57 "9affcfae47b848ec2caf1c49b4b283531e1cc425f93582b36806e52a43d78d1a",
58 ),
59 }
60 }
61}
62
63#[derive(Clone, Debug, PartialEq, Eq, cbor::Encode, cbor::Decode)]
65pub enum Quote {
66 #[cbor(rename = "ias")]
67 Ias(ias::AVR),
68
69 #[cbor(rename = "pcs")]
70 Pcs(pcs::QuoteBundle),
71}
72
73impl Quote {
74 pub fn verify(&self, policy: &QuotePolicy) -> Result<VerifiedQuote> {
76 let mut verified_quote = match self {
77 Quote::Ias(avr) => ias::verify(avr, &policy.ias.clone().unwrap_or_default()),
78 Quote::Pcs(qb) => {
79 let now = Utc.timestamp_opt(insecure_posix_time(), 0).unwrap();
80 Ok(qb.verify(&policy.pcs.clone().unwrap_or_default(), now)?)
81 }
82 }?;
83
84 update_insecure_posix_time(verified_quote.timestamp);
86 verified_quote.timestamp = insecure_posix_time();
87
88 Ok(verified_quote)
89 }
90
91 pub fn is_fresh(&self, now: i64, ts: i64, policy: &QuotePolicy) -> bool {
93 if (now - ts).abs() > MAX_QUOTE_AGE {
95 return false;
96 }
97
98 match self {
100 Quote::Ias(_) => true, Quote::Pcs(_) => !policy.pcs.clone().unwrap_or_default().is_expired(now, ts),
102 }
103 }
104}
105
106#[derive(Clone, Debug, Default, PartialEq, Eq, cbor::Encode, cbor::Decode)]
108pub struct QuotePolicy {
109 #[cbor(rename = "ias")]
110 pub ias: Option<ias::QuotePolicy>,
111
112 #[cbor(rename = "pcs")]
113 pub pcs: Option<pcs::QuotePolicy>,
114}
115
116#[derive(Debug, Default, Clone)]
118pub struct VerifiedQuote {
119 pub report_data: Vec<u8>,
120 pub identity: EnclaveIdentity,
121 pub timestamp: i64,
122}
123
124#[cfg(target_env = "sgx")]
126pub fn report_for(target_info: &sgx_isa::Targetinfo, report_data: &[u8; 64]) -> sgx_isa::Report {
127 sgx_isa::Report::for_target(target_info, report_data)
128}
129
130#[cfg(not(target_env = "sgx"))]
132pub fn report_for(_target_info: &sgx_isa::Targetinfo, report_data: &[u8; 64]) -> sgx_isa::Report {
133 let ei = EnclaveIdentity::current().expect("mock enclave identity not available");
134
135 sgx_isa::Report {
137 mrenclave: ei.mr_enclave.into(),
138 mrsigner: ei.mr_signer.into(),
139 cpusvn: [8, 9, 14, 13, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
140 attributes: sgx_isa::Attributes {
141 flags: sgx_isa::AttributesFlags::INIT
142 | sgx_isa::AttributesFlags::DEBUG
143 | sgx_isa::AttributesFlags::MODE64BIT,
144 xfrm: 3,
145 },
146 reportdata: *report_data,
147 ..Default::default()
148 }
149}