Skip to content

Commit 8f990ee

Browse files
authored
Merge pull request #8 from datachainlab/improve-docs
Fix Quote v4 verifier and improve docs Signed-off-by: Jun Kimura <jun.kimura@datachain.jp>
2 parents 46e65c2 + 0e293de commit 8f990ee

File tree

19 files changed

+508
-844
lines changed

19 files changed

+508
-844
lines changed

crates/quote-verifier/src/cert.rs

Lines changed: 41 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use dcap_types::cert::{SgxExtensionTcbLevel, SgxExtensions};
55
use dcap_types::tcbinfo::{TcbComponent, TcbInfoV3};
66
use dcap_types::TcbInfoV3TcbStatus;
77
use dcap_types::{SGX_TEE_TYPE, TDX_TEE_TYPE};
8-
use x509_parser::oid_registry::OID_X509_EXT_CRL_DISTRIBUTION_POINTS;
98
use x509_parser::prelude::*;
109

10+
/// Parse a PEM-encoded certificate chain into a vector of `X509Certificate`.
1111
pub fn parse_certchain(pem_certs: &[Pem]) -> crate::Result<Vec<X509Certificate>> {
1212
Ok(pem_certs
1313
.iter()
@@ -44,7 +44,7 @@ pub fn verify_crl_signature(
4444
verify_p256_signature_der(data, signature, public_key)
4545
}
4646

47-
// verify_certchain_signature just verify that the certchain signature matches, any other checks will be done by the caller
47+
/// verify_certchain_signature just verify that the certchain signature matches, any other checks will be done by the caller
4848
pub fn verify_certchain_signature(
4949
certs: &[&X509Certificate],
5050
root_cert: &X509Certificate,
@@ -61,67 +61,52 @@ pub fn verify_certchain_signature(
6161
verify_certificate(prev_cert, root_cert)
6262
}
6363

64+
/// Get the Subject Common Name (CN) from a certificate.
6465
pub fn get_x509_subject_cn(cert: &X509Certificate) -> String {
6566
let subject = cert.subject();
6667
let cn = subject.iter_common_name().next().unwrap();
6768
cn.as_str().unwrap().to_string()
6869
}
6970

71+
/// Get the Issuer Common Name (CN) from a certificate.
7072
pub fn get_x509_issuer_cn(cert: &X509Certificate) -> String {
7173
let issuer = cert.issuer();
7274
let cn = issuer.iter_common_name().next().unwrap();
7375
cn.as_str().unwrap().to_string()
7476
}
7577

76-
pub fn get_crl_uri(cert: &X509Certificate) -> Option<String> {
77-
let crl_ext = cert
78-
.get_extension_unique(&OID_X509_EXT_CRL_DISTRIBUTION_POINTS)
79-
.unwrap()
80-
.unwrap();
81-
let crl_uri = match crl_ext.parsed_extension() {
82-
ParsedExtension::CRLDistributionPoints(crls) => {
83-
match &crls.iter().next().unwrap().distribution_point {
84-
Some(DistributionPointName::FullName(uri)) => {
85-
let uri = &uri[0];
86-
match uri {
87-
GeneralName::URI(uri) => Some(uri.to_string()),
88-
_ => None,
89-
}
90-
}
91-
_ => None,
92-
}
93-
}
94-
_ => {
95-
unreachable!();
96-
}
97-
};
98-
crl_uri
99-
}
100-
101-
/// https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/7e5b2a13ca5472de8d97dd7d7024c2ea5af9a6ba/Src/AttestationLibrary/src/Verifiers/Checks/TcbLevelCheck.cpp#L129-L181
102-
pub fn get_sgx_tdx_fmspc_tcbstatus_v3(
78+
/// Get the TCB status of the SGX and TDX corresponding to the given SVN from the TCB Info V3.
79+
/// This function returns the TCB status of the SGX and TDX, and the advisory IDs.
80+
/// ref. <https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/7e5b2a13ca5472de8d97dd7d7024c2ea5af9a6ba/Src/AttestationLibrary/src/Verifiers/Checks/TcbLevelCheck.cpp#L129-L181>
81+
///
82+
/// # Arguments
83+
/// * `tee_type` - The type of TEE (SGX or TDX)
84+
/// * `tee_tcb_svn` - The TCB SVN of the TEE (only for TDX)
85+
/// * `sgx_extensions` - The SGX Extensions from the PCK Certificate
86+
/// * `tcbinfov3` - The TCB Info V3
87+
/// # Returns
88+
/// * `(sgx_tcb_status, tdx_tcb_status, advisory_ids)` - The TCB status of the SGX and TDX, and the advisory IDs
89+
pub fn get_sgx_tdx_tcb_status_v3(
10390
tee_type: u32,
10491
tee_tcb_svn: Option<[u8; 16]>,
105-
// SGX Extensions from the PCK Certificate
10692
sgx_extensions: &SgxExtensions,
10793
tcbinfov3: &TcbInfoV3,
10894
) -> crate::Result<(TcbInfoV3TcbStatus, Option<TcbInfoV3TcbStatus>, Vec<String>)> {
109-
let is_tdx = tee_type == TDX_TEE_TYPE && tcbinfov3.tcb_info.id == "TDX";
110-
if !is_tdx {
111-
// check if tee_type and tcb_info.id are consistent
112-
assert!(tee_type == SGX_TEE_TYPE && tcbinfov3.tcb_info.id == "SGX");
113-
}
114-
115-
let is_tdx = if tee_type == SGX_TEE_TYPE {
116-
false
95+
if tee_type == SGX_TEE_TYPE {
96+
if tcbinfov3.tcb_info.id != "SGX" {
97+
bail!("Invalid TCB Info ID for SGX TEE Type");
98+
} else if tee_tcb_svn.is_some() {
99+
bail!("SGX TCB SVN is not needed");
100+
}
117101
} else if tee_type == TDX_TEE_TYPE {
118-
if tee_tcb_svn.is_none() {
102+
if tcbinfov3.tcb_info.id != "TDX" {
103+
bail!("Invalid TCB Info ID for TDX TEE Type");
104+
} else if tee_tcb_svn.is_none() {
119105
bail!("TDX TCB SVN is missing");
120106
}
121-
true
122107
} else {
123108
bail!("Unsupported TEE type: {}", tee_type);
124-
};
109+
}
125110

126111
// ref. https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/7e5b2a13ca5472de8d97dd7d7024c2ea5af9a6ba/Src/AttestationLibrary/src/Verifiers/QuoteVerifier.cpp#L117
127112
if sgx_extensions.fmspc != tcbinfov3.tcb_info.fmspc()? {
@@ -148,15 +133,16 @@ pub fn get_sgx_tdx_fmspc_tcbstatus_v3(
148133
&& extension_pcesvn >= tcb_level.tcb.pcesvn
149134
{
150135
sgx_tcb_status = Some(TcbInfoV3TcbStatus::from_str(tcb_level.tcb_status.as_str())?);
151-
if !is_tdx {
136+
if tee_type == SGX_TEE_TYPE {
152137
return Ok((
153138
sgx_tcb_status.unwrap(),
154139
None,
155140
tcb_level.advisory_ids.clone().unwrap_or_default(),
156141
));
157142
}
158143
}
159-
if is_tdx && sgx_tcb_status.is_some() {
144+
145+
if tee_type == TDX_TEE_TYPE && sgx_tcb_status.is_some() {
160146
let tdxtcbcomponents = match &tcb_level.tcb.tdxtcbcomponents {
161147
Some(cmps) => cmps,
162148
None => bail!("TDX TCB Components are missing"),
@@ -178,6 +164,18 @@ pub fn get_sgx_tdx_fmspc_tcbstatus_v3(
178164
}
179165
}
180166

167+
/// Merge two vectors of advisory ids into one vector
168+
/// This function will remove any duplicates
169+
pub fn merge_advisory_ids(advisory_ids: Vec<String>, advisory_ids2: Vec<String>) -> Vec<String> {
170+
let mut ids = advisory_ids
171+
.into_iter()
172+
.chain(advisory_ids2)
173+
.collect::<Vec<_>>();
174+
ids.sort();
175+
ids.dedup();
176+
ids
177+
}
178+
181179
fn match_sgxtcbcomp(tcb: &SgxExtensionTcbLevel, sgxtcbcomponents: &[TcbComponent; 16]) -> bool {
182180
// Compare all of the SGX TCB Comp SVNs retrieved from the SGX PCK Certificate (from 01 to 16) with the corresponding values of SVNs in sgxtcbcomponents array of TCB Level.
183181
// If all SGX TCB Comp SVNs in the certificate are greater or equal to the corresponding values in TCB Level, then return true.
@@ -197,15 +195,3 @@ fn match_tdxtcbcomp(tee_tcb_svn: &[u8; 16], tdxtcbcomponents: &[TcbComponent; 16
197195
.zip(tdxtcbcomponents.iter())
198196
.all(|(tee, tcb)| *tee >= tcb.svn)
199197
}
200-
201-
/// Merge two vectors of advisory ids into one vector
202-
/// This function will remove any duplicates
203-
pub fn merge_advisory_ids(advisory_ids: Vec<String>, advisory_ids2: Vec<String>) -> Vec<String> {
204-
let mut ids = advisory_ids
205-
.into_iter()
206-
.chain(advisory_ids2)
207-
.collect::<Vec<_>>();
208-
ids.sort();
209-
ids.dedup();
210-
ids
211-
}

crates/quote-verifier/src/collaterals.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,34 @@ use x509_parser::{certificate::X509Certificate, revocation_list::CertificateRevo
66

77
use crate::Result;
88

9-
/**
10-
* IntelCollateral is a struct that holds the collateral data that is required to verify the
11-
* authenticity of the quote. This includes the TCBInfo, QEIdentity, certificates and CRLs.
12-
*/
9+
/// IntelCollateral is a struct that holds the collateral data that is required to verify the
10+
/// authenticity of the quote. This includes the TCBInfo, QEIdentity, certificates and CRLs.
1311
#[derive(Clone, Debug, Default)]
1412
pub struct IntelCollateral {
1513
/// TCBInfo in JSON format
16-
/// ref. https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-tcb-info-model-v3
14+
/// ref. <https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-tcb-info-model-v3>
1715
pub tcbinfo_bytes: Vec<u8>,
1816
/// QEIdentity in JSON format
19-
/// ref. https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-enclave-identity-model-v2
17+
/// ref. <https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-enclave-identity-model-v2>
2018
pub qeidentity_bytes: Vec<u8>,
2119
/// SGX Intel Root CA certificate in DER format
22-
/// ref. https://certificates.trustedservices.intel.com/Intel_SGX_Provisioning_Certification_RootCA.pem
20+
/// ref. <https://certificates.trustedservices.intel.com/Intel_SGX_Provisioning_Certification_RootCA.pem>
2321
pub sgx_intel_root_ca_der: Vec<u8>,
2422
/// SGX TCB Signing certificate in DER format
2523
/// You can get this from the response header of the TCBInfo API
26-
/// ref. https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-tcb-info-v4
24+
/// ref. <https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-tcb-info-v4>
2725
pub sgx_tcb_signing_der: Vec<u8>,
2826
/// SGX Intel Root CA CRL in DER format
29-
/// ref. https://certificates.trustedservices.intel.com/IntelSGXRootCA.der
27+
/// ref. <https://certificates.trustedservices.intel.com/IntelSGXRootCA.der>
3028
pub sgx_intel_root_ca_crl_der: Vec<u8>,
3129
/// SGX PCK Platform/Processor CA CRL in DER format
3230
/// NOTE: This CRL issuer must be matched with the quote's PCK cert issuer
33-
/// ref. https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-revocation-v4
31+
/// ref. <https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-revocation-v4>
3432
pub sgx_pck_crl_der: Vec<u8>,
3533
}
3634

3735
impl IntelCollateral {
38-
/// Serializes the IntelCollateral struct into a Vec<u8>
36+
/// Serializes the IntelCollateral struct into a `Vec<u8>`
3937
pub fn to_bytes(&self) -> Vec<u8> {
4038
// serialization scheme is simple: the bytestream is made of 2 parts
4139
// the first contains a u32 length for each of the members

crates/quote-verifier/src/crl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl<'a> IntelSgxCrls<'a> {
142142

143143
/// Get the CRL type of the certificate
144144
/// We assume that the issuer of the certificate issues the only one type of CRL
145-
/// ref. p.5 https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/SGX_PCK_Certificate_CRL_Spec-1.4.pdf
145+
/// ref. p.5 <https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/SGX_PCK_Certificate_CRL_Spec-1.4.pdf>
146146
fn get_crl_type_from_cert(cert: &X509Certificate) -> Result<CrlType> {
147147
let issuer_cn = cert
148148
.issuer()
@@ -155,7 +155,7 @@ fn get_crl_type_from_cert(cert: &X509Certificate) -> Result<CrlType> {
155155

156156
/// Get the type of the CRL from the issuer common name of the CRL
157157
/// We assume that the issuer of the crl issues the only one type of CRL
158-
/// ref. p.5 https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/SGX_PCK_Certificate_CRL_Spec-1.4.pdf
158+
/// ref. p.5 <https://download.01.org/intel-sgx/sgx-dcap/1.22/linux/docs/SGX_PCK_Certificate_CRL_Spec-1.4.pdf>
159159
fn get_crl_type_from_crl(crl: &CertificateRevocationList) -> Result<CrlType> {
160160
get_crl_type_from_issuer_cn(
161161
crl.issuer()

crates/quote-verifier/src/crypto.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,28 @@ use p256::ecdsa::{signature::Verifier, Signature, VerifyingKey};
33
use sha2::{Digest, Sha256};
44
use sha3::Keccak256;
55

6-
// verify_p256_signature_bytes verifies a P256 ECDSA signature
7-
// using the provided data, signature, and public key.
8-
// The data is the message that was signed as a byte slice.
9-
// The signature is the signature (in raw form [r][s]) of the data as a byte slice. (64 bytes)
10-
// The public_key is the public key (in uncompressed form [4][x][y]) of the entity that signed the data. (65 bytes)
11-
// Returns true if the signature is valid, false otherwise.
6+
/// verify_p256_signature_bytes verifies a P256 ECDSA signature
7+
/// using the provided data, signature, and public key.
8+
/// # Arguments
9+
/// * `data` - The data that was signed.
10+
/// * `signature` - The signature is the signature (in raw form \[r\]\[s\]) of the data as a byte slice. (64 bytes)
11+
/// * `public_key` - The public key (in uncompressed form \[4\]\[\x\]\[y\]) of the entity that signed the data. (65 bytes)
12+
/// # Returns
13+
/// * Returns true if the signature is valid, false otherwise.
1214
pub fn verify_p256_signature_bytes(data: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()> {
1315
let signature = Signature::from_bytes(signature.into())?;
1416
let verifying_key = VerifyingKey::from_sec1_bytes(public_key)?;
1517
Ok(verifying_key.verify(data, &signature)?)
1618
}
1719

20+
/// verify_p256_signature_der verifies a P256 ECDSA signature
21+
/// using the provided data, signature, and public key.
22+
/// # Arguments
23+
/// * `data` - The data that was signed.
24+
/// * `signature_der` - The der encoded signature of the data as a byte slice.
25+
/// * `public_key` - The public key (in uncompressed form \[4\]\[\x\]\[y\]) of the entity that signed the data. (65 bytes)
26+
/// # Returns
27+
/// * Returns true if the signature is valid, false otherwise.
1828
pub fn verify_p256_signature_der(
1929
data: &[u8],
2030
signature_der: &[u8],
@@ -25,6 +35,7 @@ pub fn verify_p256_signature_der(
2535
Ok(verifying_key.verify(data, &signature)?)
2636
}
2737

38+
/// sha256sum returns the SHA-256 hash of the input data.
2839
pub fn sha256sum(data: &[u8]) -> [u8; 32] {
2940
let mut hasher = Sha256::new();
3041
hasher.update(data);
@@ -34,6 +45,7 @@ pub fn sha256sum(data: &[u8]) -> [u8; 32] {
3445
output
3546
}
3647

48+
/// keccak256sum returns the Keccak-256 hash of the input data.
3749
pub fn keccak256sum(data: &[u8]) -> [u8; 32] {
3850
let mut hasher = Keccak256::new();
3951
hasher.update(data);

crates/quote-verifier/src/enclave_identity.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ pub fn validate_qe_identityv2(
5959
})
6060
}
6161

62-
pub fn get_qe_tcbstatus(
62+
/// Get the TCB status for matching the ISV SVN of the QE report
63+
///
64+
/// ref. <https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/stable/Src/AttestationLibrary/src/Verifiers/EnclaveIdentityV2.cpp#L326>
65+
pub fn get_qe_tcb_status(
6366
qe_report_isv_svn: u16,
6467
qeidentityv2_tcb_levels: &[EnclaveIdentityV2TcbLevelItem],
6568
) -> Result<(EnclaveIdentityV2TcbStatus, Vec<String>)> {
@@ -154,23 +157,23 @@ mod tests {
154157
]))
155158
.unwrap();
156159

157-
let (status, advisory_ids) = get_qe_tcbstatus(9, &tcb_levels).unwrap();
160+
let (status, advisory_ids) = get_qe_tcb_status(9, &tcb_levels).unwrap();
158161
assert_eq!(status, EnclaveIdentityV2TcbStatus::UpToDate);
159162
assert!(advisory_ids.is_empty());
160163

161-
let (status, advisory_ids) = get_qe_tcbstatus(8, &tcb_levels).unwrap();
164+
let (status, advisory_ids) = get_qe_tcb_status(8, &tcb_levels).unwrap();
162165
assert_eq!(status, EnclaveIdentityV2TcbStatus::UpToDate);
163166
assert!(advisory_ids.is_empty());
164167

165-
let (status, advisory_ids) = get_qe_tcbstatus(7, &tcb_levels).unwrap();
168+
let (status, advisory_ids) = get_qe_tcb_status(7, &tcb_levels).unwrap();
166169
assert_eq!(status, EnclaveIdentityV2TcbStatus::OutOfDate);
167170
assert!(advisory_ids.is_empty());
168171

169-
let (status, advisory_ids) = get_qe_tcbstatus(5, &tcb_levels).unwrap();
172+
let (status, advisory_ids) = get_qe_tcb_status(5, &tcb_levels).unwrap();
170173
assert_eq!(status, EnclaveIdentityV2TcbStatus::Revoked);
171174
assert_eq!(advisory_ids, vec!["INTEL-SA-00615"]);
172175

173-
let res = get_qe_tcbstatus(4, &tcb_levels);
176+
let res = get_qe_tcb_status(4, &tcb_levels);
174177
assert!(res.is_err(), "{:?}", res);
175178
}
176179
}

crates/quote-verifier/src/quotes/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::collaterals::IntelCollateral;
66
use crate::crl::IntelSgxCrls;
77
use crate::crypto::sha256sum;
88
use crate::crypto::verify_p256_signature_bytes;
9-
use crate::enclave_identity::get_qe_tcbstatus;
9+
use crate::enclave_identity::get_qe_tcb_status;
1010
use crate::enclave_identity::validate_qe_identityv2;
1111
use crate::pck::validate_pck_cert;
1212
use crate::sgx_extensions::extract_sgx_extensions;
@@ -187,7 +187,7 @@ fn check_quote_header(quote_header: &QuoteHeader, expected_quote_version: u16) -
187187
}
188188
/// Verify the QE Report and return the TCB Status and Advisory IDs
189189
///
190-
/// ref. https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/29bd3b0a3b46c1159907d656b45f378f97e7e686/Src/AttestationLibrary/src/Verifiers/EnclaveReportVerifier.cpp#L47
190+
/// ref. <https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/29bd3b0a3b46c1159907d656b45f378f97e7e686/Src/AttestationLibrary/src/Verifiers/EnclaveReportVerifier.cpp#L47>
191191
/// do the following checks:
192192
/// - ensure that `ecdsa_attestation_key` and `qe_auth_data` are valid against the `qe_report.report_data`
193193
/// - validate the `qe_report` against the `qeidentityv2`
@@ -223,7 +223,7 @@ fn verify_qe_report(
223223
// https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/29bd3b0a3b46c1159907d656b45f378f97e7e686/Src/AttestationLibrary/src/Verifiers/EnclaveReportVerifier.cpp#L92
224224
// https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/7e5b2a13ca5472de8d97dd7d7024c2ea5af9a6ba/Src/AttestationLibrary/src/Verifiers/QuoteVerifier.cpp#L286
225225
let (tcb_status, advisory_ids) =
226-
get_qe_tcbstatus(qe_report.isv_svn, &qeidentityv2.enclave_identity.tcb_levels)?;
226+
get_qe_tcb_status(qe_report.isv_svn, &qeidentityv2.enclave_identity.tcb_levels)?;
227227

228228
Ok(QeTcb {
229229
tcb_evaluation_data_number: qeidentityv2.enclave_identity.tcb_evaluation_data_number,

crates/quote-verifier/src/quotes/version_3.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{check_quote_header, converge_tcb_status_with_qe_tcb, verify_quote_common, Result};
22
use crate::{
3-
cert::{get_sgx_tdx_fmspc_tcbstatus_v3, merge_advisory_ids},
3+
cert::{get_sgx_tdx_tcb_status_v3, merge_advisory_ids},
44
collaterals::IntelCollateral,
55
crypto::keccak256sum,
66
verifier::QuoteVerificationOutput,
@@ -41,7 +41,7 @@ pub fn verify_quote_v3(
4141
)?;
4242
let TcbInfo::V3(tcb_info_v3) = tcb_info;
4343
let (tcb_status, _, tcb_advisory_ids) =
44-
get_sgx_tdx_fmspc_tcbstatus_v3(quote.header.tee_type, None, &sgx_extensions, &tcb_info_v3)?;
44+
get_sgx_tdx_tcb_status_v3(quote.header.tee_type, None, &sgx_extensions, &tcb_info_v3)?;
4545

4646
Ok(QuoteVerificationOutput {
4747
version: VERIFIER_VERSION,

0 commit comments

Comments
 (0)