Skip to content

Commit aad2e3b

Browse files
authored
Merge pull request #965 from Dstack-TEE/codex/fix-mock-attestation-dcap-collateral
[STACKED on #964] fix(mock-attestation): model complete DCAP collateral
2 parents 467ee97 + 1c9d6f7 commit aad2e3b

2 files changed

Lines changed: 60 additions & 7 deletions

File tree

dstack/crates/mock-attestation/src/server.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ pub fn router(state: Arc<MockCollateralState>) -> Router {
6060
Router::new()
6161
.route("/sgx/certification/v4/pckcrl", get(pck_crl))
6262
.route("/sgx/certification/v4/rootcacrl", get(pccs_root_crl))
63+
// Older guest images use the SGX PCS prefix for shared DCAP collateral.
64+
// Serve both spellings so simulated TDX evidence remains compatible.
65+
.route("/sgx/certification/v4/tcb", get(tcb_info))
66+
.route("/sgx/certification/v4/qe/identity", get(qe_identity))
6367
.route("/tdx/certification/v4/tcb", get(tcb_info))
6468
.route("/tdx/certification/v4/qe/identity", get(qe_identity))
6569
.route("/vcek/v1/Milan/cert_chain", get(sev_ca_chain))
@@ -90,8 +94,11 @@ async fn pccs_root_crl(State(state): State<Arc<MockCollateralState>>) -> impl In
9094

9195
async fn pck_crl(State(state): State<Arc<MockCollateralState>>) -> impl IntoResponse {
9296
binary(
93-
state.tdx.root_crl_der(),
94-
Some(("SGX-PCK-CRL-Issuer-Chain", state.tdx.root_ca_pem())),
97+
state.tdx.pck_crl_der(),
98+
Some((
99+
"SGX-PCK-CRL-Issuer-Chain",
100+
state.tdx.sample_collateral().unwrap().pck_crl_issuer_chain,
101+
)),
95102
)
96103
}
97104

dstack/crates/mock-attestation/src/tdx.rs

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ const INTEL_QE_VENDOR_ID: [u8; 16] = [
3030
pub struct TdxGenerator {
3131
root: Certificate,
3232
root_signing_key: SigningKey,
33+
pck_ca: Certificate,
3334
pck: Certificate,
3435
pck_key: SigningKey,
36+
pck_crl: Vec<u8>,
3537
tcb_signer: Certificate,
3638
tcb_signer_key: SigningKey,
3739
qe_signer: Certificate,
@@ -88,12 +90,19 @@ impl TdxGenerator {
8890
},
8991
root_signing_key,
9092
) = make_root(&seed)?;
93+
let (pck_ca, pck_ca_key) = make_ca(
94+
"Mock Intel SGX PCK Platform CA",
95+
"tdx-pck-ca",
96+
&seed,
97+
&root,
98+
&root_key,
99+
)?;
91100
let (pck, pck_key) = make_leaf(
92101
"Mock Intel SGX PCK Certificate",
93102
"tdx-pck",
94103
&seed,
95-
&root,
96-
&root_key,
104+
&pck_ca,
105+
&pck_ca_key,
97106
true,
98107
)?;
99108
let (tcb_signer, tcb_signer_key) = make_leaf(
@@ -112,6 +121,17 @@ impl TdxGenerator {
112121
&root_key,
113122
false,
114123
)?;
124+
let pck_crl = CertificateRevocationListParams {
125+
this_update: fixed_time(MOCK_PKI_NOT_BEFORE)?,
126+
next_update: fixed_time(MOCK_PKI_NOT_AFTER)?,
127+
crl_number: SerialNumber::from(1u64),
128+
issuing_distribution_point: None,
129+
revoked_certs: Vec::new(),
130+
key_identifier_method: KeyIdMethod::Sha256,
131+
}
132+
.signed_by(&pck_ca, &pck_ca_key)?
133+
.der()
134+
.to_vec();
115135
let root_crl = CertificateRevocationListParams {
116136
this_update: fixed_time(MOCK_PKI_NOT_BEFORE)?,
117137
next_update: fixed_time(MOCK_PKI_NOT_AFTER)?,
@@ -126,8 +146,10 @@ impl TdxGenerator {
126146
Ok(Self {
127147
root,
128148
root_signing_key,
149+
pck_ca,
129150
pck,
130151
pck_key,
152+
pck_crl,
131153
tcb_signer,
132154
tcb_signer_key,
133155
qe_signer,
@@ -157,6 +179,10 @@ impl TdxGenerator {
157179
self.root_crl.clone()
158180
}
159181

182+
pub fn pck_crl_der(&self) -> Vec<u8> {
183+
self.pck_crl.clone()
184+
}
185+
160186
pub fn attest(&self, report_data: [u8; 64]) -> Result<TdxEvidence> {
161187
self.attest_with_rtmrs(
162188
report_data,
@@ -207,7 +233,8 @@ impl TdxGenerator {
207233
.map_err(|bytes: Vec<u8>| anyhow::anyhow!("invalid QE report size {}", bytes.len()))?;
208234
let qe_sig: Signature = self.pck_key.sign(&qe_report_bytes);
209235

210-
let pck_chain = format!("{}{}", self.pck.pem(), self.root.pem()).into_bytes();
236+
let pck_chain =
237+
format!("{}{}{}", self.pck.pem(), self.pck_ca.pem(), self.root.pem()).into_bytes();
211238
let qe_certification = QEReportCertificationData {
212239
qe_report: qe_report_bytes,
213240
qe_report_signature: qe_sig.to_bytes().into(),
@@ -287,9 +314,9 @@ impl TdxGenerator {
287314
"isvprodid":1, "tcbLevels":[{"tcb":{"isvsvn":1},"tcbDate":issue,"tcbStatus":"UpToDate"}]
288315
}).to_string();
289316
Ok(QuoteCollateralV3 {
290-
pck_crl_issuer_chain: self.root.pem(),
317+
pck_crl_issuer_chain: format!("{}{}", self.pck_ca.pem(), self.root.pem()),
291318
root_ca_crl: self.root_crl.clone(),
292-
pck_crl: self.root_crl.clone(),
319+
pck_crl: self.pck_crl.clone(),
293320
tcb_info_issuer_chain: format!("{}{}", self.tcb_signer.pem(), self.root.pem()),
294321
tcb_info_signature: sign_raw(&self.tcb_signer_key, tcb_info.as_bytes())?,
295322
tcb_info,
@@ -322,6 +349,25 @@ fn make_root(seed: &[u8; 32]) -> Result<(CertifiedKey, SigningKey)> {
322349
Ok((CertifiedKey { cert, key_pair }, signing_key))
323350
}
324351

352+
fn make_ca(
353+
name: &str,
354+
label: &str,
355+
seed: &[u8; 32],
356+
issuer: &Certificate,
357+
issuer_key: &KeyPair,
358+
) -> Result<(Certificate, KeyPair)> {
359+
let (key, _) = deterministic_key_pair(seed, label)?;
360+
let mut params = cert_params(name)?;
361+
params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
362+
params.key_usages.extend([
363+
KeyUsagePurpose::DigitalSignature,
364+
KeyUsagePurpose::KeyCertSign,
365+
KeyUsagePurpose::CrlSign,
366+
]);
367+
let cert = params.signed_by(&key, issuer, issuer_key)?;
368+
Ok((cert, key))
369+
}
370+
325371
fn make_leaf(
326372
name: &str,
327373
label: &str,

0 commit comments

Comments
 (0)