Skip to content

Commit 328ea2e

Browse files
authored
Merge pull request #6 from datachainlab/tcb-eval-num
Add `min_tcb_evaluation_data_number` to Output Signed-off-by: Jun Kimura <jun.kimura@datachain.jp>
2 parents add8a70 + 2ddd792 commit 328ea2e

File tree

13 files changed

+156
-134
lines changed

13 files changed

+156
-134
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ jobs:
3030
curl -L https://risczero.com/install | bash
3131
echo "$HOME/.risc0/bin" >> $GITHUB_PATH
3232
- name: Install RISC Zero toolchain
33-
run: rzup install rust && rzup install cargo-risczero v1.2.2
33+
run: rzup install rust && rzup install cargo-risczero 1.2.2
3434
- run: . "/home/runner/.bashrc" && ZKDCAP_RISC0_BUILD=1 cargo build -r --manifest-path=./zkvm/risc0/Cargo.toml
3535
- run: git diff --exit-code

crates/collaterals/src/enclave_identity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl EnclaveIdentityV2Builder {
8585
}
8686
}
8787

88-
pub fn tcb_evaluation_data_number(self, tcb_evaluation_data_number: u64) -> Self {
88+
pub fn tcb_evaluation_data_number(self, tcb_evaluation_data_number: u32) -> Self {
8989
Self {
9090
obj: EnclaveIdentityV2Inner {
9191
tcb_evaluation_data_number,

crates/quote-verifier/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ mod quote_verifier_tests {
2424
use crate::cert::verify_crl_signature;
2525
use crate::collaterals::IntelCollateral;
2626
use crate::crypto::keccak256sum;
27-
use crate::quotes::{version_3::verify_quote_dcapv3, version_4::verify_quote_dcapv4};
27+
use crate::quotes::{version_3::verify_quote_v3, version_4::verify_quote_v4};
2828
use crate::tcbinfo::validate_tcbinfov3;
29-
use crate::verifier::VerifiedOutput;
29+
use crate::verifier::QuoteVerificationOutput;
3030
use dcap_types::quotes::{version_3::QuoteV3, version_4::QuoteV4};
3131
use dcap_types::tcbinfo::TcbInfoV3;
3232
use dcap_types::utils::{parse_crl_der, parse_pem, parse_x509_der, pem_to_der};
@@ -96,7 +96,7 @@ mod quote_verifier_tests {
9696
let res = QuoteV3::from_bytes(&dcap_quote_bytes);
9797
assert!(res.is_ok(), "failed to parse quotev3: {:?}", res.err());
9898
let dcap_quote = res.unwrap();
99-
let res = verify_quote_dcapv3(&dcap_quote, &collaterals, 1737458686);
99+
let res = verify_quote_v3(&dcap_quote, &collaterals, 1737458686);
100100
assert!(res.is_ok(), "verification failed: {:?}", res.err());
101101
let verified_output = res.unwrap();
102102
assert_eq!(verified_output.quote_version, 3);
@@ -124,7 +124,7 @@ mod quote_verifier_tests {
124124
"invalid `not_after_min`"
125125
);
126126
let bz = verified_output.to_bytes();
127-
let res = VerifiedOutput::from_bytes(&bz);
127+
let res = QuoteVerificationOutput::from_bytes(&bz);
128128
assert!(
129129
res.is_ok(),
130130
"failed to parse verified output: {:?}",
@@ -154,12 +154,12 @@ mod quote_verifier_tests {
154154
assert!(res.is_ok(), "failed to parse quotev4: {:?}", res.err());
155155
let dcap_quote = res.unwrap();
156156

157-
let res = verify_quote_dcapv4(&dcap_quote, &collaterals, 1737467060);
157+
let res = verify_quote_v4(&dcap_quote, &collaterals, 1737467060);
158158
assert!(res.is_ok(), "verification failed: {:?}", res.err());
159159
let verified_output = res.unwrap();
160160
assert_eq!(verified_output.tcb_status, Status::TcbOutOfDate);
161161
let bz = verified_output.to_bytes();
162-
let res = VerifiedOutput::from_bytes(&bz);
162+
let res = QuoteVerificationOutput::from_bytes(&bz);
163163
assert!(
164164
res.is_ok(),
165165
"failed to parse verified output: {:?}",

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

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ use dcap_types::{EnclaveIdentityV2TcbStatus, Status, TcbInfoV3TcbStatus};
2727
use dcap_types::{ECDSA_256_WITH_P256_CURVE, INTEL_QE_VENDOR_ID};
2828
use x509_parser::certificate::X509Certificate;
2929

30-
/// common_verify_and_fetch_tcb is a common function that verifies the quote and fetches the TCB info
30+
/// The TCB info of the QE
31+
#[derive(Debug, Clone, PartialEq, Eq)]
32+
pub struct QeTcb {
33+
pub tcb_evaluation_data_number: u32,
34+
pub tcb_status: EnclaveIdentityV2TcbStatus,
35+
pub advisory_ids: Vec<String>,
36+
}
37+
38+
/// Verify the quote and return the TCB info of the QE, SGX extensions from the PCK leaf certificate, TCB info of the platform, and the validity intersection of all collaterals
3139
///
3240
/// # Arguments
3341
///
@@ -45,13 +53,12 @@ use x509_parser::certificate::X509Certificate;
4553
/// # Returns
4654
///
4755
/// * A tuple containing:
48-
/// * The TCB status of the QE
49-
/// * The advisory IDs of the QE
56+
/// * The TCB info of the QE
5057
/// * The SGX extensions from the PCK leaf certificate
51-
/// * The TCB info
58+
/// * The TCB info of the platform
5259
/// * The validity intersection of all collaterals
5360
#[allow(clippy::too_many_arguments)]
54-
fn common_verify_and_fetch_tcb(
61+
fn verify_quote_common(
5562
quote_header: &QuoteHeader,
5663
quote_body: &QuoteBody,
5764
ecdsa_attestation_signature: &[u8; 64],
@@ -62,13 +69,7 @@ fn common_verify_and_fetch_tcb(
6269
qe_cert_data: &CertData,
6370
collaterals: &IntelCollateral,
6471
current_time: u64,
65-
) -> Result<(
66-
EnclaveIdentityV2TcbStatus,
67-
Vec<String>,
68-
SgxExtensions,
69-
TcbInfo,
70-
ValidityIntersection,
71-
)> {
72+
) -> Result<(QeTcb, SgxExtensions, TcbInfo, ValidityIntersection)> {
7273
// get the certchain embedded in the ecda quote signature data
7374
// this can be one of 5 types, and we only support type 5
7475
// https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/aa239d25a437a28f3f4de92c38f5b6809faac842/QuoteGeneration/quote_wrapper/common/inc/sgx_quote_3.h#L63C4-L63C112
@@ -143,41 +144,34 @@ fn common_verify_and_fetch_tcb(
143144
};
144145

145146
// validate QE Report and Quote Body
146-
let (qe_tcb_status, advisory_ids, pck_cert_sgx_extensions) = {
147-
let (qe_tcb_status, advisory_ids) = verify_qe_report(
148-
qe_report,
149-
ecdsa_attestation_pubkey,
150-
qe_auth_data,
151-
&qeidentityv2,
152-
&pck_leaf_cert,
153-
qe_report_signature,
154-
)?;
155-
verify_quote_attestation(
156-
quote_header,
157-
quote_body,
158-
ecdsa_attestation_pubkey,
159-
ecdsa_attestation_signature,
160-
)
161-
.context("Invalid quote attestation")?;
162-
163-
(
164-
qe_tcb_status,
165-
advisory_ids,
166-
extract_sgx_extensions(&pck_leaf_cert)?,
167-
)
168-
};
147+
let qe_tcb = verify_qe_report(
148+
qe_report,
149+
ecdsa_attestation_pubkey,
150+
qe_auth_data,
151+
&qeidentityv2,
152+
&pck_leaf_cert,
153+
qe_report_signature,
154+
)?;
155+
verify_quote_attestation(
156+
quote_header,
157+
quote_body,
158+
ecdsa_attestation_pubkey,
159+
ecdsa_attestation_signature,
160+
)
161+
.context("Invalid quote attestation")?;
162+
let pck_cert_sgx_extensions = extract_sgx_extensions(&pck_leaf_cert)?;
169163

170164
if !validity.validate() {
171165
bail!("Validity intersection provided from collaterals is invalid");
166+
} else if !validity.validate_time(current_time) {
167+
bail!(
168+
"certificates are expired: validity={} current_time={}",
169+
validity,
170+
current_time
171+
);
172172
}
173173

174-
Ok((
175-
qe_tcb_status,
176-
advisory_ids,
177-
pck_cert_sgx_extensions,
178-
tcb_info,
179-
validity,
180-
))
174+
Ok((qe_tcb, pck_cert_sgx_extensions, tcb_info, validity))
181175
}
182176

183177
fn check_quote_header(quote_header: &QuoteHeader, expected_quote_version: u16) -> Result<()> {
@@ -206,7 +200,7 @@ fn verify_qe_report(
206200
qeidentityv2: &EnclaveIdentityV2,
207201
pck_leaf_cert: &X509Certificate,
208202
qe_report_signature: &[u8; 64],
209-
) -> Result<(EnclaveIdentityV2TcbStatus, Vec<String>)> {
203+
) -> Result<QeTcb> {
210204
// validate QEReport then get TCB Status
211205
if !validate_qe_report_data(
212206
&qe_report.report_data,
@@ -228,7 +222,14 @@ fn verify_qe_report(
228222

229223
// https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/29bd3b0a3b46c1159907d656b45f378f97e7e686/Src/AttestationLibrary/src/Verifiers/EnclaveReportVerifier.cpp#L92
230224
// https://github.com/intel/SGX-TDX-DCAP-QuoteVerificationLibrary/blob/7e5b2a13ca5472de8d97dd7d7024c2ea5af9a6ba/Src/AttestationLibrary/src/Verifiers/QuoteVerifier.cpp#L286
231-
get_qe_tcbstatus(qe_report.isv_svn, &qeidentityv2.enclave_identity.tcb_levels)
225+
let (tcb_status, advisory_ids) =
226+
get_qe_tcbstatus(qe_report.isv_svn, &qeidentityv2.enclave_identity.tcb_levels)?;
227+
228+
Ok(QeTcb {
229+
tcb_evaluation_data_number: qeidentityv2.enclave_identity.tcb_evaluation_data_number,
230+
tcb_status,
231+
advisory_ids,
232+
})
232233
}
233234

234235
/// Verify the attestation signature for the quote (header + body) using the attestation public key
@@ -239,8 +240,7 @@ fn verify_quote_attestation(
239240
ecdsa_attestation_signature: &[u8; 64],
240241
) -> Result<()> {
241242
// verify the signature for attestation body
242-
let mut data = Vec::new();
243-
data.extend_from_slice(&quote_header.to_bytes());
243+
let mut data = quote_header.to_bytes().to_vec();
244244
match quote_body {
245245
QuoteBody::SGXQuoteBody(body) => data.extend_from_slice(&body.to_bytes()),
246246
QuoteBody::TD10QuoteBody(body) => data.extend_from_slice(&body.to_bytes()),

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

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,62 @@
1-
use super::{
2-
check_quote_header, common_verify_and_fetch_tcb, converge_tcb_status_with_qe_tcb, Result,
3-
};
1+
use super::{check_quote_header, converge_tcb_status_with_qe_tcb, verify_quote_common, Result};
42
use crate::{
53
cert::{get_sgx_tdx_fmspc_tcbstatus_v3, merge_advisory_ids},
64
collaterals::IntelCollateral,
75
crypto::keccak256sum,
8-
verifier::VerifiedOutput,
6+
verifier::QuoteVerificationOutput,
97
VERIFIER_VERSION,
108
};
11-
use anyhow::{bail, Context};
9+
use anyhow::Context;
10+
use core::cmp::min;
1211
use dcap_types::{
1312
quotes::{body::QuoteBody, version_3::QuoteV3},
1413
tcbinfo::TcbInfo,
1514
};
1615

17-
pub fn verify_quote_dcapv3(
16+
/// Verify the given DCAP quote v3 and return the verification output.
17+
///
18+
/// # Arguments
19+
/// - `quote`: The quote to be verified
20+
/// - `collateral`: The collateral data to be used for verification
21+
/// - `current_time`: The current time in seconds since the Unix epoch
22+
pub fn verify_quote_v3(
1823
quote: &QuoteV3,
19-
collaterals: &IntelCollateral,
24+
collateral: &IntelCollateral,
2025
current_time: u64,
21-
) -> Result<VerifiedOutput> {
26+
) -> Result<QuoteVerificationOutput> {
2227
check_quote_header(&quote.header, 3).context("invalid quote header")?;
2328

2429
let quote_body = QuoteBody::SGXQuoteBody(quote.isv_enclave_report);
25-
let (qe_tcb_status, qe_advisory_ids, sgx_extensions, tcb_info, validity) =
26-
common_verify_and_fetch_tcb(
27-
&quote.header,
28-
&quote_body,
29-
&quote.signature.isv_enclave_report_signature,
30-
&quote.signature.ecdsa_attestation_key,
31-
&quote.signature.qe_report,
32-
&quote.signature.qe_report_signature,
33-
&quote.signature.qe_auth_data.data,
34-
&quote.signature.qe_cert_data,
35-
collaterals,
36-
current_time,
37-
)?;
38-
if !validity.validate_time(current_time) {
39-
bail!(
40-
"certificates are expired: validity={} current_time={}",
41-
validity,
42-
current_time
43-
);
44-
}
30+
let (qe_status, sgx_extensions, tcb_info, validity) = verify_quote_common(
31+
&quote.header,
32+
&quote_body,
33+
&quote.signature.isv_enclave_report_signature,
34+
&quote.signature.ecdsa_attestation_key,
35+
&quote.signature.qe_report,
36+
&quote.signature.qe_report_signature,
37+
&quote.signature.qe_auth_data.data,
38+
&quote.signature.qe_cert_data,
39+
collateral,
40+
current_time,
41+
)?;
4542
let TcbInfo::V3(tcb_info_v3) = tcb_info;
4643
let (tcb_status, _, tcb_advisory_ids) =
4744
get_sgx_tdx_fmspc_tcbstatus_v3(quote.header.tee_type, None, &sgx_extensions, &tcb_info_v3)?;
4845

49-
Ok(VerifiedOutput {
46+
Ok(QuoteVerificationOutput {
5047
version: VERIFIER_VERSION,
5148
quote_version: quote.header.version,
5249
tee_type: quote.header.tee_type,
53-
tcb_status: converge_tcb_status_with_qe_tcb(tcb_status, qe_tcb_status),
50+
tcb_status: converge_tcb_status_with_qe_tcb(tcb_status, qe_status.tcb_status),
51+
min_tcb_evaluation_data_number: min(
52+
qe_status.tcb_evaluation_data_number,
53+
tcb_info_v3.tcb_info.tcb_evaluation_data_number,
54+
),
5455
fmspc: sgx_extensions.fmspc,
55-
sgx_intel_root_ca_hash: keccak256sum(collaterals.sgx_intel_root_ca_der.as_ref()),
56+
sgx_intel_root_ca_hash: keccak256sum(collateral.sgx_intel_root_ca_der.as_ref()),
5657
validity,
5758
quote_body,
58-
advisory_ids: merge_advisory_ids(tcb_advisory_ids, qe_advisory_ids),
59+
advisory_ids: merge_advisory_ids(tcb_advisory_ids, qe_status.advisory_ids),
5960
})
6061
}
6162

@@ -143,11 +144,13 @@ mod tests {
143144
// fmspc and tcb_levels must be consistent with the sgx extensions in the pck cert
144145
let tcb_info = TcbInfoV3Builder::new(true)
145146
.fmspc([0, 96, 106, 0, 0, 0])
147+
.tcb_evaluation_data_number(2)
146148
.tcb_levels(target_tcb_levels)
147149
.build_and_sign(&tcb_certchain.key)
148150
.unwrap();
149151

150152
let qe_identity = EnclaveIdentityV2Builder::new(EnclaveIdentityId::QE)
153+
.tcb_evaluation_data_number(1)
151154
.tcb_levels_json(json!([
152155
{
153156
"tcb": {
@@ -170,7 +173,9 @@ mod tests {
170173
};
171174

172175
let current_time = 1730000000;
173-
let res = verify_quote_dcapv3(&quote, &collateral, current_time);
176+
let res = verify_quote_v3(&quote, &collateral, current_time);
174177
assert!(res.is_ok(), "{:?}", res);
178+
let output = res.unwrap();
179+
assert_eq!(output.min_tcb_evaluation_data_number, 1);
175180
}
176181
}

0 commit comments

Comments
 (0)