Skip to content

Commit 5e9f15f

Browse files
committed
[rom_ext, attestation] Fix DICE measurements
1. Report the DICE measurements in big-endian order. 2. Check the key IDs reported by the DICE certs. Signed-off-by: Chris Frantz <[email protected]> (cherry picked from commit 4f179e0) (cherry picked from commit 4b7192e)
1 parent 30cf60b commit 5e9f15f

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

sw/device/silicon_creator/lib/cert/dice.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ rom_error_t dice_cdi_0_cert_build(hmac_digest_t *rom_ext_measurement,
8585
uint8_t *cert, size_t *cert_size) {
8686
uint32_t rom_ext_security_version_be =
8787
__builtin_bswap32(rom_ext_security_version);
88+
hmac_digest_t rom_ext_hash = *rom_ext_measurement;
89+
util_reverse_bytes(&rom_ext_hash, sizeof(rom_ext_hash));
8890

8991
// Generate the TBS certificate.
9092
cdi_0_tbs_values_t cdi_0_tbs_params = {0};
9193

92-
TEMPLATE_SET(cdi_0_tbs_params, Cdi0, RomExtHash, rom_ext_measurement->digest);
94+
TEMPLATE_SET(cdi_0_tbs_params, Cdi0, RomExtHash, rom_ext_hash.digest);
9395
TEMPLATE_SET(cdi_0_tbs_params, Cdi0, RomExtSecurityVersion,
9496
&rom_ext_security_version_be);
9597
TEMPLATE_SET(cdi_0_tbs_params, Cdi0, OwnerIntermediatePubKeyEcX,
@@ -139,13 +141,17 @@ rom_error_t dice_cdi_1_cert_build(hmac_digest_t *owner_measurement,
139141
uint8_t *cert, size_t *cert_size) {
140142
uint32_t owner_security_version_be =
141143
__builtin_bswap32(owner_security_version);
144+
hmac_digest_t owner_hash = *owner_measurement;
145+
hmac_digest_t owner_manifest_hash = *owner_manifest_measurement;
146+
util_reverse_bytes(&owner_hash, sizeof(owner_hash));
147+
util_reverse_bytes(&owner_manifest_hash, sizeof(owner_manifest_hash));
142148

143149
// Generate the TBS certificate.
144150
cdi_1_tbs_values_t cdi_1_tbs_params = {0};
145151

146-
TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerHash, owner_measurement->digest);
152+
TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerHash, owner_hash.digest);
147153
TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerManifestHash,
148-
owner_manifest_measurement->digest);
154+
owner_manifest_hash.digest);
149155
TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerSecurityVersion,
150156
&owner_security_version_be);
151157
TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerPubKeyEcX, cdi_1_pubkey->x);

