Skip to content

Commit 8f598fc

Browse files
committed
Parse and verify certificate for AmdSevSnpTransparentDiceAttestationVerifier
This changes adds the remaining verification logic for the `AmdSevSnpTransparentDiceAttestationVerifier` verifier. In addition to verifying the transparent evidence, it will also verify that the `Evidence.signed_user_data_certificate` was signed by the final layer's key and extract the bytes. It places these bytes into an `EventAttestationResults` proto with a single entry. The key to this entry is "user-data-payload" which is hardcoded. Bug: 483663538 Change-Id: I036e106fc366d7c1eda8ce2c19f318858df912ad
1 parent c3f10ba commit 8f598fc

3 files changed

Lines changed: 62 additions & 7 deletions

File tree

oak_attestation_verification/src/results.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ const HYBRID_ENCRYPTION_PUBLIC_KEY_ID: &str = "oak-hybrid-encryption-public-key:
3939
/// signed by the enclave.
4040
const SIGNING_PUBLIC_KEY_ID: &str = "oak-signing-public-key:ecdsa-p256";
4141

42+
/// Denotes an artifact ID of the user data payload extracted from the signed
43+
/// user data certificate in the attestation evidence.
44+
const USER_DATA_PAYLOAD_ID: &str = "user-data-payload";
45+
4246
pub fn get_initial_measurement(results: &EventAttestationResults) -> Option<&Vec<u8>> {
4347
results.artifacts.get(INITIAL_MEASUREMENT_ID)
4448
}
@@ -85,6 +89,10 @@ pub fn set_signing_public_key(results: &mut EventAttestationResults, key: &[u8])
8589
results.artifacts.insert(SIGNING_PUBLIC_KEY_ID.to_string(), key.to_vec());
8690
}
8791

92+
pub fn set_user_data_payload(results: &mut EventAttestationResults, payload: &[u8]) {
93+
results.artifacts.insert(USER_DATA_PAYLOAD_ID.to_string(), payload.to_vec());
94+
}
95+
8896
/// Returns a reference to the event artifact in the attestation results
8997
/// specified by the given ID, or an error if that reference does not exist,
9098
/// or if there is more than a single reference (`artifact_id` key exists

oak_attestation_verification/src/verifier.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ use ecdsa::{Signature, signature::Verifier};
2424
use oak_attestation_verification_types::verifier::AttestationVerifier;
2525
use oak_dice::cert::{cose_key_to_verifying_key, get_public_key_from_claims_set};
2626
use oak_proto_rust::oak::attestation::v1::{
27-
AttestationResults, Endorsements, EventLog, Evidence, ExpectedValues, ExtractedEvidence,
28-
LayerEvidence, ReferenceValues, attestation_results::Status, endorsements, expected_values,
27+
AttestationResults, Endorsements, EventAttestationResults, EventLog, Evidence, ExpectedValues,
28+
ExtractedEvidence, LayerEvidence, ReferenceValues, attestation_results::Status, endorsements,
29+
expected_values,
2930
};
3031
use oak_time::{Clock, Instant};
3132
use p256::ecdsa::VerifyingKey;
@@ -35,6 +36,7 @@ use crate::{
3536
expect::get_expected_values,
3637
extract::{EventIdType, claims_set_from_serialized_cert, extract_event_data, extract_evidence},
3738
platform::verify_root_attestation_signature,
39+
results::set_user_data_payload,
3840
};
3941

4042
// We don't use additional authenticated data.
@@ -433,6 +435,39 @@ pub fn verify_dice_chain_and_extract_evidence(
433435
extract_evidence(evidence)
434436
}
435437

438+
/// Verifies the signed user data certificate and returns an
439+
/// [`EventAttestationResults`] containing the payload bytes.
440+
///
441+
/// Parses the provided `signed_user_data_certificate` bytes as a COSE_Sign1
442+
/// structure, verifies its signature using the given `verifying_key`, and
443+
/// returns the payload as an `EventAttestationResults` with the
444+
/// `user-data-payload` artifact key.
445+
pub fn verify_user_data_certificate(
446+
signed_user_data_certificate: &[u8],
447+
verifying_key: &VerifyingKey,
448+
) -> anyhow::Result<EventAttestationResults> {
449+
// Parse the signed user data certificate as a COSE_Sign1 structure.
450+
let user_data_cert = coset::CoseSign1::from_slice(signed_user_data_certificate)
451+
.map_err(|_cose_err| anyhow::anyhow!("could not parse signed user data certificate"))?;
452+
453+
// Verify the signature using the provided verification key.
454+
user_data_cert
455+
.verify_signature(ADDITIONAL_DATA, |signature, contents| {
456+
let sig = Signature::from_slice(signature)?;
457+
verifying_key.verify(contents, &sig)
458+
})
459+
.map_err(|error| anyhow::anyhow!(error))
460+
.context("verifying signed user data certificate signature")?;
461+
462+
// Extract the payload bytes and wrap in an EventAttestationResults.
463+
let payload = user_data_cert
464+
.payload
465+
.ok_or_else(|| anyhow::anyhow!("no payload in signed user data certificate"))?;
466+
let mut results = EventAttestationResults::default();
467+
set_user_data_payload(&mut results, &payload);
468+
Ok(results)
469+
}
470+
436471
/// Validates that the digest of the events captured in the event log are
437472
/// correctly described in the claims of the associated dice layers.
438473
// Claim entries are under different keys for standard events and transparent

oak_attestation_verification/src/verifiers.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use crate::{
4747
system::SystemPolicy,
4848
},
4949
results::get_initial_measurement,
50-
verifier::{EventLogType, verify_dice_chain},
50+
verifier::{EventLogType, verify_dice_chain, verify_user_data_certificate},
5151
};
5252

5353
// Base AMD SEV-SNP verifier that validates AMD SEV-SNP platform authenticity
@@ -203,10 +203,11 @@ impl AttestationVerifier for AmdSevSnpTransparentDiceAttestationVerifier {
203203
.context("verifying platform policy")?;
204204

205205
// Verify DICE chain integrity.
206-
// The output argument is ommited because last layer's certificate authority key
207-
// is not used to sign anything.
208-
let _ = verify_dice_chain(evidence, EventLogType::TransparentEventLog)
209-
.context("verifying DICE chain")?;
206+
// The output argument is recorded because it can be used to verify the
207+
// `Evidence.signed_user_data_certificate` structure.
208+
let last_layer_verifying_key =
209+
verify_dice_chain(evidence, EventLogType::TransparentEventLog)
210+
.context("verifying DICE chain")?;
210211

211212
let firmware_results = self
212213
.base_verifier
@@ -231,6 +232,17 @@ impl AttestationVerifier for AmdSevSnpTransparentDiceAttestationVerifier {
231232
event_attestation_results.extend(results);
232233
}
233234

235+
// Attestation has been verified. We now verify the signed user data
236+
// certificate, if present.
237+
if !evidence.signed_user_data_certificate.is_empty() {
238+
let user_data_result = verify_user_data_certificate(
239+
&evidence.signed_user_data_certificate,
240+
&last_layer_verifying_key,
241+
)
242+
.context("verifying signed user data certificate")?;
243+
event_attestation_results.push(user_data_result);
244+
}
245+
234246
Ok(AttestationResults {
235247
status: Status::Success.into(),
236248
extracted_evidence: None,

0 commit comments

Comments
 (0)