mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 07:03:56 +02:00
Merge pull request #309 from matter-labs/platform
feat: add platform-specific implementations for quote verification
This commit is contained in:
commit
1536e00d63
13 changed files with 596 additions and 567 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -4968,7 +4968,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",
|
||||||
|
@ -5003,6 +5002,7 @@ version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"intel-tee-quote-verification-sys",
|
"intel-tee-quote-verification-sys",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tdx-attest-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -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" }
|
||||||
|
|
4
crates/teepot-tee-quote-verification-rs/src/empty.rs
Normal file
4
crates/teepot-tee-quote-verification-rs/src/empty.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2025 Matter Labs
|
||||||
|
|
||||||
|
pub const NOTHING_TO_SEE_HERE: u8 = 0;
|
561
crates/teepot-tee-quote-verification-rs/src/intel.rs
Normal file
561
crates/teepot-tee-quote-verification-rs/src/intel.rs
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024-2025 Matter Labs
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
//! Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP)
|
||||||
|
//! Rust wrapper for Quote Verification Library
|
||||||
|
//! ================================================
|
||||||
|
//!
|
||||||
|
//! 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 std::{marker::PhantomData, ops::Deref, slice};
|
||||||
|
|
||||||
|
use intel_tee_quote_verification_sys as qvl_sys;
|
||||||
|
pub use qvl_sys::{
|
||||||
|
quote3_error_t, sgx_ql_qe_report_info_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t,
|
||||||
|
sgx_ql_qve_collateral_t, sgx_ql_request_policy_t, sgx_qv_path_type_t, tdx_ql_qve_collateral_t,
|
||||||
|
tee_qv_free_collateral, tee_supp_data_descriptor_t,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// When the Quoting Verification Library is linked to a process, it needs to know the proper enclave loading policy.
|
||||||
|
/// The library may be linked with a long lived process, such as a service, where it can load the enclaves and leave
|
||||||
|
/// them loaded (persistent). This better ensures that the enclaves will be available upon quote requests and not subject
|
||||||
|
/// to EPC limitations if loaded on demand. However, if the Quoting library is linked with an application process, there
|
||||||
|
/// may be many applications with the Quoting library and a better utilization of EPC is to load and unloaded the quoting
|
||||||
|
/// enclaves on demand (ephemeral). The library will be shipped with a default policy of loading enclaves and leaving
|
||||||
|
/// them loaded until the library is unloaded (PERSISTENT). If the policy is set to EPHEMERAL, then the QE and PCE will
|
||||||
|
/// be loaded and unloaded on-demand. If either enclave is already loaded when the policy is change to EPHEMERAL, the
|
||||||
|
/// enclaves will be unloaded before returning.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **policy**\
|
||||||
|
/// Set the requested enclave loading policy to either *SGX_QL_PERSISTENT*, *SGX_QL_EPHEMERAL* or *SGX_QL_DEFAULT*.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// - ***SGX_QL_SUCCESS***\
|
||||||
|
/// Successfully set the enclave loading policy for the quoting library's enclaves.\
|
||||||
|
/// - ***SGX_QL_UNSUPPORTED_LOADING_POLICY***\
|
||||||
|
/// The selected policy is not support by the quoting library.\
|
||||||
|
/// - ***SGX_QL_ERROR_UNEXPECTED***\
|
||||||
|
/// Unexpected internal error.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use teepot_tee_quote_verification_rs::*;
|
||||||
|
///
|
||||||
|
/// let policy = sgx_ql_request_policy_t::SGX_QL_DEFAULT;
|
||||||
|
/// let ret = sgx_qv_set_enclave_load_policy(policy);
|
||||||
|
///
|
||||||
|
/// assert_eq!(ret, quote3_error_t::SGX_QL_SUCCESS);
|
||||||
|
/// ```
|
||||||
|
pub fn sgx_qv_set_enclave_load_policy(policy: sgx_ql_request_policy_t) -> quote3_error_t {
|
||||||
|
unsafe { qvl_sys::sgx_qv_set_enclave_load_policy(policy) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get SGX supplemental data required size.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Size of the supplemental data in bytes.
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_ERROR_QVL_QVE_MISMATCH*
|
||||||
|
/// - *SGX_QL_ENCLAVE_LOAD_ERROR*
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use teepot_tee_quote_verification_rs::*;
|
||||||
|
///
|
||||||
|
/// let data_size = sgx_qv_get_quote_supplemental_data_size().unwrap();
|
||||||
|
///
|
||||||
|
/// assert_eq!(data_size, std::mem::size_of::<sgx_ql_qv_supplemental_t>() as u32);
|
||||||
|
/// ```
|
||||||
|
pub fn sgx_qv_get_quote_supplemental_data_size() -> Result<u32, quote3_error_t> {
|
||||||
|
let mut data_size = 0u32;
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::sgx_qv_get_quote_supplemental_data_size(&mut data_size) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => Ok(data_size),
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform SGX ECDSA quote verification.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **quote**\
|
||||||
|
/// SGX Quote, presented as u8 vector.
|
||||||
|
/// - **quote_collateral**\
|
||||||
|
/// Quote Certification Collateral provided by the caller.
|
||||||
|
/// - **expiration_check_date**\
|
||||||
|
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
||||||
|
/// - **qve_report_info**\
|
||||||
|
/// This parameter can be used in 2 ways.\
|
||||||
|
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
||||||
|
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
||||||
|
/// - **supplemental_data_size**\
|
||||||
|
/// Size of the supplemental data (in bytes).
|
||||||
|
/// - **supplemental_data**\
|
||||||
|
/// The parameter is optional. If it is None, supplemental_data_size must be 0.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Result type of (collateral_expiration_status, verification_result).
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
||||||
|
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
||||||
|
/// - *SGX_QL_ERROR_UNEXPECTED*
|
||||||
|
///
|
||||||
|
pub fn sgx_qv_verify_quote(
|
||||||
|
quote: &[u8],
|
||||||
|
quote_collateral: Option<&Collateral>,
|
||||||
|
expiration_check_date: i64,
|
||||||
|
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
||||||
|
supplemental_data_size: u32,
|
||||||
|
supplemental_data: Option<&mut sgx_ql_qv_supplemental_t>,
|
||||||
|
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
||||||
|
let mut collateral_expiration_status = 1u32;
|
||||||
|
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
||||||
|
|
||||||
|
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
||||||
|
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
||||||
|
|
||||||
|
let p_qve_report_info = match qve_report_info {
|
||||||
|
Some(p) => p,
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
let p_supplemental_data = match supplemental_data {
|
||||||
|
Some(p) => p as *mut sgx_ql_qv_supplemental_t as *mut u8,
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::sgx_qv_verify_quote(
|
||||||
|
quote.as_ptr(),
|
||||||
|
quote.len() as u32,
|
||||||
|
p_quote_collateral,
|
||||||
|
expiration_check_date,
|
||||||
|
&mut collateral_expiration_status,
|
||||||
|
&mut quote_verification_result,
|
||||||
|
p_qve_report_info,
|
||||||
|
supplemental_data_size,
|
||||||
|
p_supplemental_data,
|
||||||
|
) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => {
|
||||||
|
Ok((collateral_expiration_status, quote_verification_result))
|
||||||
|
}
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get TDX supplemental data required size.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Size of the supplemental data in bytes.
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_ERROR_QVL_QVE_MISMATCH*
|
||||||
|
/// - *SGX_QL_ENCLAVE_LOAD_ERROR*
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// use teepot_tee_quote_verification_rs::*;
|
||||||
|
///
|
||||||
|
/// let data_size = tdx_qv_get_quote_supplemental_data_size().unwrap();
|
||||||
|
///
|
||||||
|
/// assert_eq!(data_size, std::mem::size_of::<sgx_ql_qv_supplemental_t>() as u32);
|
||||||
|
/// ```
|
||||||
|
pub fn tdx_qv_get_quote_supplemental_data_size() -> Result<u32, quote3_error_t> {
|
||||||
|
let mut data_size = 0u32;
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::tdx_qv_get_quote_supplemental_data_size(&mut data_size) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => Ok(data_size),
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform TDX ECDSA quote verification.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **quote**\
|
||||||
|
/// TDX Quote, presented as u8 vector.
|
||||||
|
/// - **quote_collateral**\
|
||||||
|
/// Quote Certification Collateral provided by the caller.
|
||||||
|
/// - **expiration_check_date**\
|
||||||
|
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
||||||
|
/// - **qve_report_info**\
|
||||||
|
/// This parameter can be used in 2 ways.\
|
||||||
|
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
||||||
|
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
||||||
|
/// - **supplemental_data_size**\
|
||||||
|
/// Size of the supplemental data (in bytes).
|
||||||
|
/// - **supplemental_data**\
|
||||||
|
/// The parameter is optional. If it is None, supplemental_data_size must be 0.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Result type of (collateral_expiration_status, verification_result).
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
||||||
|
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
||||||
|
/// - *SGX_QL_ERROR_UNEXPECTED*
|
||||||
|
///
|
||||||
|
pub fn tdx_qv_verify_quote(
|
||||||
|
quote: &[u8],
|
||||||
|
quote_collateral: Option<&Collateral>,
|
||||||
|
expiration_check_date: i64,
|
||||||
|
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
||||||
|
supplemental_data_size: u32,
|
||||||
|
supplemental_data: Option<&mut sgx_ql_qv_supplemental_t>,
|
||||||
|
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
||||||
|
let mut collateral_expiration_status = 1u32;
|
||||||
|
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
||||||
|
|
||||||
|
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
||||||
|
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
||||||
|
|
||||||
|
let p_qve_report_info = match qve_report_info {
|
||||||
|
Some(p) => p,
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
let p_supplemental_data = match supplemental_data {
|
||||||
|
Some(p) => p as *mut sgx_ql_qv_supplemental_t as *mut u8,
|
||||||
|
None => std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::tdx_qv_verify_quote(
|
||||||
|
quote.as_ptr(),
|
||||||
|
quote.len() as u32,
|
||||||
|
p_quote_collateral,
|
||||||
|
expiration_check_date,
|
||||||
|
&mut collateral_expiration_status,
|
||||||
|
&mut quote_verification_result,
|
||||||
|
p_qve_report_info,
|
||||||
|
supplemental_data_size,
|
||||||
|
p_supplemental_data,
|
||||||
|
) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => {
|
||||||
|
Ok((collateral_expiration_status, quote_verification_result))
|
||||||
|
}
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the full path of QVE and QPL library.\
|
||||||
|
/// The function takes the enum and the corresponding full path.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **path_type**\
|
||||||
|
/// The type of binary being passed in.
|
||||||
|
/// - **path**\
|
||||||
|
/// It should be a valid full path.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// - ***SGX_QL_SUCCESS***\
|
||||||
|
/// Successfully set the full path.
|
||||||
|
/// - ***SGX_QL_ERROR_INVALID_PARAMETER***\
|
||||||
|
/// Path is not a valid full path or the path is too long.
|
||||||
|
///
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn sgx_qv_set_path(path_type: sgx_qv_path_type_t, path: &str) -> quote3_error_t {
|
||||||
|
match std::ffi::CString::new(path) {
|
||||||
|
Ok(path) => unsafe { qvl_sys::sgx_qv_set_path(path_type, path.as_ptr()) },
|
||||||
|
_ => quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Collateral {
|
||||||
|
pub major_version: u16,
|
||||||
|
pub minor_version: u16,
|
||||||
|
pub tee_type: u32,
|
||||||
|
pub pck_crl_issuer_chain: Box<[u8]>,
|
||||||
|
pub root_ca_crl: Box<[u8]>,
|
||||||
|
pub pck_crl: Box<[u8]>,
|
||||||
|
pub tcb_info_issuer_chain: Box<[u8]>,
|
||||||
|
pub tcb_info: Box<[u8]>,
|
||||||
|
pub qe_identity_issuer_chain: Box<[u8]>,
|
||||||
|
pub qe_identity: Box<[u8]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// referential struct
|
||||||
|
struct SgxQlQveCollateralT<'a> {
|
||||||
|
inner: sgx_ql_qve_collateral_t,
|
||||||
|
_phantom: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the referential struct
|
||||||
|
impl<'a> From<&'a Collateral> for SgxQlQveCollateralT<'a> {
|
||||||
|
fn from(data: &'a Collateral) -> Self {
|
||||||
|
let mut this = SgxQlQveCollateralT {
|
||||||
|
inner: sgx_ql_qve_collateral_t {
|
||||||
|
__bindgen_anon_1: Default::default(),
|
||||||
|
tee_type: data.tee_type,
|
||||||
|
pck_crl_issuer_chain: data.pck_crl_issuer_chain.as_ptr() as _,
|
||||||
|
pck_crl_issuer_chain_size: data.pck_crl_issuer_chain.len() as _,
|
||||||
|
root_ca_crl: data.root_ca_crl.as_ptr() as _,
|
||||||
|
root_ca_crl_size: data.root_ca_crl.len() as _,
|
||||||
|
pck_crl: data.pck_crl.as_ptr() as _,
|
||||||
|
pck_crl_size: data.pck_crl.len() as _,
|
||||||
|
tcb_info_issuer_chain: data.tcb_info_issuer_chain.as_ptr() as _,
|
||||||
|
tcb_info_issuer_chain_size: data.tcb_info_issuer_chain.len() as _,
|
||||||
|
tcb_info: data.tcb_info.as_ptr() as _,
|
||||||
|
tcb_info_size: data.tcb_info.len() as _,
|
||||||
|
qe_identity_issuer_chain: data.qe_identity_issuer_chain.as_ptr() as _,
|
||||||
|
qe_identity_issuer_chain_size: data.qe_identity_issuer_chain.len() as _,
|
||||||
|
qe_identity: data.qe_identity.as_ptr() as _,
|
||||||
|
qe_identity_size: data.qe_identity.len() as _,
|
||||||
|
},
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
this.inner.__bindgen_anon_1.__bindgen_anon_1.major_version = data.major_version;
|
||||||
|
this.inner.__bindgen_anon_1.__bindgen_anon_1.minor_version = data.minor_version;
|
||||||
|
this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for SgxQlQveCollateralT<'_> {
|
||||||
|
type Target = sgx_ql_qve_collateral_t;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get quote verification collateral.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **quote**\
|
||||||
|
/// SGX/TDX Quote, presented as u8 vector.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Result type of quote_collateral.
|
||||||
|
///
|
||||||
|
/// - **quote_collateral**\
|
||||||
|
/// This is the Quote Certification Collateral retrieved based on Quote.
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_PLATFORM_LIB_UNAVAILABLE*
|
||||||
|
/// - *SGX_QL_PCK_CERT_CHAIN_ERROR*
|
||||||
|
/// - *SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT*
|
||||||
|
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_OUT_OF_MEMORY*
|
||||||
|
/// - *SGX_QL_NO_QUOTE_COLLATERAL_DATA*
|
||||||
|
/// - *SGX_QL_ERROR_UNEXPECTED*
|
||||||
|
///
|
||||||
|
pub fn tee_qv_get_collateral(quote: &[u8]) -> Result<Collateral, quote3_error_t> {
|
||||||
|
fn try_into_collateral(
|
||||||
|
buf: *const sgx_ql_qve_collateral_t,
|
||||||
|
buf_len: u32,
|
||||||
|
) -> Result<Collateral, quote3_error_t> {
|
||||||
|
fn try_into_boxed_slice(
|
||||||
|
p: *mut ::std::os::raw::c_char,
|
||||||
|
size: u32,
|
||||||
|
) -> Result<Box<[u8]>, quote3_error_t> {
|
||||||
|
if p.is_null() || !p.is_aligned() {
|
||||||
|
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
|
||||||
|
}
|
||||||
|
Ok(Box::from(unsafe {
|
||||||
|
slice::from_raw_parts(p as _, size as _)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf.is_null()
|
||||||
|
|| (buf_len as usize) < size_of::<sgx_ql_qve_collateral_t>()
|
||||||
|
|| !buf.is_aligned()
|
||||||
|
{
|
||||||
|
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: buf is not null, buf_len is not zero, and buf is aligned.
|
||||||
|
let collateral = unsafe { *buf };
|
||||||
|
|
||||||
|
Ok(Collateral {
|
||||||
|
major_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.major_version },
|
||||||
|
minor_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.minor_version },
|
||||||
|
tee_type: collateral.tee_type,
|
||||||
|
pck_crl_issuer_chain: try_into_boxed_slice(
|
||||||
|
collateral.pck_crl_issuer_chain,
|
||||||
|
collateral.pck_crl_issuer_chain_size,
|
||||||
|
)?,
|
||||||
|
root_ca_crl: try_into_boxed_slice(collateral.root_ca_crl, collateral.root_ca_crl_size)?,
|
||||||
|
pck_crl: try_into_boxed_slice(collateral.pck_crl, collateral.pck_crl_size)?,
|
||||||
|
tcb_info_issuer_chain: try_into_boxed_slice(
|
||||||
|
collateral.tcb_info_issuer_chain,
|
||||||
|
collateral.tcb_info_issuer_chain_size,
|
||||||
|
)?,
|
||||||
|
tcb_info: try_into_boxed_slice(collateral.tcb_info, collateral.tcb_info_size)?,
|
||||||
|
qe_identity_issuer_chain: try_into_boxed_slice(
|
||||||
|
collateral.qe_identity_issuer_chain,
|
||||||
|
collateral.qe_identity_issuer_chain_size,
|
||||||
|
)?,
|
||||||
|
qe_identity: try_into_boxed_slice(collateral.qe_identity, collateral.qe_identity_size)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = std::ptr::null_mut();
|
||||||
|
let mut buf_len = 0u32;
|
||||||
|
|
||||||
|
match unsafe {
|
||||||
|
qvl_sys::tee_qv_get_collateral(quote.as_ptr(), quote.len() as u32, &mut buf, &mut buf_len)
|
||||||
|
} {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => {
|
||||||
|
let collateral = try_into_collateral(buf as _, buf_len);
|
||||||
|
|
||||||
|
match unsafe { tee_qv_free_collateral(buf) } {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => collateral,
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get supplemental data latest version and required size, support both SGX and TDX.
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **quote**\
|
||||||
|
/// SGX/TDX Quote, presented as u8 vector.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Result type of (version, data_size) tuple.
|
||||||
|
///
|
||||||
|
/// - **version**\
|
||||||
|
/// Latest version of the supplemental data.
|
||||||
|
/// - **data_size**\
|
||||||
|
/// The size of the buffer in bytes required to contain all of the supplemental data.
|
||||||
|
///
|
||||||
|
pub fn tee_get_supplemental_data_version_and_size(
|
||||||
|
quote: &[u8],
|
||||||
|
) -> Result<(u32, u32), quote3_error_t> {
|
||||||
|
let mut version = 0u32;
|
||||||
|
let mut data_size = 0u32;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::tee_get_supplemental_data_version_and_size(
|
||||||
|
quote.as_ptr(),
|
||||||
|
quote.len() as u32,
|
||||||
|
&mut version,
|
||||||
|
&mut data_size,
|
||||||
|
) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => Ok((version, data_size)),
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform quote verification for SGX and TDX.\
|
||||||
|
/// This API works the same as the old one, but takes a new parameter to describe the supplemental data (supp_data_descriptor).
|
||||||
|
///
|
||||||
|
/// # Param
|
||||||
|
/// - **quote**\
|
||||||
|
/// SGX/TDX Quote, presented as u8 vector.
|
||||||
|
/// - **quote_collateral**\
|
||||||
|
/// Quote Certification Collateral provided by the caller.
|
||||||
|
/// - **expiration_check_date**\
|
||||||
|
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
||||||
|
/// - **qve_report_info**\
|
||||||
|
/// This parameter can be used in 2 ways.\
|
||||||
|
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
||||||
|
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
||||||
|
/// - **supp_datal_descriptor**\
|
||||||
|
/// *tee_supp_data_descriptor_t* structure.\
|
||||||
|
/// You can specify the major version of supplemental data by setting supp_datal_descriptor.major_version.\
|
||||||
|
/// If supp_datal_descriptor is None, no supplemental data is returned.\
|
||||||
|
/// If supp_datal_descriptor.major_version == 0, then return the latest version of the *sgx_ql_qv_supplemental_t* structure.\
|
||||||
|
/// If supp_datal_descriptor.major_version <= latest supported version, return the latest minor version associated with that major version.\
|
||||||
|
/// If supp_datal_descriptor.major_version > latest supported version, return an error *SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED*.
|
||||||
|
///
|
||||||
|
/// # Return
|
||||||
|
/// Result type of (collateral_expiration_status, verification_result).
|
||||||
|
///
|
||||||
|
/// Status code of the operation, one of:
|
||||||
|
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
||||||
|
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
||||||
|
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
||||||
|
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
||||||
|
/// - *SGX_QL_ERROR_UNEXPECTED*
|
||||||
|
///
|
||||||
|
pub fn tee_verify_quote(
|
||||||
|
quote: &[u8],
|
||||||
|
quote_collateral: Option<&Collateral>,
|
||||||
|
expiration_check_date: i64,
|
||||||
|
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
||||||
|
supp_data_descriptor: Option<&mut tee_supp_data_descriptor_t>,
|
||||||
|
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
||||||
|
let mut collateral_expiration_status = 1u32;
|
||||||
|
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
||||||
|
|
||||||
|
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
||||||
|
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
||||||
|
|
||||||
|
let p_qve_report_info = qve_report_info.map_or(std::ptr::null_mut(), |p| p);
|
||||||
|
|
||||||
|
let p_supp_data_descriptor = supp_data_descriptor.map_or(std::ptr::null_mut(), |p| p);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
match qvl_sys::tee_verify_quote(
|
||||||
|
quote.as_ptr(),
|
||||||
|
quote.len() as u32,
|
||||||
|
p_quote_collateral as _,
|
||||||
|
expiration_check_date,
|
||||||
|
&mut collateral_expiration_status,
|
||||||
|
&mut quote_verification_result,
|
||||||
|
p_qve_report_info,
|
||||||
|
p_supp_data_descriptor,
|
||||||
|
) {
|
||||||
|
quote3_error_t::SGX_QL_SUCCESS => {
|
||||||
|
Ok((collateral_expiration_status, quote_verification_result))
|
||||||
|
}
|
||||||
|
error_code => Err(error_code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,557 +1,11 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// Copyright (c) 2024-2025 Matter Labs
|
// Copyright (c) 2024-2025 Matter Labs
|
||||||
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
#[cfg_attr(all(target_os = "linux", target_arch = "x86_64"), path = "intel.rs")]
|
||||||
/*
|
#[cfg_attr(
|
||||||
* Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
|
not(all(target_os = "linux", target_arch = "x86_64")),
|
||||||
*
|
path = "empty.rs"
|
||||||
* Redistribution and use in source and binary forms, with or without
|
)]
|
||||||
* modification, are permitted provided that the following conditions
|
mod os;
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in
|
|
||||||
* the documentation and/or other materials provided with the
|
|
||||||
* distribution.
|
|
||||||
* * Neither the name of Intel Corporation nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
//! Intel(R) Software Guard Extensions Data Center Attestation Primitives (Intel(R) SGX DCAP)
|
|
||||||
//! Rust wrapper for Quote Verification Library
|
|
||||||
//! ================================================
|
|
||||||
//!
|
|
||||||
//! This is a safe wrapper for **sgx-dcap-quoteverify-sys**.
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
pub use os::*;
|
||||||
use std::{marker::PhantomData, ops::Deref, slice};
|
|
||||||
|
|
||||||
use intel_tee_quote_verification_sys as qvl_sys;
|
|
||||||
pub use qvl_sys::{
|
|
||||||
quote3_error_t, sgx_ql_qe_report_info_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t,
|
|
||||||
sgx_ql_qve_collateral_t, sgx_ql_request_policy_t, sgx_qv_path_type_t, tdx_ql_qve_collateral_t,
|
|
||||||
tee_qv_free_collateral, tee_supp_data_descriptor_t,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// When the Quoting Verification Library is linked to a process, it needs to know the proper enclave loading policy.
|
|
||||||
/// The library may be linked with a long lived process, such as a service, where it can load the enclaves and leave
|
|
||||||
/// them loaded (persistent). This better ensures that the enclaves will be available upon quote requests and not subject
|
|
||||||
/// to EPC limitations if loaded on demand. However, if the Quoting library is linked with an application process, there
|
|
||||||
/// may be many applications with the Quoting library and a better utilization of EPC is to load and unloaded the quoting
|
|
||||||
/// enclaves on demand (ephemeral). The library will be shipped with a default policy of loading enclaves and leaving
|
|
||||||
/// them loaded until the library is unloaded (PERSISTENT). If the policy is set to EPHEMERAL, then the QE and PCE will
|
|
||||||
/// be loaded and unloaded on-demand. If either enclave is already loaded when the policy is change to EPHEMERAL, the
|
|
||||||
/// enclaves will be unloaded before returning.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **policy**\
|
|
||||||
/// Set the requested enclave loading policy to either *SGX_QL_PERSISTENT*, *SGX_QL_EPHEMERAL* or *SGX_QL_DEFAULT*.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// - ***SGX_QL_SUCCESS***\
|
|
||||||
/// Successfully set the enclave loading policy for the quoting library's enclaves.\
|
|
||||||
/// - ***SGX_QL_UNSUPPORTED_LOADING_POLICY***\
|
|
||||||
/// The selected policy is not support by the quoting library.\
|
|
||||||
/// - ***SGX_QL_ERROR_UNEXPECTED***\
|
|
||||||
/// Unexpected internal error.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use teepot_tee_quote_verification_rs::*;
|
|
||||||
///
|
|
||||||
/// let policy = sgx_ql_request_policy_t::SGX_QL_DEFAULT;
|
|
||||||
/// let ret = sgx_qv_set_enclave_load_policy(policy);
|
|
||||||
///
|
|
||||||
/// assert_eq!(ret, quote3_error_t::SGX_QL_SUCCESS);
|
|
||||||
/// ```
|
|
||||||
pub fn sgx_qv_set_enclave_load_policy(policy: sgx_ql_request_policy_t) -> quote3_error_t {
|
|
||||||
unsafe { qvl_sys::sgx_qv_set_enclave_load_policy(policy) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get SGX supplemental data required size.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Size of the supplemental data in bytes.
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_ERROR_QVL_QVE_MISMATCH*
|
|
||||||
/// - *SGX_QL_ENCLAVE_LOAD_ERROR*
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use teepot_tee_quote_verification_rs::*;
|
|
||||||
///
|
|
||||||
/// let data_size = sgx_qv_get_quote_supplemental_data_size().unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(data_size, std::mem::size_of::<sgx_ql_qv_supplemental_t>() as u32);
|
|
||||||
/// ```
|
|
||||||
pub fn sgx_qv_get_quote_supplemental_data_size() -> Result<u32, quote3_error_t> {
|
|
||||||
let mut data_size = 0u32;
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::sgx_qv_get_quote_supplemental_data_size(&mut data_size) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => Ok(data_size),
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform SGX ECDSA quote verification.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **quote**\
|
|
||||||
/// SGX Quote, presented as u8 vector.
|
|
||||||
/// - **quote_collateral**\
|
|
||||||
/// Quote Certification Collateral provided by the caller.
|
|
||||||
/// - **expiration_check_date**\
|
|
||||||
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
|
||||||
/// - **qve_report_info**\
|
|
||||||
/// This parameter can be used in 2 ways.\
|
|
||||||
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
|
||||||
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
|
||||||
/// - **supplemental_data_size**\
|
|
||||||
/// Size of the supplemental data (in bytes).
|
|
||||||
/// - **supplemental_data**\
|
|
||||||
/// The parameter is optional. If it is None, supplemental_data_size must be 0.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Result type of (collateral_expiration_status, verification_result).
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
|
||||||
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
|
||||||
/// - *SGX_QL_ERROR_UNEXPECTED*
|
|
||||||
///
|
|
||||||
pub fn sgx_qv_verify_quote(
|
|
||||||
quote: &[u8],
|
|
||||||
quote_collateral: Option<&Collateral>,
|
|
||||||
expiration_check_date: i64,
|
|
||||||
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
|
||||||
supplemental_data_size: u32,
|
|
||||||
supplemental_data: Option<&mut sgx_ql_qv_supplemental_t>,
|
|
||||||
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
|
||||||
let mut collateral_expiration_status = 1u32;
|
|
||||||
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
|
||||||
|
|
||||||
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
|
||||||
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
|
||||||
|
|
||||||
let p_qve_report_info = match qve_report_info {
|
|
||||||
Some(p) => p,
|
|
||||||
None => std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
let p_supplemental_data = match supplemental_data {
|
|
||||||
Some(p) => p as *mut sgx_ql_qv_supplemental_t as *mut u8,
|
|
||||||
None => std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::sgx_qv_verify_quote(
|
|
||||||
quote.as_ptr(),
|
|
||||||
quote.len() as u32,
|
|
||||||
p_quote_collateral,
|
|
||||||
expiration_check_date,
|
|
||||||
&mut collateral_expiration_status,
|
|
||||||
&mut quote_verification_result,
|
|
||||||
p_qve_report_info,
|
|
||||||
supplemental_data_size,
|
|
||||||
p_supplemental_data,
|
|
||||||
) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => {
|
|
||||||
Ok((collateral_expiration_status, quote_verification_result))
|
|
||||||
}
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get TDX supplemental data required size.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Size of the supplemental data in bytes.
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_ERROR_QVL_QVE_MISMATCH*
|
|
||||||
/// - *SGX_QL_ENCLAVE_LOAD_ERROR*
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
/// ```
|
|
||||||
/// use teepot_tee_quote_verification_rs::*;
|
|
||||||
///
|
|
||||||
/// let data_size = tdx_qv_get_quote_supplemental_data_size().unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(data_size, std::mem::size_of::<sgx_ql_qv_supplemental_t>() as u32);
|
|
||||||
/// ```
|
|
||||||
pub fn tdx_qv_get_quote_supplemental_data_size() -> Result<u32, quote3_error_t> {
|
|
||||||
let mut data_size = 0u32;
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::tdx_qv_get_quote_supplemental_data_size(&mut data_size) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => Ok(data_size),
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform TDX ECDSA quote verification.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **quote**\
|
|
||||||
/// TDX Quote, presented as u8 vector.
|
|
||||||
/// - **quote_collateral**\
|
|
||||||
/// Quote Certification Collateral provided by the caller.
|
|
||||||
/// - **expiration_check_date**\
|
|
||||||
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
|
||||||
/// - **qve_report_info**\
|
|
||||||
/// This parameter can be used in 2 ways.\
|
|
||||||
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
|
||||||
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
|
||||||
/// - **supplemental_data_size**\
|
|
||||||
/// Size of the supplemental data (in bytes).
|
|
||||||
/// - **supplemental_data**\
|
|
||||||
/// The parameter is optional. If it is None, supplemental_data_size must be 0.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Result type of (collateral_expiration_status, verification_result).
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
|
||||||
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
|
||||||
/// - *SGX_QL_ERROR_UNEXPECTED*
|
|
||||||
///
|
|
||||||
pub fn tdx_qv_verify_quote(
|
|
||||||
quote: &[u8],
|
|
||||||
quote_collateral: Option<&Collateral>,
|
|
||||||
expiration_check_date: i64,
|
|
||||||
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
|
||||||
supplemental_data_size: u32,
|
|
||||||
supplemental_data: Option<&mut sgx_ql_qv_supplemental_t>,
|
|
||||||
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
|
||||||
let mut collateral_expiration_status = 1u32;
|
|
||||||
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
|
||||||
|
|
||||||
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
|
||||||
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
|
||||||
|
|
||||||
let p_qve_report_info = match qve_report_info {
|
|
||||||
Some(p) => p,
|
|
||||||
None => std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
let p_supplemental_data = match supplemental_data {
|
|
||||||
Some(p) => p as *mut sgx_ql_qv_supplemental_t as *mut u8,
|
|
||||||
None => std::ptr::null_mut(),
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::tdx_qv_verify_quote(
|
|
||||||
quote.as_ptr(),
|
|
||||||
quote.len() as u32,
|
|
||||||
p_quote_collateral,
|
|
||||||
expiration_check_date,
|
|
||||||
&mut collateral_expiration_status,
|
|
||||||
&mut quote_verification_result,
|
|
||||||
p_qve_report_info,
|
|
||||||
supplemental_data_size,
|
|
||||||
p_supplemental_data,
|
|
||||||
) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => {
|
|
||||||
Ok((collateral_expiration_status, quote_verification_result))
|
|
||||||
}
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the full path of QVE and QPL library.\
|
|
||||||
/// The function takes the enum and the corresponding full path.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **path_type**\
|
|
||||||
/// The type of binary being passed in.
|
|
||||||
/// - **path**\
|
|
||||||
/// It should be a valid full path.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// - ***SGX_QL_SUCCESS***\
|
|
||||||
/// Successfully set the full path.
|
|
||||||
/// - ***SGX_QL_ERROR_INVALID_PARAMETER***\
|
|
||||||
/// Path is not a valid full path or the path is too long.
|
|
||||||
///
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
pub fn sgx_qv_set_path(path_type: sgx_qv_path_type_t, path: &str) -> quote3_error_t {
|
|
||||||
match std::ffi::CString::new(path) {
|
|
||||||
Ok(path) => unsafe { qvl_sys::sgx_qv_set_path(path_type, path.as_ptr()) },
|
|
||||||
_ => quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct Collateral {
|
|
||||||
pub major_version: u16,
|
|
||||||
pub minor_version: u16,
|
|
||||||
pub tee_type: u32,
|
|
||||||
pub pck_crl_issuer_chain: Box<[u8]>,
|
|
||||||
pub root_ca_crl: Box<[u8]>,
|
|
||||||
pub pck_crl: Box<[u8]>,
|
|
||||||
pub tcb_info_issuer_chain: Box<[u8]>,
|
|
||||||
pub tcb_info: Box<[u8]>,
|
|
||||||
pub qe_identity_issuer_chain: Box<[u8]>,
|
|
||||||
pub qe_identity: Box<[u8]>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// referential struct
|
|
||||||
struct SgxQlQveCollateralT<'a> {
|
|
||||||
inner: sgx_ql_qve_collateral_t,
|
|
||||||
_phantom: PhantomData<&'a ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the referential struct
|
|
||||||
impl<'a> From<&'a Collateral> for SgxQlQveCollateralT<'a> {
|
|
||||||
fn from(data: &'a Collateral) -> Self {
|
|
||||||
let mut this = SgxQlQveCollateralT {
|
|
||||||
inner: sgx_ql_qve_collateral_t {
|
|
||||||
__bindgen_anon_1: Default::default(),
|
|
||||||
tee_type: data.tee_type,
|
|
||||||
pck_crl_issuer_chain: data.pck_crl_issuer_chain.as_ptr() as _,
|
|
||||||
pck_crl_issuer_chain_size: data.pck_crl_issuer_chain.len() as _,
|
|
||||||
root_ca_crl: data.root_ca_crl.as_ptr() as _,
|
|
||||||
root_ca_crl_size: data.root_ca_crl.len() as _,
|
|
||||||
pck_crl: data.pck_crl.as_ptr() as _,
|
|
||||||
pck_crl_size: data.pck_crl.len() as _,
|
|
||||||
tcb_info_issuer_chain: data.tcb_info_issuer_chain.as_ptr() as _,
|
|
||||||
tcb_info_issuer_chain_size: data.tcb_info_issuer_chain.len() as _,
|
|
||||||
tcb_info: data.tcb_info.as_ptr() as _,
|
|
||||||
tcb_info_size: data.tcb_info.len() as _,
|
|
||||||
qe_identity_issuer_chain: data.qe_identity_issuer_chain.as_ptr() as _,
|
|
||||||
qe_identity_issuer_chain_size: data.qe_identity_issuer_chain.len() as _,
|
|
||||||
qe_identity: data.qe_identity.as_ptr() as _,
|
|
||||||
qe_identity_size: data.qe_identity.len() as _,
|
|
||||||
},
|
|
||||||
_phantom: PhantomData,
|
|
||||||
};
|
|
||||||
this.inner.__bindgen_anon_1.__bindgen_anon_1.major_version = data.major_version;
|
|
||||||
this.inner.__bindgen_anon_1.__bindgen_anon_1.minor_version = data.minor_version;
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for SgxQlQveCollateralT<'_> {
|
|
||||||
type Target = sgx_ql_qve_collateral_t;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get quote verification collateral.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **quote**\
|
|
||||||
/// SGX/TDX Quote, presented as u8 vector.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Result type of quote_collateral.
|
|
||||||
///
|
|
||||||
/// - **quote_collateral**\
|
|
||||||
/// This is the Quote Certification Collateral retrieved based on Quote.
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_PLATFORM_LIB_UNAVAILABLE*
|
|
||||||
/// - *SGX_QL_PCK_CERT_CHAIN_ERROR*
|
|
||||||
/// - *SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT*
|
|
||||||
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_OUT_OF_MEMORY*
|
|
||||||
/// - *SGX_QL_NO_QUOTE_COLLATERAL_DATA*
|
|
||||||
/// - *SGX_QL_ERROR_UNEXPECTED*
|
|
||||||
///
|
|
||||||
pub fn tee_qv_get_collateral(quote: &[u8]) -> Result<Collateral, quote3_error_t> {
|
|
||||||
fn try_into_collateral(
|
|
||||||
buf: *const sgx_ql_qve_collateral_t,
|
|
||||||
buf_len: u32,
|
|
||||||
) -> Result<Collateral, quote3_error_t> {
|
|
||||||
fn try_into_boxed_slice(
|
|
||||||
p: *mut ::std::os::raw::c_char,
|
|
||||||
size: u32,
|
|
||||||
) -> Result<Box<[u8]>, quote3_error_t> {
|
|
||||||
if p.is_null() || !p.is_aligned() {
|
|
||||||
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
|
|
||||||
}
|
|
||||||
Ok(Box::from(unsafe {
|
|
||||||
slice::from_raw_parts(p as _, size as _)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
if buf.is_null()
|
|
||||||
|| (buf_len as usize) < size_of::<sgx_ql_qve_collateral_t>()
|
|
||||||
|| !buf.is_aligned()
|
|
||||||
{
|
|
||||||
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: buf is not null, buf_len is not zero, and buf is aligned.
|
|
||||||
let collateral = unsafe { *buf };
|
|
||||||
|
|
||||||
Ok(Collateral {
|
|
||||||
major_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.major_version },
|
|
||||||
minor_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.minor_version },
|
|
||||||
tee_type: collateral.tee_type,
|
|
||||||
pck_crl_issuer_chain: try_into_boxed_slice(
|
|
||||||
collateral.pck_crl_issuer_chain,
|
|
||||||
collateral.pck_crl_issuer_chain_size,
|
|
||||||
)?,
|
|
||||||
root_ca_crl: try_into_boxed_slice(collateral.root_ca_crl, collateral.root_ca_crl_size)?,
|
|
||||||
pck_crl: try_into_boxed_slice(collateral.pck_crl, collateral.pck_crl_size)?,
|
|
||||||
tcb_info_issuer_chain: try_into_boxed_slice(
|
|
||||||
collateral.tcb_info_issuer_chain,
|
|
||||||
collateral.tcb_info_issuer_chain_size,
|
|
||||||
)?,
|
|
||||||
tcb_info: try_into_boxed_slice(collateral.tcb_info, collateral.tcb_info_size)?,
|
|
||||||
qe_identity_issuer_chain: try_into_boxed_slice(
|
|
||||||
collateral.qe_identity_issuer_chain,
|
|
||||||
collateral.qe_identity_issuer_chain_size,
|
|
||||||
)?,
|
|
||||||
qe_identity: try_into_boxed_slice(collateral.qe_identity, collateral.qe_identity_size)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf = std::ptr::null_mut();
|
|
||||||
let mut buf_len = 0u32;
|
|
||||||
|
|
||||||
match unsafe {
|
|
||||||
qvl_sys::tee_qv_get_collateral(quote.as_ptr(), quote.len() as u32, &mut buf, &mut buf_len)
|
|
||||||
} {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => {
|
|
||||||
let collateral = try_into_collateral(buf as _, buf_len);
|
|
||||||
|
|
||||||
match unsafe { tee_qv_free_collateral(buf) } {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => collateral,
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get supplemental data latest version and required size, support both SGX and TDX.
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **quote**\
|
|
||||||
/// SGX/TDX Quote, presented as u8 vector.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Result type of (version, data_size) tuple.
|
|
||||||
///
|
|
||||||
/// - **version**\
|
|
||||||
/// Latest version of the supplemental data.
|
|
||||||
/// - **data_size**\
|
|
||||||
/// The size of the buffer in bytes required to contain all of the supplemental data.
|
|
||||||
///
|
|
||||||
pub fn tee_get_supplemental_data_version_and_size(
|
|
||||||
quote: &[u8],
|
|
||||||
) -> Result<(u32, u32), quote3_error_t> {
|
|
||||||
let mut version = 0u32;
|
|
||||||
let mut data_size = 0u32;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::tee_get_supplemental_data_version_and_size(
|
|
||||||
quote.as_ptr(),
|
|
||||||
quote.len() as u32,
|
|
||||||
&mut version,
|
|
||||||
&mut data_size,
|
|
||||||
) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => Ok((version, data_size)),
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform quote verification for SGX and TDX.\
|
|
||||||
/// This API works the same as the old one, but takes a new parameter to describe the supplemental data (supp_data_descriptor).
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// - **quote**\
|
|
||||||
/// SGX/TDX Quote, presented as u8 vector.
|
|
||||||
/// - **quote_collateral**\
|
|
||||||
/// Quote Certification Collateral provided by the caller.
|
|
||||||
/// - **expiration_check_date**\
|
|
||||||
/// This is the date that the QvE will use to determine if any of the inputted collateral have expired.
|
|
||||||
/// - **qve_report_info**\
|
|
||||||
/// This parameter can be used in 2 ways.\
|
|
||||||
/// - If qve_report_info is NOT None, the API will use Intel QvE to perform quote verification, and QvE will generate a report using the target_info in sgx_ql_qe_report_info_t structure.\
|
|
||||||
/// - if qve_report_info is None, the API will use QVL library to perform quote verification, note that the results can not be cryptographically authenticated in this mode.
|
|
||||||
/// - **supp_datal_descriptor**\
|
|
||||||
/// *tee_supp_data_descriptor_t* structure.\
|
|
||||||
/// You can specify the major version of supplemental data by setting supp_datal_descriptor.major_version.\
|
|
||||||
/// If supp_datal_descriptor is None, no supplemental data is returned.\
|
|
||||||
/// If supp_datal_descriptor.major_version == 0, then return the latest version of the *sgx_ql_qv_supplemental_t* structure.\
|
|
||||||
/// If supp_datal_descriptor.major_version <= latest supported version, return the latest minor version associated with that major version.\
|
|
||||||
/// If supp_datal_descriptor.major_version > latest supported version, return an error *SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED*.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// Result type of (collateral_expiration_status, verification_result).
|
|
||||||
///
|
|
||||||
/// Status code of the operation, one of:
|
|
||||||
/// - *SGX_QL_ERROR_INVALID_PARAMETER*
|
|
||||||
/// - *SGX_QL_QUOTE_FORMAT_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED*
|
|
||||||
/// - *SGX_QL_UNABLE_TO_GENERATE_REPORT*
|
|
||||||
/// - *SGX_QL_CRL_UNSUPPORTED_FORMAT*
|
|
||||||
/// - *SGX_QL_ERROR_UNEXPECTED*
|
|
||||||
///
|
|
||||||
pub fn tee_verify_quote(
|
|
||||||
quote: &[u8],
|
|
||||||
quote_collateral: Option<&Collateral>,
|
|
||||||
expiration_check_date: i64,
|
|
||||||
qve_report_info: Option<&mut sgx_ql_qe_report_info_t>,
|
|
||||||
supp_data_descriptor: Option<&mut tee_supp_data_descriptor_t>,
|
|
||||||
) -> Result<(u32, sgx_ql_qv_result_t), quote3_error_t> {
|
|
||||||
let mut collateral_expiration_status = 1u32;
|
|
||||||
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
|
|
||||||
|
|
||||||
let quote_collateral = quote_collateral.map(SgxQlQveCollateralT::from);
|
|
||||||
let p_quote_collateral = quote_collateral.as_deref().map_or(std::ptr::null(), |p| p);
|
|
||||||
|
|
||||||
let p_qve_report_info = qve_report_info.map_or(std::ptr::null_mut(), |p| p);
|
|
||||||
|
|
||||||
let p_supp_data_descriptor = supp_data_descriptor.map_or(std::ptr::null_mut(), |p| p);
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
match qvl_sys::tee_verify_quote(
|
|
||||||
quote.as_ptr(),
|
|
||||||
quote.len() as u32,
|
|
||||||
p_quote_collateral as _,
|
|
||||||
expiration_check_date,
|
|
||||||
&mut collateral_expiration_status,
|
|
||||||
&mut quote_verification_result,
|
|
||||||
p_qve_report_info,
|
|
||||||
p_supp_data_descriptor,
|
|
||||||
) {
|
|
||||||
quote3_error_t::SGX_QL_SUCCESS => {
|
|
||||||
Ok((collateral_expiration_status, quote_verification_result))
|
|
||||||
}
|
|
||||||
error_code => Err(error_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,15 +10,15 @@ 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]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
asn1_der.workspace = true
|
asn1_der.workspace = true
|
||||||
|
@ -49,6 +49,7 @@ serde_json.workspace = true
|
||||||
sha2.workspace = true
|
sha2.workspace = true
|
||||||
sha3.workspace = true
|
sha3.workspace = true
|
||||||
signature.workspace = true
|
signature.workspace = true
|
||||||
|
teepot-tee-quote-verification-rs = { path = "../teepot-tee-quote-verification-rs", optional = true }
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tracing.workspace = true
|
tracing.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,6 +16,7 @@ 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;
|
mod utils;
|
||||||
|
|
||||||
|
@ -644,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)
|
||||||
}
|
}
|
||||||
|
@ -690,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>,
|
||||||
|
|
|
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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