sw/host/tests/attestation/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ rust_binary(
1515
"@crate_index//:anyhow",
1616
"@crate_index//:base64ct",
1717
"@crate_index//:clap",
18+
"@crate_index//:hex",
1819
"@crate_index//:humantime",
1920
"@crate_index//:log",
2021
"@crate_index//:num-bigint-dig",

sw/host/tests/attestation/attestation_test.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use opentitanlib::test_utils::init::InitializeTest;
1818
use opentitanlib::uart::console::UartConsole;
1919
use opentitanlib::util::file::FromReader;
2020

21-
use ot_certs::template::{CertificateExtension, Value};
21+
use ot_certs::template::{AttributeType, CertificateExtension, Name, SubjectPublicKeyInfo, Value};
2222
use ot_certs::x509;
2323

2424
#[derive(Debug, Parser)]
@@ -68,6 +68,23 @@ fn get_base64_blob(haystack: &str, rx: &str) -> Result<Vec<u8>> {
6868
Ok(bin)
6969
}
7070

71+
fn check_public_key(key: &SubjectPublicKeyInfo, id: &[u8], subject: &Name) -> Result<bool> {
72+
let SubjectPublicKeyInfo::EcPublicKey(info) = key;
73+
74+
let mut material = Vec::new();
75+
material.extend(&info.public_key.x.get_value().to_bytes_be());
76+
material.extend(&info.public_key.y.get_value().to_bytes_be());
77+
let hash = sha256::sha256(&material).to_be_bytes();
78+
let keyid = &hash[..20];
79+
log::info!("computed id = {:?}", hex::encode(keyid));
80+
log::info!(" id = {:?}", hex::encode(id));
81+
82+
let name = subject[0][&AttributeType::SerialNumber].get_value();
83+
log::info!(" subject = {:?}", name);
84+
85+
Ok(keyid == id && &hex::encode(keyid) == name)
86+
}
87+
7188
fn attestation_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
7289
let uart = transport.uart("console")?;
7390
let capture = UartConsole::wait_for(
@@ -91,20 +108,26 @@ fn attestation_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
91108

92109
let image = Image::read_from_file(opts.init.bootstrap.bootstrap.as_deref().unwrap())?;
93110

94-
// TODO: determine the correct endianness for expressing these measurements.
95111
let measurements = image
96112
.subimages()?
97113
.iter()
98-
.map(|s| s.compute_digest().unwrap().to_le_bytes())
114+
.map(|s| s.compute_digest().unwrap().to_be_bytes())
99115
.collect::<Vec<_>>();
100116
let owner_measurements = [
101117
// The owner page digests should not include the signature or seal fields.
102-
sha256::sha256(&owner_page_0[0..OwnerBlock::SIGNATURE_OFFSET]).to_le_bytes(),
103-
sha256::sha256(&owner_page_1[0..OwnerBlock::SIGNATURE_OFFSET]).to_le_bytes(),
118+
sha256::sha256(&owner_page_0[0..OwnerBlock::SIGNATURE_OFFSET]).to_be_bytes(),
119+
sha256::sha256(&owner_page_1[0..OwnerBlock::SIGNATURE_OFFSET]).to_be_bytes(),
104120
];
105121

106122
let CertificateExtension::DiceTcbInfo(dice) = &cdi0.private_extensions[0];
107-
log::info!("Checking CDI_0 (ROM_EXT) DICE Extension: {dice:#?}");
123+
log::info!("Checking CDI_0 (ROM_EXT) DICE certificate: {cdi0:#?}");
124+
// Check that the subject key and subject key identifiers match.
125+
log::info!("Subject key:");
126+
assert!(check_public_key(
127+
&cdi0.subject_public_key_info,
128+
cdi0.subject_key_identifier.get_value(),
129+
&cdi0.subject,
130+
)?);
108131
assert_eq!(dice.model.get_value(), "ROM_EXT");
109132
assert_eq!(dice.vendor.get_value(), "OpenTitan");
110133
assert_eq!(dice.layer.get_value(), &BigUint::from(1u8));
@@ -113,7 +136,21 @@ fn attestation_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
113136
assert_eq!(fw_ids[0].digest.get_value(), &measurements[0]);
114137

115138
let CertificateExtension::DiceTcbInfo(dice) = &cdi1.private_extensions[0];
116-
log::info!("Checking CDI_1 (Owner) DICE Extension: {dice:#?}");
139+
log::info!("Checking CDI_1 (Owner) DICE certificate: {cdi1:#?}");
140+
// Check that the subject key and subject key identifiers match.
141+
log::info!("Subject key:");
142+
assert!(check_public_key(
143+
&cdi1.subject_public_key_info,
144+
cdi1.subject_key_identifier.get_value(),
145+
&cdi1.subject,
146+
)?);
147+
// Check that the authority key identifier of CDI_1 is the subject key of CDI_0.
148+
log::info!("Issuer key:");
149+
assert!(check_public_key(
150+
&cdi0.subject_public_key_info,
151+
cdi1.authority_key_identifier.get_value(),
152+
&cdi1.issuer,
153+
)?);
117154
assert_eq!(dice.model.get_value(), "Owner");
118155
assert_eq!(dice.vendor.get_value(), "OpenTitan");
119156
assert_eq!(dice.layer.get_value(), &BigUint::from(2u8));

0 commit comments

Comments
 (0)