mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-22 23:44:48 +02:00
feat(quote): add FMSPC extraction and related utils
- Introduced FMSPC extraction methods and associated utility functions. - Updated `Quote` structure with parsing enhancements and FMSPC support. - Added `quote_op` feature gating for SGX/TDX-specific functionality.
This commit is contained in:
parent
2118466a8a
commit
6e65cf2f47
14 changed files with 1585 additions and 46 deletions
43
Cargo.lock
generated
43
Cargo.lock
generated
|
@ -1285,9 +1285,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "data-encoding"
|
name = "data-encoding"
|
||||||
version = "2.8.0"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
|
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dbl"
|
name = "dbl"
|
||||||
|
@ -1300,9 +1300,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dcap-qvl"
|
name = "dcap-qvl"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a8bc5d87613fe4c0a7a980c3e9113d9f10b9f9404218e19333e0eff2eff4c9a"
|
checksum = "7c8049b28b1fe35e94bd52f4c20edf7b80b6eeb378faccdd685d5cd82cbc192e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"asn1_der",
|
"asn1_der",
|
||||||
|
@ -2189,17 +2189,6 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hostname"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"windows",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
|
@ -2259,9 +2248,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.1.0"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
|
@ -4017,12 +4006,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "resolv-conf"
|
name = "resolv-conf"
|
||||||
version = "0.7.1"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4"
|
checksum = "fc7c8f7f733062b66dc1c63f9db168ac0b97a9210e247fa90fdc9ad08f51b302"
|
||||||
dependencies = [
|
|
||||||
"hostname",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rfc6979"
|
name = "rfc6979"
|
||||||
|
@ -4936,6 +4922,7 @@ name = "teepot"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"asn1_der",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64",
|
"base64",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
@ -4967,7 +4954,6 @@ dependencies = [
|
||||||
"sha2",
|
"sha2",
|
||||||
"sha3",
|
"sha3",
|
||||||
"signature",
|
"signature",
|
||||||
"tdx-attest-rs",
|
|
||||||
"teepot-tee-quote-verification-rs",
|
"teepot-tee-quote-verification-rs",
|
||||||
"testaso",
|
"testaso",
|
||||||
"thiserror 2.0.11",
|
"thiserror 2.0.11",
|
||||||
|
@ -5002,6 +4988,7 @@ version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"intel-tee-quote-verification-sys",
|
"intel-tee-quote-verification-sys",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tdx-attest-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -5945,16 +5932,6 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows"
|
|
||||||
version = "0.52.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
|
||||||
dependencies = [
|
|
||||||
"windows-core",
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
|
|
@ -68,3 +68,6 @@ tracing-test = { version = "0.2.5", features = ["no-env-filter"] }
|
||||||
url = "2.5.2"
|
url = "2.5.2"
|
||||||
x509-cert = { version = "0.2", features = ["builder", "signature", "default"] }
|
x509-cert = { version = "0.2", features = ["builder", "signature", "default"] }
|
||||||
zeroize = { version = "1.7.0", features = ["serde"] }
|
zeroize = { version = "1.7.0", features = ["serde"] }
|
||||||
|
asn1_der = { version = "0.7", default-features = false, features = [
|
||||||
|
"native_types",
|
||||||
|
] }
|
||||||
|
|
|
@ -14,3 +14,4 @@ serde = { version = "1", features = ["derive", "rc"] }
|
||||||
|
|
||||||
[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies]
|
[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies]
|
||||||
intel-tee-quote-verification-sys = { version = "0.2.1" }
|
intel-tee-quote-verification-sys = { version = "0.2.1" }
|
||||||
|
tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" }
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
//!
|
//!
|
||||||
//! This is a safe wrapper for **sgx-dcap-quoteverify-sys**.
|
//! This is a safe wrapper for **sgx-dcap-quoteverify-sys**.
|
||||||
|
|
||||||
|
pub mod tdx_attest_rs {
|
||||||
|
pub use tdx_attest_rs::*;
|
||||||
|
}
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{marker::PhantomData, ops::Deref, slice};
|
use std::{marker::PhantomData, ops::Deref, slice};
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,17 @@ edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
|
|
||||||
[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies]
|
|
||||||
tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" }
|
|
||||||
teepot-tee-quote-verification-rs = { path = "../teepot-tee-quote-verification-rs" }
|
|
||||||
|
|
||||||
[target.'cfg(not(all(target_os = "linux", target_arch = "x86_64")))'.dependencies]
|
[target.'cfg(not(all(target_os = "linux", target_arch = "x86_64")))'.dependencies]
|
||||||
dcap-qvl = "0.2.3"
|
dcap-qvl = "0.2.3"
|
||||||
chrono = "0.4.40"
|
chrono = "0.4.40"
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["quote_op"]
|
||||||
|
quote_op = ["dep:teepot-tee-quote-verification-rs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
teepot-tee-quote-verification-rs = { path = "../teepot-tee-quote-verification-rs", optional = true }
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
bytemuck.workspace = true
|
bytemuck.workspace = true
|
||||||
|
@ -56,6 +57,7 @@ tracing-log.workspace = true
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
x509-cert.workspace = true
|
x509-cert.workspace = true
|
||||||
zeroize.workspace = true
|
zeroize.workspace = true
|
||||||
|
asn1_der.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod ethereum;
|
pub mod ethereum;
|
||||||
pub mod log;
|
pub mod log;
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
pub mod pki;
|
pub mod pki;
|
||||||
pub mod prover;
|
pub mod prover;
|
||||||
pub mod quote;
|
pub mod quote;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//! Quote Error type
|
//! Quote Error type
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(feature = "quote_op", target_os = "linux", target_arch = "x86_64"))]
|
||||||
use tdx_attest_rs::tdx_attest_error_t;
|
use teepot_tee_quote_verification_rs::tdx_attest_rs::tdx_attest_error_t;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Quote parsing error
|
/// Quote parsing error
|
||||||
|
@ -22,7 +22,7 @@ pub enum QuoteError {
|
||||||
InvalidTeeType,
|
InvalidTeeType,
|
||||||
#[error("unsupported body type")]
|
#[error("unsupported body type")]
|
||||||
UnsupportedBodyType,
|
UnsupportedBodyType,
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(feature = "quote_op", target_os = "linux", target_arch = "x86_64"))]
|
||||||
#[error("tdx_att_get_quote error {msg}: {inner:?}")]
|
#[error("tdx_att_get_quote error {msg}: {inner:?}")]
|
||||||
TdxAttGetQuote {
|
TdxAttGetQuote {
|
||||||
inner: tdx_attest_error_t,
|
inner: tdx_attest_error_t,
|
||||||
|
@ -58,7 +58,7 @@ pub enum QuoteError {
|
||||||
CrlUnsupportedFormat(String),
|
CrlUnsupportedFormat(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(feature = "quote_op", target_os = "linux", target_arch = "x86_64"))]
|
||||||
impl From<tdx_attest_error_t> for QuoteError {
|
impl From<tdx_attest_error_t> for QuoteError {
|
||||||
fn from(code: tdx_attest_error_t) -> Self {
|
fn from(code: tdx_attest_error_t) -> Self {
|
||||||
Self::TdxAttGetQuote {
|
Self::TdxAttGetQuote {
|
||||||
|
@ -108,7 +108,7 @@ impl<T, E: std::fmt::Display> QuoteContextErr for Result<T, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(feature = "quote_op", target_os = "linux", target_arch = "x86_64"))]
|
||||||
impl<T> QuoteContext for Result<T, tdx_attest_error_t> {
|
impl<T> QuoteContext for Result<T, tdx_attest_error_t> {
|
||||||
type Ok = T;
|
type Ok = T;
|
||||||
fn context<I: Into<String>>(self, msg: I) -> Result<T, QuoteError> {
|
fn context<I: Into<String>>(self, msg: I) -> Result<T, QuoteError> {
|
||||||
|
|
|
@ -11,9 +11,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
use bytemuck::cast_slice;
|
use bytemuck::cast_slice;
|
||||||
use std::{ffi::CStr, mem, mem::MaybeUninit, pin::Pin};
|
use std::{ffi::CStr, mem, mem::MaybeUninit, pin::Pin};
|
||||||
use tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t};
|
|
||||||
use teepot_tee_quote_verification_rs::{
|
use teepot_tee_quote_verification_rs::{
|
||||||
quote3_error_t as _quote3_error_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t,
|
quote3_error_t as _quote3_error_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t,
|
||||||
|
tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t},
|
||||||
tee_get_supplemental_data_version_and_size, tee_qv_get_collateral, tee_supp_data_descriptor_t,
|
tee_get_supplemental_data_version_and_size, tee_qv_get_collateral, tee_supp_data_descriptor_t,
|
||||||
tee_verify_quote, Collateral as IntelCollateral,
|
tee_verify_quote, Collateral as IntelCollateral,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
//! Get a quote from a TEE
|
//! Get a quote from a TEE
|
||||||
|
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
pub mod attestation;
|
pub mod attestation;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod tcblevel;
|
pub mod tcblevel;
|
||||||
|
@ -15,7 +16,9 @@ pub mod tcblevel;
|
||||||
not(all(target_os = "linux", target_arch = "x86_64")),
|
not(all(target_os = "linux", target_arch = "x86_64")),
|
||||||
path = "phala.rs"
|
path = "phala.rs"
|
||||||
)]
|
)]
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
mod os;
|
mod os;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use crate::quote::{
|
use crate::quote::{
|
||||||
error::{QuoteContext as _, QuoteError},
|
error::{QuoteContext as _, QuoteError},
|
||||||
|
@ -547,6 +550,23 @@ impl Decode for Quote {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FMSPC (Family-Model-Stepping-Platform-CustomSKU) is a 6-byte identifier
|
||||||
|
/// that uniquely identifies a platform's SGX TCB level.
|
||||||
|
/// It is extracted from the PCK certificate in the SGX quote and is used to
|
||||||
|
/// fetch TCB information from Intel's Provisioning Certification Service.
|
||||||
|
pub type Fmspc = [u8; 6];
|
||||||
|
|
||||||
|
/// CPU Security Version Number (CPUSVN) is a 16-byte value representing
|
||||||
|
/// the security version of the CPU microcode and firmware.
|
||||||
|
/// It is used in SGX attestation to determine the security patch level
|
||||||
|
/// of the platform.
|
||||||
|
pub type CpuSvn = [u8; 16];
|
||||||
|
|
||||||
|
/// Security Version Number (SVN) is a 16-bit value representing the
|
||||||
|
/// security version of a component (like PCE or QE).
|
||||||
|
/// Higher values indicate newer security patches have been applied.
|
||||||
|
pub type Svn = u16;
|
||||||
|
|
||||||
impl Quote {
|
impl Quote {
|
||||||
/// Parse a TEE quote from a byte slice.
|
/// Parse a TEE quote from a byte slice.
|
||||||
pub fn parse(quote: &[u8]) -> Result<Self, QuoteError> {
|
pub fn parse(quote: &[u8]) -> Result<Self, QuoteError> {
|
||||||
|
@ -555,6 +575,32 @@ impl Quote {
|
||||||
Ok(quote)
|
Ok(quote)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the raw certificate chain from the quote.
|
||||||
|
pub fn raw_cert_chain(&self) -> Result<&[u8], QuoteError> {
|
||||||
|
let cert_data = match &self.auth_data {
|
||||||
|
AuthData::V3(data) => &data.certification_data,
|
||||||
|
AuthData::V4(data) => &data.qe_report_data.certification_data,
|
||||||
|
};
|
||||||
|
if cert_data.cert_type != 5 {
|
||||||
|
QuoteError::QuoteCertificationDataUnsupported(format!(
|
||||||
|
"Unsupported cert type: {}",
|
||||||
|
cert_data.cert_type
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(&cert_data.body.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the FMSPC from the quote.
|
||||||
|
pub fn fmspc(&self) -> Result<Fmspc, QuoteError> {
|
||||||
|
let raw_cert_chain = self.raw_cert_chain()?;
|
||||||
|
let certs = utils::extract_certs(raw_cert_chain)?;
|
||||||
|
let cert = certs
|
||||||
|
.first()
|
||||||
|
.ok_or(QuoteError::Unexpected("Invalid certificate".into()))?;
|
||||||
|
let extension_section = utils::get_intel_extension(cert)?;
|
||||||
|
utils::get_fmspc(&extension_section)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the report data
|
/// Get the report data
|
||||||
pub fn get_report_data(&self) -> &[u8] {
|
pub fn get_report_data(&self) -> &[u8] {
|
||||||
match &self.report {
|
match &self.report {
|
||||||
|
@ -600,6 +646,7 @@ impl FromStr for TEEType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the attestation quote from a TEE
|
/// Get the attestation quote from a TEE
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
pub fn get_quote(report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> {
|
pub fn get_quote(report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> {
|
||||||
os::get_quote(report_data)
|
os::get_quote(report_data)
|
||||||
}
|
}
|
||||||
|
@ -646,11 +693,13 @@ pub struct Collateral {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the collateral data from an SGX or TDX quote
|
/// Get the collateral data from an SGX or TDX quote
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
pub fn get_collateral(quote: &[u8]) -> Result<Collateral, QuoteError> {
|
pub fn get_collateral(quote: &[u8]) -> Result<Collateral, QuoteError> {
|
||||||
os::get_collateral(quote)
|
os::get_collateral(quote)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verifies a quote with optional collateral material
|
/// Verifies a quote with optional collateral material
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
pub fn verify_quote_with_collateral(
|
pub fn verify_quote_with_collateral(
|
||||||
quote: &[u8],
|
quote: &[u8],
|
||||||
collateral: Option<&Collateral>,
|
collateral: Option<&Collateral>,
|
||||||
|
|
106
crates/teepot/src/quote/utils.rs
Normal file
106
crates/teepot/src/quote/utils.rs
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024-2025 Matter Labs
|
||||||
|
|
||||||
|
// Parts of it are Copyright (c) 2024 Phala Network
|
||||||
|
// and copied from https://github.com/Phala-Network/dcap-qvl
|
||||||
|
|
||||||
|
use crate::quote::{error::QuoteError, Fmspc};
|
||||||
|
use asn1_der::{
|
||||||
|
typed::{DerDecodable, Sequence},
|
||||||
|
DerObject,
|
||||||
|
};
|
||||||
|
use x509_cert::certificate::CertificateInner;
|
||||||
|
|
||||||
|
pub mod oids {
|
||||||
|
use const_oid::ObjectIdentifier as OID;
|
||||||
|
|
||||||
|
const fn oid(s: &str) -> OID {
|
||||||
|
OID::new_unwrap(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const SGX_EXTENSION: OID = oid("1.2.840.113741.1.13.1");
|
||||||
|
pub const FMSPC: OID = oid("1.2.840.113741.1.13.1.4");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_oid_works() {
|
||||||
|
assert_eq!(
|
||||||
|
SGX_EXTENSION.as_bytes(),
|
||||||
|
oid("1.2.840.113741.1.13.1").as_bytes()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_intel_extension(cert: &CertificateInner) -> Result<Vec<u8>, QuoteError> {
|
||||||
|
let mut extension_iter = cert
|
||||||
|
.tbs_certificate
|
||||||
|
.extensions
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or(&[])
|
||||||
|
.iter()
|
||||||
|
.filter(|e| e.extn_id == oids::SGX_EXTENSION)
|
||||||
|
.map(|e| e.extn_value.clone());
|
||||||
|
|
||||||
|
let extension = extension_iter
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| QuoteError::Unexpected("Intel extension not found".into()))?;
|
||||||
|
if extension_iter.next().is_some() {
|
||||||
|
//"There should only be one section containing Intel extensions"
|
||||||
|
return Err(QuoteError::Unexpected("Intel extension ambiguity".into()));
|
||||||
|
}
|
||||||
|
Ok(extension.into_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_extension(path: &[&[u8]], raw: &[u8]) -> Result<Vec<u8>, QuoteError> {
|
||||||
|
let obj = DerObject::decode(raw)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to decode DER object".into()))?;
|
||||||
|
let subobj =
|
||||||
|
get_obj(path, obj).map_err(|_| QuoteError::Unexpected("Failed to get subobject".into()))?;
|
||||||
|
Ok(subobj.value().to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_obj<'a>(path: &[&[u8]], mut obj: DerObject<'a>) -> Result<DerObject<'a>, QuoteError> {
|
||||||
|
for oid in path {
|
||||||
|
let seq = Sequence::load(obj)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to load sequence".into()))?;
|
||||||
|
obj = sub_obj(oid, seq)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to get subobject".into()))?;
|
||||||
|
}
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sub_obj<'a>(oid: &[u8], seq: Sequence<'a>) -> Result<DerObject<'a>, QuoteError> {
|
||||||
|
for i in 0..seq.len() {
|
||||||
|
let entry = seq
|
||||||
|
.get(i)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to get entry".into()))?;
|
||||||
|
let entry = Sequence::load(entry)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to load sequence".into()))?;
|
||||||
|
let name = entry
|
||||||
|
.get(0)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to get name".into()))?;
|
||||||
|
let value = entry
|
||||||
|
.get(1)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to get value".into()))?;
|
||||||
|
if name.value() == oid {
|
||||||
|
return Ok(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(QuoteError::Unexpected("Oid is missing".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fmspc(extension_section: &[u8]) -> Result<Fmspc, QuoteError> {
|
||||||
|
let data = find_extension(&[oids::FMSPC.as_bytes()], extension_section)
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to find Fmspc".into()))?;
|
||||||
|
if data.len() != 6 {
|
||||||
|
return Err(QuoteError::Unexpected("Fmspc length mismatch".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
data.try_into()
|
||||||
|
.map_err(|_| QuoteError::Unexpected("Failed to decode Fmspc".into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_certs(cert_chain: &[u8]) -> Result<Vec<CertificateInner>, QuoteError> {
|
||||||
|
let cert_chain = cert_chain.strip_suffix(&[0]).unwrap_or(cert_chain);
|
||||||
|
|
||||||
|
CertificateInner::<x509_cert::certificate::Rfc5280>::load_pem_chain(cert_chain)
|
||||||
|
.map_err(|e| QuoteError::Unexpected(format!("Could not load a PEM chain: {}", e)))
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
//! Intel TDX helper functions.
|
//! Intel TDX helper functions.
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(feature = "quote_op", target_os = "linux", target_arch = "x86_64"))]
|
||||||
pub mod rtmr;
|
pub mod rtmr;
|
||||||
|
|
||||||
/// The sha384 digest of 0u32, which is used in the UEFI TPM protocol
|
/// The sha384 digest of 0u32, which is used in the UEFI TPM protocol
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//! rtmr event data
|
//! rtmr event data
|
||||||
|
|
||||||
use crate::sgx::QuoteError;
|
use crate::sgx::QuoteError;
|
||||||
|
use teepot_tee_quote_verification_rs::tdx_attest_rs::{tdx_att_extend, tdx_attest_error_t};
|
||||||
|
|
||||||
/// The actual rtmr event data handled in DCAP
|
/// The actual rtmr event data handled in DCAP
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
|
@ -59,8 +60,8 @@ impl TdxRtmrEvent {
|
||||||
pub fn extend(self) -> Result<(), QuoteError> {
|
pub fn extend(self) -> Result<(), QuoteError> {
|
||||||
let event: Vec<u8> = self.into();
|
let event: Vec<u8> = self.into();
|
||||||
|
|
||||||
match tdx_attest_rs::tdx_att_extend(&event) {
|
match tdx_att_extend(&event) {
|
||||||
tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => Ok(()),
|
tdx_attest_error_t::TDX_ATTEST_SUCCESS => Ok(()),
|
||||||
error_code => Err(error_code.into()),
|
error_code => Err(error_code.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1394
crates/teepot/tests/sgx_quote_fmspc.rs
Normal file
1394
crates/teepot/tests/sgx_quote_fmspc.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Copyright (c) 2024-2025 Matter Labs
|
// Copyright (c) 2024-2025 Matter Labs
|
||||||
|
|
||||||
|
#[cfg(feature = "quote_op")]
|
||||||
mod sgx {
|
mod sgx {
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use std::time::{Duration, UNIX_EPOCH};
|
use std::time::{Duration, UNIX_EPOCH};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue