1 //! Test methods to confirm basic functionality of trait implementations.
2
3 extern crate alloc;
4 use authgraph_core::key::{
5 AesKey, EcSignKey, EcVerifyKey, EcdhSecret, HmacKey, Identity, Key, Nonce12, PseudoRandKey,
6 COMPONENT_NAME, COMPONENT_VERSION, CURVE25519_PRIV_KEY_LEN,
7 EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION, GUEST_OS_COMPONENT_NAME, IDENTITY_VERSION, INSTANCE_HASH,
8 RESETTABLE, SECURITY_VERSION,
9 };
10 use authgraph_core::keyexchange;
11 use authgraph_core::traits::{
12 AesGcm, Device, EcDh, EcDsa, Hkdf, Hmac, MonotonicClock, Rng, Sha256,
13 };
14 use authgraph_core::{ag_err, error::Error};
15 use authgraph_wire::ErrorCode;
16 use coset::{
17 cbor::Value,
18 iana::{self, EnumI64},
19 Algorithm, CborSerializable, CoseKey, CoseKeyBuilder, CoseSign1Builder, HeaderBuilder,
20 KeyOperation, KeyType, Label,
21 };
22 pub use diced_open_dice::CdiValues;
23 use std::ffi::CString;
24
25 /// UDS used to create the DICE chains in this test-util library.
26 pub const UDS: [u8; diced_open_dice::CDI_SIZE] = [
27 0x1d, 0xa5, 0xea, 0x90, 0x47, 0xfc, 0xb5, 0xf6, 0x47, 0x12, 0xd3, 0x65, 0x9c, 0xf2, 0x00, 0xe0,
28 0x06, 0xf7, 0xe8, 0x9e, 0x2f, 0xd0, 0x94, 0x7f, 0xc9, 0x9a, 0x9d, 0x40, 0xf7, 0xce, 0x13, 0x21,
29 ];
30
31 /// Sample value for instance hash
32 pub const SAMPLE_INSTANCE_HASH: [u8; 64] = [
33 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a,
34 0x7d, 0x7e, 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x9d, 0x55, 0x8a, 0xe9, 0x90,
35 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x9d, 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95,
36 0x59, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0x7d, 0x7e, 0xf5, 0x8e, 0xf5, 0x8e,
37 ];
38
39 /// Test basic [`Rng`] functionality.
test_rng<R: Rng>(rng: &mut R)40 pub fn test_rng<R: Rng>(rng: &mut R) {
41 let mut nonce1 = [0; 16];
42 let mut nonce2 = [0; 16];
43 rng.fill_bytes(&mut nonce1);
44 assert_ne!(nonce1, nonce2, "random value is all zeroes!");
45
46 rng.fill_bytes(&mut nonce2);
47 assert_ne!(nonce1, nonce2, "two random values match!");
48 }
49
50 /// Test basic [`MonotonicClock`] functionality.
test_clock<C: MonotonicClock>(clock: &C)51 pub fn test_clock<C: MonotonicClock>(clock: &C) {
52 let t1 = clock.now();
53 let t2 = clock.now();
54 assert!(t2.0 >= t1.0);
55 std::thread::sleep(std::time::Duration::from_millis(400));
56 let t3 = clock.now();
57 assert!(t3.0 > (t1.0 + 200));
58 }
59
60 /// Test basic [`Sha256`] functionality.
test_sha256<S: Sha256>(digest: &S)61 pub fn test_sha256<S: Sha256>(digest: &S) {
62 let tests: &[(&'static [u8], &'static str)] = &[
63 (b"", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
64 (b"abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"),
65 ];
66 for (i, (data, want)) in tests.iter().enumerate() {
67 let got = digest.compute_sha256(data).unwrap();
68 assert_eq!(hex::encode(got), *want, "incorrect for case {i}")
69 }
70 }
71
72 /// Test basic [`Hmac`] functionality.
test_hmac<H: Hmac>(hmac: &H)73 pub fn test_hmac<H: Hmac>(hmac: &H) {
74 struct TestCase {
75 key: &'static str, // 32 bytes, hex-encoded
76 data: &'static [u8],
77 want: &'static str, // 32 bytes, hex-encoded
78 }
79 let tests = [
80 TestCase {
81 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
82 data: b"Hello",
83 want: "0adc968519e7e86e9fde625df7037baeab85ea5001583b93b9f576258bf7b20c",
84 },
85 TestCase {
86 key: "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
87 data: &[],
88 want: "d38b42096d80f45f826b44a9d5607de72496a415d3f4a1a8c88e3bb9da8dc1cb",
89 },
90 ];
91
92 for (i, test) in tests.iter().enumerate() {
93 let key = hex::decode(test.key).unwrap();
94 let key = HmacKey(key.try_into().unwrap());
95 let got = hmac.compute_hmac(&key, test.data).unwrap();
96 assert_eq!(hex::encode(&got), test.want, "incorrect for case {i}");
97 }
98 }
99
100 /// Test basic HKDF functionality.
test_hkdf<H: Hkdf>(h: &H)101 pub fn test_hkdf<H: Hkdf>(h: &H) {
102 struct TestCase {
103 ikm: &'static str,
104 salt: &'static str,
105 info: &'static str,
106 want: &'static str,
107 }
108
109 let tests = [
110 // RFC 5869 section A.1
111 TestCase {
112 ikm: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
113 salt: "000102030405060708090a0b0c",
114 info: "f0f1f2f3f4f5f6f7f8f9",
115 want: "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf",
116 },
117 // RFC 5869 section A.2
118 TestCase {
119 ikm: concat!(
120 "000102030405060708090a0b0c0d0e0f",
121 "101112131415161718191a1b1c1d1e1f",
122 "202122232425262728292a2b2c2d2e2f",
123 "303132333435363738393a3b3c3d3e3f",
124 "404142434445464748494a4b4c4d4e4f",
125 ),
126 salt: concat!(
127 "606162636465666768696a6b6c6d6e6f",
128 "707172737475767778797a7b7c7d7e7f",
129 "808182838485868788898a8b8c8d8e8f",
130 "909192939495969798999a9b9c9d9e9f",
131 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
132 ),
133 info: concat!(
134 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf",
135 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf",
136 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf",
137 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef",
138 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
139 ),
140 want: "b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c",
141 },
142 TestCase {
143 ikm: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
144 salt: "",
145 info: "",
146 want: "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d",
147 },
148 ];
149
150 for (i, test) in tests.iter().enumerate() {
151 let ikm = hex::decode(test.ikm).unwrap();
152 let salt = hex::decode(test.salt).unwrap();
153 let info = hex::decode(test.info).unwrap();
154
155 let got = hkdf(h, &salt, &ikm, &info).unwrap().0;
156 assert_eq!(hex::encode(got), test.want, "incorrect for case {i}");
157 }
158 }
159
hkdf(hkdf: &dyn Hkdf, salt: &[u8], ikm: &[u8], info: &[u8]) -> Result<PseudoRandKey, Error>160 fn hkdf(hkdf: &dyn Hkdf, salt: &[u8], ikm: &[u8], info: &[u8]) -> Result<PseudoRandKey, Error> {
161 let ikm = EcdhSecret(ikm.to_vec());
162 let prk = hkdf.extract(salt, &ikm)?;
163 hkdf.expand(&prk, info)
164 }
165
166 /// Simple test that AES key generation is random.
test_aes_gcm_keygen<A: AesGcm, R: Rng>(aes: &A, rng: &mut R)167 pub fn test_aes_gcm_keygen<A: AesGcm, R: Rng>(aes: &A, rng: &mut R) {
168 let key1 = aes.generate_key(rng).unwrap();
169 let key2 = aes.generate_key(rng).unwrap();
170 assert_ne!(key1.0, key2.0, "identical generated AES keys!");
171 }
172
173 /// Test basic AES-GCM round-trip functionality.
test_aes_gcm_roundtrip<A: AesGcm, R: Rng>(aes: &A, rng: &mut R)174 pub fn test_aes_gcm_roundtrip<A: AesGcm, R: Rng>(aes: &A, rng: &mut R) {
175 let key = aes.generate_key(rng).unwrap();
176 let msg = b"The Magic Words are Squeamish Ossifrage";
177 let aad = b"the aad";
178 let nonce = Nonce12(*b"1243567890ab");
179 let ct = aes.encrypt(&key, msg, aad, &nonce).unwrap();
180 let pt = aes.decrypt(&key, &ct, aad, &nonce).unwrap();
181 assert_eq!(pt, msg);
182
183 // Modifying any of the inputs should induce failure.
184 let bad_key = aes.generate_key(rng).unwrap();
185 let bad_aad = b"the AAD";
186 let bad_nonce = Nonce12(*b"ab1243567890");
187 let mut bad_ct = ct.clone();
188 bad_ct[0] ^= 0x01;
189
190 assert!(aes.decrypt(&bad_key, &ct, aad, &nonce).is_err());
191 assert!(aes.decrypt(&key, &bad_ct, aad, &nonce).is_err());
192 assert!(aes.decrypt(&key, &ct, bad_aad, &nonce).is_err());
193 assert!(aes.decrypt(&key, &ct, aad, &bad_nonce).is_err());
194 }
195
196 /// Test AES-GCM against test vectors.
test_aes_gcm<A: AesGcm>(aes: &A)197 pub fn test_aes_gcm<A: AesGcm>(aes: &A) {
198 struct TestCase {
199 key: &'static str,
200 iv: &'static str,
201 aad: &'static str,
202 msg: &'static str,
203 ct: &'static str,
204 tag: &'static str,
205 }
206
207 // Test vectors from Wycheproof aes_gcm_test.json.
208 let aes_gcm_tests = [
209 TestCase {
210 // tcId: 73
211 key: "92ace3e348cd821092cd921aa3546374299ab46209691bc28b8752d17f123c20",
212 iv: "00112233445566778899aabb",
213 aad: "00000000ffffffff",
214 msg: "00010203040506070809",
215 ct: "e27abdd2d2a53d2f136b",
216 tag: "9a4a2579529301bcfb71c78d4060f52c",
217 },
218 TestCase {
219 // tcId: 74
220 key: "29d3a44f8723dc640239100c365423a312934ac80239212ac3df3421a2098123",
221 iv: "00112233445566778899aabb",
222 aad: "aabbccddeeff",
223 msg: "",
224 ct: "",
225 tag: "2a7d77fa526b8250cb296078926b5020",
226 },
227 TestCase {
228 // tcId: 75
229 key: "80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0",
230 iv: "4da5bf8dfd5852c1ea12379d",
231 aad: "",
232 msg: "",
233 ct: "",
234 tag: "4771a7c404a472966cea8f73c8bfe17a",
235 },
236 TestCase {
237 // tcId: 76
238 key: "cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273",
239 iv: "99e23ec48985bccdeeab60f1",
240 aad: "",
241 msg: "2a",
242 ct: "06",
243 tag: "633c1e9703ef744ffffb40edf9d14355",
244 },
245 TestCase {
246 // tcId: 77
247 key: "51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152",
248 iv: "4f07afedfdc3b6c2361823d3",
249 aad: "",
250 msg: "be3308f72a2c6aed",
251 ct: "cf332a12fdee800b",
252 tag: "602e8d7c4799d62c140c9bb834876b09",
253 },
254 TestCase {
255 // tcId: 78
256 key: "67119627bd988eda906219e08c0d0d779a07d208ce8a4fe0709af755eeec6dcb",
257 iv: "68ab7fdbf61901dad461d23c",
258 aad: "",
259 msg: "51f8c1f731ea14acdb210a6d973e07",
260 ct: "43fc101bff4b32bfadd3daf57a590e",
261 tag: "ec04aacb7148a8b8be44cb7eaf4efa69",
262 },
263 ];
264 for (i, test) in aes_gcm_tests.iter().enumerate() {
265 let key = AesKey(hex::decode(test.key).unwrap().try_into().unwrap());
266 let nonce = Nonce12(hex::decode(test.iv).unwrap().try_into().unwrap());
267 let aad = hex::decode(test.aad).unwrap();
268 let msg = hex::decode(test.msg).unwrap();
269 let want_hex = test.ct.to_owned() + test.tag;
270
271 let got = aes.encrypt(&key, &msg, &aad, &nonce).unwrap();
272 assert_eq!(hex::encode(&got), want_hex, "incorrect for case {i}");
273
274 let got_pt = aes.decrypt(&key, &got, &aad, &nonce).unwrap();
275 assert_eq!(hex::encode(got_pt), test.msg, "incorrect decrypt for case {i}");
276 }
277 }
278
279 /// Test `EcDh` impl for ECDH.
test_ecdh<E: EcDh>(ecdh: &E)280 pub fn test_ecdh<E: EcDh>(ecdh: &E) {
281 let key1 = ecdh.generate_key().unwrap();
282 let key2 = ecdh.generate_key().unwrap();
283 let secret12 = ecdh.compute_shared_secret(&key1.priv_key, &key2.pub_key).unwrap();
284 let secret21 = ecdh.compute_shared_secret(&key2.priv_key, &key1.pub_key).unwrap();
285 assert_eq!(secret12.0, secret21.0);
286 }
287
288 /// Test `EcDsa` impl for verify.
test_ecdsa<E: EcDsa>(ecdsa: &E)289 pub fn test_ecdsa<E: EcDsa>(ecdsa: &E) {
290 let ed25519_key = coset::CoseKeyBuilder::new_okp_key()
291 .param(iana::OkpKeyParameter::Crv as i64, Value::from(iana::EllipticCurve::Ed25519 as u64))
292 .param(
293 iana::OkpKeyParameter::X as i64,
294 Value::from(
295 hex::decode("7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa")
296 .unwrap(),
297 ),
298 )
299 .algorithm(coset::iana::Algorithm::EdDSA)
300 .build();
301 let p256_key = CoseKeyBuilder::new_ec2_pub_key(
302 iana::EllipticCurve::P_256,
303 hex::decode("2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838").unwrap(),
304 hex::decode("c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e").unwrap(),
305 )
306 .algorithm(iana::Algorithm::ES256)
307 .build();
308 let p384_key = CoseKeyBuilder::new_ec2_pub_key(
309 iana::EllipticCurve::P_384,
310 hex::decode("2da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa").unwrap(),
311 hex::decode("4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f").unwrap(),
312 )
313 .algorithm(iana::Algorithm::ES384)
314 .build();
315
316 struct TestCase {
317 key: EcVerifyKey,
318 msg: &'static str, // hex
319 sig: &'static str, // hex
320 }
321 let tests = [
322 // Wycheproof: eddsa_test.json tcId=5
323 TestCase {
324 key: EcVerifyKey::Ed25519(ed25519_key),
325 msg: "313233343030",
326 sig: "657c1492402ab5ce03e2c3a7f0384d051b9cf3570f1207fc78c1bcc98c281c2bf0cf5b3a289976458a1be6277a5055545253b45b07dcc1abd96c8b989c00f301",
327 },
328 // Wycheproof: ecdsa_secp256r1_sha256_test.json tcId=3
329 // Signature converted to R | S form
330 TestCase {
331 key: EcVerifyKey::P256(p256_key),
332 msg: "313233343030",
333 sig: "2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
334 },
335 // Wycheproof: ecdsa_secp384r1_sha384_test.json tcId=3
336 // Signature converted to R | S form
337 TestCase {
338 key: EcVerifyKey::P384(p384_key),
339 msg: "313233343030",
340 sig: "12b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d7e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82",
341 },
342 ];
343
344 for (i, test) in tests.iter().enumerate() {
345 let sig = hex::decode(test.sig).unwrap();
346 let msg = hex::decode(test.msg).unwrap();
347
348 assert!(ecdsa.verify_signature(&test.key, &msg, &sig).is_ok(), "failed for case {i}");
349
350 // A modified message should not verify.
351 let mut bad_msg = msg.clone();
352 bad_msg[0] ^= 0x01;
353 assert!(
354 ecdsa.verify_signature(&test.key, &bad_msg, &sig).is_err(),
355 "unexpected success for case {i}"
356 );
357
358 // A modified signature should not verify.
359 let mut bad_sig = sig;
360 bad_sig[0] ^= 0x01;
361 assert!(
362 ecdsa.verify_signature(&test.key, &msg, &bad_sig).is_err(),
363 "unexpected success for case {i}"
364 );
365 }
366 }
367
368 /// Test EdDSA signing and verification for Ed25519.
test_ed25519_round_trip<E: EcDsa>(ecdsa: &E)369 pub fn test_ed25519_round_trip<E: EcDsa>(ecdsa: &E) {
370 // Wycheproof: eddsa_test.json
371 let ed25519_pub_key = coset::CoseKeyBuilder::new_okp_key()
372 .param(iana::OkpKeyParameter::Crv as i64, Value::from(iana::EllipticCurve::Ed25519 as u64))
373 .param(
374 iana::OkpKeyParameter::X as i64,
375 Value::from(
376 hex::decode("7d4d0e7f6153a69b6242b522abbee685fda4420f8834b108c3bdae369ef549fa")
377 .unwrap(),
378 ),
379 )
380 .algorithm(coset::iana::Algorithm::EdDSA)
381 .build();
382 let ed25519_verify_key = EcVerifyKey::Ed25519(ed25519_pub_key);
383 let ed25519_sign_key = EcSignKey::Ed25519(
384 hex::decode("add4bb8103785baf9ac534258e8aaf65f5f1adb5ef5f3df19bb80ab989c4d64b")
385 .unwrap()
386 .try_into()
387 .unwrap(),
388 );
389 test_ecdsa_round_trip(ecdsa, &ed25519_verify_key, &ed25519_sign_key)
390 }
391
392 // It's not possible to include a generic test for `EcDsa::sign` with NIST curves because the
393 // format of the `EcSignKey` is implementation-dependent. The following tests are therefore
394 // specific to implementations (such as the reference implementation) which store private key
395 // material for NIST EC curves in the form of DER-encoded `ECPrivateKey` structures.
396
397 /// Test EdDSA signing and verification for P-256.
test_p256_round_trip<E: EcDsa>(ecdsa: &E)398 pub fn test_p256_round_trip<E: EcDsa>(ecdsa: &E) {
399 // Generated with: openssl ecparam --name prime256v1 -genkey -noout -out p256-privkey.pem
400 //
401 // Contents (der2ascii -pem -i p256-privkey.pem):
402 //
403 // SEQUENCE {
404 // INTEGER { 1 }
405 // OCTET_STRING { `0733c93e22240ba783739f9e2bd4b4065bfcecac9268362587dc814da5b84080` }
406 // [0] {
407 // # secp256r1
408 // OBJECT_IDENTIFIER { 1.2.840.10045.3.1.7 }
409 // }
410 // [1] {
411 // BIT_STRING { `00` `04`
412 // `2b31afcfab1aba1f8850d7ecfa235e14d60a1ef5b2a75b93ccaa4322de094477`
413 // `21ba560a040bab8c922edd32a279e9d3ac991f1507d4b4beded5fd80298b7cee`
414 // }
415 // }
416 // }
417 let p256_priv_key = hex::decode("307702010104200733c93e22240ba783739f9e2bd4b4065bfcecac9268362587dc814da5b84080a00a06082a8648ce3d030107a144034200042b31afcfab1aba1f8850d7ecfa235e14d60a1ef5b2a75b93ccaa4322de09447721ba560a040bab8c922edd32a279e9d3ac991f1507d4b4beded5fd80298b7cee").unwrap();
418 let p256_pub_key = CoseKeyBuilder::new_ec2_pub_key(
419 iana::EllipticCurve::P_256,
420 hex::decode("2b31afcfab1aba1f8850d7ecfa235e14d60a1ef5b2a75b93ccaa4322de094477").unwrap(),
421 hex::decode("21ba560a040bab8c922edd32a279e9d3ac991f1507d4b4beded5fd80298b7cee").unwrap(),
422 )
423 .algorithm(iana::Algorithm::ES256)
424 .build();
425
426 test_ecdsa_round_trip(ecdsa, &EcVerifyKey::P256(p256_pub_key), &EcSignKey::P256(p256_priv_key))
427 }
428
429 /// Test EdDSA signing and verification for P-384.
test_p384_round_trip<E: EcDsa>(ecdsa: &E)430 pub fn test_p384_round_trip<E: EcDsa>(ecdsa: &E) {
431 // Generated with: openssl ecparam --name secp384r1 -genkey -noout -out p384-privkey.pem
432 //
433 // Contents (der2ascii -pem -i p384-privkey.pem):
434 //
435 // SEQUENCE {
436 // INTEGER { 1 }
437 // OCTET_STRING { `81a9d9e43e47dbbf3e7e4e9e06d467b1b126603969bf80f0ade1e1aea9ed534884b81d86ece0bbd41d541bf6d22f6be2` }
438 // [0] {
439 // # secp384r1
440 // OBJECT_IDENTIFIER { 1.3.132.0.34 }
441 // }
442 // [1] {
443 // BIT_STRING { `00` `04`
444 // `fdf3f076a6e98047baf68a44d319f0200a03c4807eb0e869db88e1c9758ba96647fecbe0456c475feeb67021e053de93`
445 // `478ad58e972d52af0ea5911fe24f82448e9c073263aaa49117c451e787eced645796e50b24ee2c632a6c77e6d430ad01`
446 // }
447 // }
448 // }
449 let p384_priv_key = hex::decode("3081a4020101043081a9d9e43e47dbbf3e7e4e9e06d467b1b126603969bf80f0ade1e1aea9ed534884b81d86ece0bbd41d541bf6d22f6be2a00706052b81040022a16403620004fdf3f076a6e98047baf68a44d319f0200a03c4807eb0e869db88e1c9758ba96647fecbe0456c475feeb67021e053de93478ad58e972d52af0ea5911fe24f82448e9c073263aaa49117c451e787eced645796e50b24ee2c632a6c77e6d430ad01").unwrap();
450 let p384_pub_key = CoseKeyBuilder::new_ec2_pub_key(
451 iana::EllipticCurve::P_384,
452 hex::decode("fdf3f076a6e98047baf68a44d319f0200a03c4807eb0e869db88e1c9758ba96647fecbe0456c475feeb67021e053de93").unwrap(),
453 hex::decode("478ad58e972d52af0ea5911fe24f82448e9c073263aaa49117c451e787eced645796e50b24ee2c632a6c77e6d430ad01").unwrap(),
454 )
455 .algorithm(iana::Algorithm::ES384)
456 .build();
457
458 test_ecdsa_round_trip(ecdsa, &EcVerifyKey::P384(p384_pub_key), &EcSignKey::P384(p384_priv_key))
459 }
460
test_ecdsa_round_trip<E: EcDsa>(ecdsa: &E, verify_key: &EcVerifyKey, sign_key: &EcSignKey)461 fn test_ecdsa_round_trip<E: EcDsa>(ecdsa: &E, verify_key: &EcVerifyKey, sign_key: &EcSignKey) {
462 let msg = b"This is the message";
463 let sig = ecdsa.sign(sign_key, msg).unwrap();
464
465 assert!(ecdsa.verify_signature(verify_key, msg, &sig).is_ok());
466
467 // A modified message should not verify.
468 let mut bad_msg = *msg;
469 bad_msg[0] ^= 0x01;
470 assert!(ecdsa.verify_signature(verify_key, &bad_msg, &sig).is_err());
471
472 // A modified signature should not verify.
473 let mut bad_sig = sig;
474 bad_sig[0] ^= 0x01;
475 assert!(ecdsa.verify_signature(verify_key, msg, &bad_sig).is_err());
476 }
477
478 /// Test `create` method of key exchange protocol
test_key_exchange_create(source: &mut keyexchange::AuthGraphParticipant)479 pub fn test_key_exchange_create(source: &mut keyexchange::AuthGraphParticipant) {
480 let create_result = source.create();
481 assert!(create_result.is_ok());
482
483 // TODO: Add more tests on the values returned from `create` (some of these tests may
484 // need to be done in `libauthgraph_boringssl_test`)
485 // 1. dh_key is not None,
486 // 2. dh_key->pub key is in CoseKey encoding (e..g purpose)
487 // 3. dh_key->priv_key arc can be decrypted from the pbk from the AgDevice, the IV attached
488 // in the unprotected headers, nonce for key exchange and the payload type = SecretKey
489 // attached in the protected headers
490 // 5. identity decodes to a CBOR vector and the second element is a bstr of
491 // CoseKey
492 // 6. nonce is same as the nonce attached in the protected header of the arc in
493 // #3 above
494 // 7. ECDH can be performed from the dh_key returned from this method
495 }
496
497 /// Test `init` method of key exchange protocol
test_key_exchange_init( source: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )498 pub fn test_key_exchange_init(
499 source: &mut keyexchange::AuthGraphParticipant,
500 sink: &mut keyexchange::AuthGraphParticipant,
501 ) {
502 let keyexchange::SessionInitiationInfo {
503 ke_key: Key { pub_key: peer_ke_pub_key, .. },
504 identity: peer_identity,
505 nonce: peer_nonce,
506 version: peer_version,
507 } = source.create().unwrap();
508
509 let init_result =
510 sink.init(&peer_ke_pub_key.unwrap(), &peer_identity, &peer_nonce, peer_version);
511 assert!(init_result.is_ok())
512 // TODO: add more tests on init_result
513 }
514
515 /// Test `finish` method of key exchange protocol
test_key_exchange_finish( source: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )516 pub fn test_key_exchange_finish(
517 source: &mut keyexchange::AuthGraphParticipant,
518 sink: &mut keyexchange::AuthGraphParticipant,
519 ) {
520 let keyexchange::SessionInitiationInfo {
521 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
522 identity: p1_identity,
523 nonce: p1_nonce,
524 version: p1_version,
525 } = source.create().unwrap();
526
527 let keyexchange::KeInitResult {
528 session_init_info:
529 keyexchange::SessionInitiationInfo {
530 ke_key: Key { pub_key: p2_ke_pub_key, .. },
531 identity: p2_identity,
532 nonce: p2_nonce,
533 version: p2_version,
534 },
535 session_info: keyexchange::SessionInfo { session_id_signature: p2_signature, .. },
536 } = sink.init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version).unwrap();
537
538 let finish_result = source.finish(
539 &p2_ke_pub_key.unwrap(),
540 &p2_identity,
541 &p2_signature,
542 &p2_nonce,
543 p2_version,
544 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
545 );
546 assert!(finish_result.is_ok())
547 // TODO: add more tests on finish_result
548 }
549
550 /// Test `authentication_complete` method of key exchange protocol
test_key_exchange_auth_complete( source: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )551 pub fn test_key_exchange_auth_complete(
552 source: &mut keyexchange::AuthGraphParticipant,
553 sink: &mut keyexchange::AuthGraphParticipant,
554 ) {
555 let keyexchange::SessionInitiationInfo {
556 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
557 identity: p1_identity,
558 nonce: p1_nonce,
559 version: p1_version,
560 } = source.create().unwrap();
561
562 let keyexchange::KeInitResult {
563 session_init_info:
564 keyexchange::SessionInitiationInfo {
565 ke_key: Key { pub_key: p2_ke_pub_key, .. },
566 identity: p2_identity,
567 nonce: p2_nonce,
568 version: p2_version,
569 },
570 session_info:
571 keyexchange::SessionInfo {
572 shared_keys: p2_shared_keys,
573 session_id: p2_session_id,
574 session_id_signature: p2_signature,
575 },
576 } = sink.init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version).unwrap();
577
578 let keyexchange::SessionInfo {
579 shared_keys: _p1_shared_keys,
580 session_id: p1_session_id,
581 session_id_signature: p1_signature,
582 } = source
583 .finish(
584 &p2_ke_pub_key.unwrap(),
585 &p2_identity,
586 &p2_signature,
587 &p2_nonce,
588 p2_version,
589 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
590 )
591 .unwrap();
592
593 let auth_complete_result = sink.authentication_complete(&p1_signature, p2_shared_keys);
594 assert!(auth_complete_result.is_ok());
595 assert_eq!(p1_session_id, p2_session_id)
596 // TODO: add more tests on finish_result, and encrypt/decrypt using the agreed keys
597 }
598
599 /// Verify that the key exchange protocol works when source's version is higher than sink's version
600 /// and that the negotiated version is sink's version
test_ke_with_newer_source( source_newer: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )601 pub fn test_ke_with_newer_source(
602 source_newer: &mut keyexchange::AuthGraphParticipant,
603 sink: &mut keyexchange::AuthGraphParticipant,
604 ) {
605 let source_version = source_newer.get_version();
606 let sink_version = sink.get_version();
607 assert!(source_version > sink_version);
608
609 let keyexchange::SessionInitiationInfo {
610 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
611 identity: p1_identity,
612 nonce: p1_nonce,
613 version: p1_version,
614 } = source_newer.create().unwrap();
615
616 let keyexchange::KeInitResult {
617 session_init_info:
618 keyexchange::SessionInitiationInfo {
619 ke_key: Key { pub_key: p2_ke_pub_key, .. },
620 identity: p2_identity,
621 nonce: p2_nonce,
622 version: p2_version,
623 },
624 session_info:
625 keyexchange::SessionInfo {
626 shared_keys: p2_shared_keys,
627 session_id: p2_session_id,
628 session_id_signature: p2_signature,
629 },
630 } = sink.init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version).unwrap();
631 assert_eq!(p2_version, sink_version);
632
633 let keyexchange::SessionInfo {
634 shared_keys: _p1_shared_keys,
635 session_id: p1_session_id,
636 session_id_signature: p1_signature,
637 } = source_newer
638 .finish(
639 &p2_ke_pub_key.unwrap(),
640 &p2_identity,
641 &p2_signature,
642 &p2_nonce,
643 p2_version,
644 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
645 )
646 .unwrap();
647
648 let auth_complete_result = sink.authentication_complete(&p1_signature, p2_shared_keys);
649 assert!(auth_complete_result.is_ok());
650 assert_eq!(p1_session_id, p2_session_id)
651 }
652
653 /// Verify that the key exchange protocol works when sink's version is higher than sources's version
654 /// and that the negotiated version is source's version
test_ke_with_newer_sink( source: &mut keyexchange::AuthGraphParticipant, sink_newer: &mut keyexchange::AuthGraphParticipant, )655 pub fn test_ke_with_newer_sink(
656 source: &mut keyexchange::AuthGraphParticipant,
657 sink_newer: &mut keyexchange::AuthGraphParticipant,
658 ) {
659 let source_version = source.get_version();
660 let sink_version = sink_newer.get_version();
661 assert!(sink_version > source_version);
662
663 let keyexchange::SessionInitiationInfo {
664 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
665 identity: p1_identity,
666 nonce: p1_nonce,
667 version: p1_version,
668 } = source.create().unwrap();
669
670 let keyexchange::KeInitResult {
671 session_init_info:
672 keyexchange::SessionInitiationInfo {
673 ke_key: Key { pub_key: p2_ke_pub_key, .. },
674 identity: p2_identity,
675 nonce: p2_nonce,
676 version: p2_version,
677 },
678 session_info:
679 keyexchange::SessionInfo {
680 shared_keys: p2_shared_keys,
681 session_id: p2_session_id,
682 session_id_signature: p2_signature,
683 },
684 } = sink_newer
685 .init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version)
686 .unwrap();
687 assert_eq!(p2_version, source_version);
688
689 let keyexchange::SessionInfo {
690 shared_keys: _p1_shared_keys,
691 session_id: p1_session_id,
692 session_id_signature: p1_signature,
693 } = source
694 .finish(
695 &p2_ke_pub_key.unwrap(),
696 &p2_identity,
697 &p2_signature,
698 &p2_nonce,
699 p2_version,
700 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
701 )
702 .unwrap();
703
704 let auth_complete_result = sink_newer.authentication_complete(&p1_signature, p2_shared_keys);
705 assert!(auth_complete_result.is_ok());
706 assert_eq!(p1_session_id, p2_session_id)
707 }
708
709 /// Verify that the key exchange protocol prevents version downgrade attacks when both source and
710 /// sink have versions newer than version 1
test_ke_for_version_downgrade( source: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )711 pub fn test_ke_for_version_downgrade(
712 source: &mut keyexchange::AuthGraphParticipant,
713 sink: &mut keyexchange::AuthGraphParticipant,
714 ) {
715 let source_version = source.get_version();
716 let sink_version = sink.get_version();
717 assert!(source_version > 1);
718 assert!(sink_version > 1);
719
720 let keyexchange::SessionInitiationInfo {
721 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
722 identity: p1_identity,
723 nonce: p1_nonce,
724 version: _p1_version,
725 } = source.create().unwrap();
726
727 let downgraded_version = 1;
728
729 let keyexchange::KeInitResult {
730 session_init_info:
731 keyexchange::SessionInitiationInfo {
732 ke_key: Key { pub_key: p2_ke_pub_key, .. },
733 identity: p2_identity,
734 nonce: p2_nonce,
735 version: p2_version,
736 },
737 session_info:
738 keyexchange::SessionInfo {
739 shared_keys: _p2_shared_keys,
740 session_id: _p2_session_id,
741 session_id_signature: p2_signature,
742 },
743 } = sink
744 .init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, downgraded_version)
745 .unwrap();
746 assert_eq!(p2_version, downgraded_version);
747
748 let finish_result = source.finish(
749 &p2_ke_pub_key.unwrap(),
750 &p2_identity,
751 &p2_signature,
752 &p2_nonce,
753 p2_version,
754 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
755 );
756 // `finish` should fail with signature verification error
757 match finish_result {
758 Ok(_) => panic!("protocol downgrade prevention is broken"),
759 Err(e) => match e {
760 Error(ErrorCode::InvalidSignature, _) => {}
761 _ => panic!("wrong error on protocol downgrade"),
762 },
763 }
764 }
765
766 /// Verify that the key exchange protocol prevents replay attacks
test_ke_for_replay( source: &mut keyexchange::AuthGraphParticipant, sink: &mut keyexchange::AuthGraphParticipant, )767 pub fn test_ke_for_replay(
768 source: &mut keyexchange::AuthGraphParticipant,
769 sink: &mut keyexchange::AuthGraphParticipant,
770 ) {
771 // Round 1 of the protocol
772 let keyexchange::SessionInitiationInfo {
773 ke_key: Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
774 identity: p1_identity,
775 nonce: p1_nonce,
776 version: p1_version,
777 } = source.create().unwrap();
778
779 let keyexchange::KeInitResult {
780 session_init_info:
781 keyexchange::SessionInitiationInfo {
782 ke_key: Key { pub_key: p2_ke_pub_key, .. },
783 identity: p2_identity,
784 nonce: p2_nonce,
785 version: p2_version,
786 },
787 session_info:
788 keyexchange::SessionInfo {
789 shared_keys: p2_shared_keys,
790 session_id: p2_session_id,
791 session_id_signature: p2_signature,
792 },
793 } = sink.init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version).unwrap();
794
795 let keyexchange::SessionInfo {
796 shared_keys: _p1_shared_keys,
797 session_id: p1_session_id,
798 session_id_signature: p1_signature,
799 } = source
800 .finish(
801 &p2_ke_pub_key.clone().unwrap(),
802 &p2_identity,
803 &p2_signature,
804 &p2_nonce,
805 p2_version,
806 Key { pub_key: p1_ke_pub_key.clone(), arc_from_pbk: p1_ke_priv_key_arc.clone() },
807 )
808 .unwrap();
809
810 let auth_complete_result = sink.authentication_complete(&p1_signature, p2_shared_keys.clone());
811 assert!(auth_complete_result.is_ok());
812 assert_eq!(p1_session_id, p2_session_id);
813
814 // An attacker may try to run the key exchange protocol again, but this time, they try to
815 // replay the inputs of the previous protocol run, ignoring the outputs of `create` and `init`
816 // of the existing protocol run. In such cases, `finish` and `authentication_complete` should
817 // fail as per the measures against replay attacks.
818 source.create().unwrap();
819
820 sink.init(p1_ke_pub_key.as_ref().unwrap(), &p1_identity, &p1_nonce, p1_version).unwrap();
821
822 let finish_result = source.finish(
823 &p2_ke_pub_key.unwrap(),
824 &p2_identity,
825 &p2_signature,
826 &p2_nonce,
827 p2_version,
828 Key { pub_key: p1_ke_pub_key, arc_from_pbk: p1_ke_priv_key_arc },
829 );
830 match finish_result {
831 Ok(_) => panic!("replay prevention is broken in finish"),
832 Err(e) if e.0 == ErrorCode::InvalidKeKey => {}
833 Err(e) => panic!("got error {e:?}, wanted ErrorCode::InvalidKeKey"),
834 }
835
836 let auth_complete_result = sink.authentication_complete(&p1_signature, p2_shared_keys);
837 match auth_complete_result {
838 Ok(_) => panic!("replay prevention is broken in authentication_complete"),
839 Err(e) if e.0 == ErrorCode::InvalidSharedKeyArcs => {}
840 Err(e) => panic!("got error {e:?}, wanted ErrorCode::InvalidSharedKeyArcs"),
841 }
842 }
843
844 /// Test the logic of decoding and validating `Identity` using the test data created with open-dice.
validate_identity<E: EcDsa>(ecdsa: &E)845 pub fn validate_identity<E: EcDsa>(ecdsa: &E) {
846 for cert_chain_len in 0..6 {
847 let (pvt_sign_key, identity) =
848 create_identity(cert_chain_len).expect("error in creating identity");
849 // decode identity
850 let decoded_identity =
851 Identity::from_slice(&identity).expect("error in decoding the identity");
852 // validate identity
853 let verify_key =
854 decoded_identity.validate(ecdsa).expect("error in validating the identity");
855 // re-encode the decoded identity
856 decoded_identity.to_vec().expect("failed to serialize Identity");
857
858 // sign using the private signing key derived from the leaf CDI attest
859 let data = b"test string to sign";
860
861 let protected =
862 HeaderBuilder::new().algorithm(verify_key.get_cose_sign_algorithm()).build();
863 let cose_sign1 = CoseSign1Builder::new()
864 .protected(protected)
865 .payload(data.to_vec())
866 .try_create_signature(&[], |input| ecdsa.sign(&pvt_sign_key, input))
867 .expect("error creating the signature")
868 .build();
869 // verify the signature with the public signing key extracted from the leaf certificate in
870 // the DICE chain
871 cose_sign1
872 .verify_signature(&[], |signature, data| {
873 ecdsa.verify_signature(&verify_key, data, signature)
874 })
875 .expect("error in verifying the signature");
876 }
877 }
878
879 /// Construct a CBOR serialized `Identity` with a `CertChain` containing the given number of
880 /// certificate entries, using open-dice. The maximum length supported by this method is 5.
881 /// Return the private signing key corresponding to the public signing key.
create_identity(dice_chain_len: usize) -> Result<(EcSignKey, Vec<u8>), Error>882 pub fn create_identity(dice_chain_len: usize) -> Result<(EcSignKey, Vec<u8>), Error> {
883 let pvt_key_seed = diced_open_dice::derive_cdi_private_key_seed(&UDS).unwrap();
884 let (root_pub_key, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
885 .expect("failed to create key pair from seed.");
886 let root_pub_cose_key = CoseKey {
887 kty: KeyType::Assigned(iana::KeyType::OKP),
888 alg: Some(Algorithm::Assigned(iana::Algorithm::EdDSA)),
889 key_ops: vec![KeyOperation::Assigned(iana::KeyOperation::Verify)].into_iter().collect(),
890 params: vec![
891 (
892 Label::Int(iana::Ec2KeyParameter::Crv.to_i64()),
893 iana::EllipticCurve::Ed25519.to_i64().into(),
894 ),
895 (Label::Int(iana::Ec2KeyParameter::X.to_i64()), Value::Bytes(root_pub_key.to_vec())),
896 ],
897 ..Default::default()
898 };
899 let root_pub_cose_key_bstr =
900 root_pub_cose_key.to_vec().expect("failed to serialize root pub key");
901
902 if dice_chain_len == 0 {
903 let cert_chain = Value::Array(vec![
904 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
905 Value::Bytes(root_pub_cose_key_bstr.clone()),
906 ]);
907 let identity = Value::Array(vec![
908 Value::Integer(IDENTITY_VERSION.into()),
909 Value::Bytes(cert_chain.to_vec()?),
910 ]);
911 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
912 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
913 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
914 })?;
915 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
916 }
917
918 const CODE_HASH_PVMFW: [u8; diced_open_dice::HASH_SIZE] = [
919 0x16, 0x48, 0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63,
920 0x26, 0x0f, 0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2,
921 0xbe, 0x25, 0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91,
922 0x4d, 0xd3, 0xfb, 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30,
923 0xf7, 0x15, 0x98, 0x14,
924 ];
925 const AUTHORITY_HASH_PVMFW: [u8; diced_open_dice::HASH_SIZE] = [
926 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c,
927 0xe7, 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6,
928 0xc8, 0xdf, 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12,
929 0x12, 0xb2, 0xfd, 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99, 0xea,
930 0xae, 0xfd, 0xaa, 0x0d,
931 ];
932 const HIDDEN_PVMFW: [u8; diced_open_dice::HIDDEN_SIZE] = [
933 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f,
934 0x1f, 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07,
935 0x97, 0x4d, 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d,
936 0x2f, 0xdf, 0x7e, 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45,
937 0x83, 0x6b, 0x12, 0x7e,
938 ];
939 let comp_name_1 = CString::new("Protected VM firmware").expect("CString::new failed");
940 let config_values_1 = diced_open_dice::DiceConfigValues {
941 component_name: Some(&comp_name_1),
942 component_version: Some(1),
943 resettable: true,
944 ..Default::default()
945 };
946 let config_descriptor_1 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_1)
947 .expect("failed to format config descriptor");
948 let input_values_1 = diced_open_dice::InputValues::new(
949 CODE_HASH_PVMFW,
950 diced_open_dice::Config::Descriptor(config_descriptor_1.as_slice()),
951 AUTHORITY_HASH_PVMFW,
952 diced_open_dice::DiceMode::kDiceModeDebug,
953 HIDDEN_PVMFW,
954 );
955 let (cdi_values_1, cert_1) = diced_open_dice::retry_dice_main_flow(&UDS, &UDS, &input_values_1)
956 .expect("Failed to run first main flow");
957
958 if dice_chain_len == 1 {
959 let cert_chain = Value::Array(vec![
960 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
961 Value::Bytes(root_pub_cose_key_bstr.clone()),
962 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
963 ]);
964 let identity = Value::Array(vec![
965 Value::Integer(IDENTITY_VERSION.into()),
966 Value::Bytes(cert_chain.to_vec()?),
967 ]);
968 let pvt_key_seed =
969 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_1.cdi_attest).unwrap();
970 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
971 .expect("failed to create key pair from seed.");
972 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
973 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
974 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
975 })?;
976 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
977 }
978
979 const CODE_HASH_SERVICE_VM: [u8; diced_open_dice::HASH_SIZE] = [
980 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83, 0x7f, 0x46,
981 0x8d, 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56, 0xb3, 0xbf,
982 0x2f, 0xfa, 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28, 0xe8, 0x29,
983 0x20, 0x49, 0x0f, 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe,
984 0x58, 0x7f, 0xd3, 0xc7,
985 ];
986 const AUTHORITY_HASH_SERVICE_VM: [u8; diced_open_dice::HASH_SIZE] = [
987 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b,
988 0xaa, 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d,
989 0xe4, 0x43, 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8, 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6,
990 0x66, 0xef, 0xab, 0x3d, 0x0f, 0x89, 0xa4, 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a,
991 0xef, 0xbc, 0x05, 0x98,
992 ];
993 const HIDDEN_SERVICE_VM: [u8; diced_open_dice::HIDDEN_SIZE] = [
994 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21,
995 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e,
996 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27,
997 0x9d, 0x55, 0x8a, 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd,
998 0x73, 0xeb, 0x35, 0x7a,
999 ];
1000
1001 let comp_name_2 = CString::new("VM entry").expect("CString::new failed");
1002 let config_values_2 = diced_open_dice::DiceConfigValues {
1003 component_name: Some(&comp_name_2),
1004 component_version: Some(12),
1005 resettable: true,
1006 ..Default::default()
1007 };
1008 let config_descriptor_2 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_2)
1009 .expect("failed to format config descriptor");
1010
1011 let input_values_2 = diced_open_dice::InputValues::new(
1012 CODE_HASH_SERVICE_VM,
1013 diced_open_dice::Config::Descriptor(config_descriptor_2.as_slice()),
1014 AUTHORITY_HASH_SERVICE_VM,
1015 diced_open_dice::DiceMode::kDiceModeDebug,
1016 HIDDEN_SERVICE_VM,
1017 );
1018
1019 let (cdi_values_2, cert_2) = diced_open_dice::retry_dice_main_flow(
1020 &cdi_values_1.cdi_attest,
1021 &cdi_values_1.cdi_seal,
1022 &input_values_2,
1023 )
1024 .expect("Failed to run first main flow");
1025
1026 if dice_chain_len == 2 {
1027 let cert_chain = Value::Array(vec![
1028 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
1029 Value::Bytes(root_pub_cose_key_bstr.clone()),
1030 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
1031 Value::from_slice(&cert_2).expect("failed to deserialize the certificate into CBOR"),
1032 ]);
1033 let identity = Value::Array(vec![
1034 Value::Integer(IDENTITY_VERSION.into()),
1035 Value::Bytes(cert_chain.to_vec()?),
1036 ]);
1037 let pvt_key_seed =
1038 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_2.cdi_attest).unwrap();
1039 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1040 .expect("failed to create key pair from seed.");
1041 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
1042 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
1043 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
1044 })?;
1045 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
1046 }
1047
1048 const CODE_HASH_PAYLOAD: [u8; diced_open_dice::HASH_SIZE] = [
1049 0x08, 0x78, 0xc2, 0x5b, 0xe7, 0xea, 0x3d, 0x62, 0x70, 0x22, 0xd9, 0x1c, 0x4f, 0x3c, 0x2e,
1050 0x2f, 0x0f, 0x97, 0xa4, 0x6f, 0x6d, 0xd5, 0xe6, 0x4a, 0x6d, 0xbe, 0x34, 0x2e, 0x56, 0x04,
1051 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05, 0xb2, 0x06, 0xa3, 0x0e,
1052 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97, 0x07, 0x86, 0x5c, 0xa1,
1053 0x42, 0x12, 0xf0, 0x34,
1054 ];
1055 const AUTHORITY_HASH_PAYLOAD: [u8; diced_open_dice::HASH_SIZE] = [
1056 0xc7, 0x97, 0x5b, 0xa9, 0x9e, 0xbf, 0x0b, 0xeb, 0xe7, 0x7f, 0x69, 0x8f, 0x8e, 0xcf, 0x04,
1057 0x7d, 0x2c, 0x0f, 0x4d, 0xbe, 0xcb, 0xf5, 0xf1, 0x4c, 0x1d, 0x1c, 0xb7, 0x44, 0xdf, 0xf8,
1058 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7, 0xa2, 0x3a, 0x5c, 0x4e,
1059 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4, 0xef, 0xa2, 0x4d, 0x72,
1060 0xa1, 0x21, 0xe2, 0x47,
1061 ];
1062
1063 let comp_name_3 = CString::new("Payload").expect("CString::new failed");
1064 let config_values_3 = diced_open_dice::DiceConfigValues {
1065 component_name: Some(&comp_name_3),
1066 component_version: Some(12),
1067 resettable: true,
1068 ..Default::default()
1069 };
1070 let config_descriptor_3 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_3)
1071 .expect("failed to format config descriptor");
1072
1073 let input_values_3 = diced_open_dice::InputValues::new(
1074 CODE_HASH_PAYLOAD,
1075 diced_open_dice::Config::Descriptor(config_descriptor_3.as_slice()),
1076 AUTHORITY_HASH_PAYLOAD,
1077 diced_open_dice::DiceMode::kDiceModeDebug,
1078 [0u8; diced_open_dice::HIDDEN_SIZE],
1079 );
1080
1081 let (cdi_values_3, cert_3) = diced_open_dice::retry_dice_main_flow(
1082 &cdi_values_2.cdi_attest,
1083 &cdi_values_2.cdi_seal,
1084 &input_values_3,
1085 )
1086 .expect("Failed to run first main flow");
1087
1088 if dice_chain_len == 3 {
1089 let cert_chain = Value::Array(vec![
1090 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
1091 Value::Bytes(root_pub_cose_key_bstr.clone()),
1092 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
1093 Value::from_slice(&cert_2).expect("failed to deserialize the certificate into CBOR"),
1094 Value::from_slice(&cert_3).expect("failed to deserialize the certificate into CBOR"),
1095 ]);
1096 let identity = Value::Array(vec![
1097 Value::Integer(IDENTITY_VERSION.into()),
1098 Value::Bytes(cert_chain.to_vec()?),
1099 ]);
1100 let pvt_key_seed =
1101 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_3.cdi_attest).unwrap();
1102 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1103 .expect("failed to create key pair from seed.");
1104 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
1105 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
1106 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
1107 })?;
1108 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
1109 }
1110
1111 const CODE_HASH_APK1: [u8; diced_open_dice::HASH_SIZE] = [
1112 0x41, 0x92, 0x0d, 0xd0, 0xf5, 0x60, 0xe3, 0x69, 0x26, 0x7f, 0xb8, 0xbc, 0x12, 0x3a, 0xd1,
1113 0x95, 0x1d, 0xb8, 0x9a, 0x9c, 0x3a, 0x3f, 0x01, 0xbf, 0xa8, 0xd9, 0x6d, 0xe9, 0x90, 0x30,
1114 0x1d, 0x0b, 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05, 0xb2, 0x06,
1115 0xa3, 0x0e, 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97, 0x07, 0x86,
1116 0x5c, 0xa1, 0x42, 0x12,
1117 ];
1118 const AUTHORITY_HASH_APK1: [u8; diced_open_dice::HASH_SIZE] = [
1119 0xe3, 0xd9, 0x1c, 0xf5, 0x6f, 0xee, 0x73, 0x40, 0x3d, 0x95, 0x59, 0x67, 0xea, 0x5d, 0x01,
1120 0xfd, 0x25, 0x9d, 0x5c, 0x88, 0x94, 0x3a, 0xc6, 0xd7, 0xa9, 0xdc, 0x4c, 0x60, 0x81, 0xbe,
1121 0x2b, 0x74, 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7, 0xa2, 0x3a,
1122 0x5c, 0x4e, 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4, 0xef, 0xa2,
1123 0x4d, 0x72, 0xa1, 0x21,
1124 ];
1125
1126 let comp_name_4 = CString::new("APK1").expect("CString::new failed");
1127 let config_values_4 = diced_open_dice::DiceConfigValues {
1128 component_name: Some(&comp_name_4),
1129 component_version: Some(12),
1130 resettable: true,
1131 ..Default::default()
1132 };
1133 let config_descriptor_4 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_4)
1134 .expect("failed to format config descriptor");
1135
1136 let input_values_4 = diced_open_dice::InputValues::new(
1137 CODE_HASH_APK1,
1138 diced_open_dice::Config::Descriptor(config_descriptor_4.as_slice()),
1139 AUTHORITY_HASH_APK1,
1140 diced_open_dice::DiceMode::kDiceModeDebug,
1141 [0u8; diced_open_dice::HIDDEN_SIZE],
1142 );
1143
1144 let (cdi_values_4, cert_4) = diced_open_dice::retry_dice_main_flow(
1145 &cdi_values_3.cdi_attest,
1146 &cdi_values_3.cdi_seal,
1147 &input_values_4,
1148 )
1149 .expect("Failed to run first main flow");
1150
1151 if dice_chain_len == 4 {
1152 let cert_chain = Value::Array(vec![
1153 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
1154 Value::Bytes(root_pub_cose_key_bstr.clone()),
1155 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
1156 Value::from_slice(&cert_2).expect("failed to deserialize the certificate into CBOR"),
1157 Value::from_slice(&cert_3).expect("failed to deserialize the certificate into CBOR"),
1158 Value::from_slice(&cert_4).expect("failed to deserialize the certificate into CBOR"),
1159 ]);
1160 let identity = Value::Array(vec![
1161 Value::Integer(IDENTITY_VERSION.into()),
1162 Value::Bytes(cert_chain.to_vec()?),
1163 ]);
1164 let pvt_key_seed =
1165 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_4.cdi_attest).unwrap();
1166 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1167 .expect("failed to create key pair from seed.");
1168 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
1169 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
1170 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
1171 })?;
1172 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
1173 }
1174
1175 const CODE_HASH_APEX1: [u8; diced_open_dice::HASH_SIZE] = [
1176 0x52, 0x93, 0x2b, 0xb0, 0x8d, 0xec, 0xdf, 0x54, 0x1f, 0x5c, 0x10, 0x9d, 0x17, 0xce, 0x7f,
1177 0xac, 0xb0, 0x2b, 0xe2, 0x99, 0x05, 0x7d, 0xa3, 0x9b, 0xa6, 0x3e, 0xf9, 0x99, 0xa2, 0xea,
1178 0xd4, 0xd9, 0x1d, 0x0b, 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05,
1179 0xb2, 0x06, 0xa3, 0x0e, 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97,
1180 0x07, 0x86, 0x5c, 0xa1,
1181 ];
1182 const AUTHORITY_HASH_APEX1: [u8; diced_open_dice::HASH_SIZE] = [
1183 0xd1, 0xfc, 0x3d, 0x5f, 0xa0, 0x5f, 0x02, 0xd0, 0x83, 0x9b, 0x0e, 0x32, 0xc2, 0x27, 0x09,
1184 0x12, 0xcc, 0xfc, 0x42, 0xf6, 0x0d, 0xf4, 0x7d, 0xc8, 0x80, 0x1a, 0x64, 0x25, 0xa7, 0xfa,
1185 0x4a, 0x37, 0x2b, 0x74, 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7,
1186 0xa2, 0x3a, 0x5c, 0x4e, 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4,
1187 0xef, 0xa2, 0x4d, 0x72,
1188 ];
1189
1190 let comp_name_5 = CString::new("APEX1").expect("CString::new failed");
1191 let config_values_5 = diced_open_dice::DiceConfigValues {
1192 component_name: Some(&comp_name_5),
1193 component_version: Some(12),
1194 resettable: true,
1195 ..Default::default()
1196 };
1197 let config_descriptor_5 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_5)
1198 .expect("failed to format config descriptor");
1199
1200 let input_values_5 = diced_open_dice::InputValues::new(
1201 CODE_HASH_APEX1,
1202 diced_open_dice::Config::Descriptor(config_descriptor_5.as_slice()),
1203 AUTHORITY_HASH_APEX1,
1204 diced_open_dice::DiceMode::kDiceModeDebug,
1205 [0u8; diced_open_dice::HIDDEN_SIZE],
1206 );
1207
1208 let (cdi_values_5, cert_5) = diced_open_dice::retry_dice_main_flow(
1209 &cdi_values_4.cdi_attest,
1210 &cdi_values_4.cdi_seal,
1211 &input_values_5,
1212 )
1213 .expect("Failed to run first main flow");
1214
1215 if dice_chain_len == 5 {
1216 let cert_chain = Value::Array(vec![
1217 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
1218 Value::Bytes(root_pub_cose_key_bstr.clone()),
1219 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
1220 Value::from_slice(&cert_2).expect("failed to deserialize the certificate into CBOR"),
1221 Value::from_slice(&cert_3).expect("failed to deserialize the certificate into CBOR"),
1222 Value::from_slice(&cert_4).expect("failed to deserialize the certificate into CBOR"),
1223 Value::from_slice(&cert_5).expect("failed to deserialize the certificate into CBOR"),
1224 ]);
1225 let identity = Value::Array(vec![
1226 Value::Integer(IDENTITY_VERSION.into()),
1227 Value::Bytes(cert_chain.to_vec()?),
1228 ]);
1229 let pvt_key_seed =
1230 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_5.cdi_attest).unwrap();
1231 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1232 .expect("failed to create key pair from seed.");
1233 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] =
1234 pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN].try_into().map_err(|e| {
1235 ag_err!(InternalError, "error in constructing the private signing key {:?}", e)
1236 })?;
1237 return Ok((EcSignKey::Ed25519(pvt_key), identity.to_vec()?));
1238 }
1239 Err(ag_err!(InternalError, "this method supports the maximum length of 5 for a DICE chain"))
1240 }
1241
1242 /// Add a smoke test for `get_identity` in the `Device` trait, to ensure that the returned Identity
1243 /// passes a set of validation.
test_get_identity<D: Device, E: EcDsa>(ag_device: &D, ecdsa: &E)1244 pub fn test_get_identity<D: Device, E: EcDsa>(ag_device: &D, ecdsa: &E) {
1245 let (_, identity) = ag_device.get_identity().unwrap();
1246 identity.validate(ecdsa).unwrap();
1247 }
1248
1249 /// Test validation of a sample BCC identity.
test_example_identity_validate<E: EcDsa>(ecdsa: &E)1250 pub fn test_example_identity_validate<E: EcDsa>(ecdsa: &E) {
1251 let mut hex_data =
1252 std::str::from_utf8(include_bytes!("../testdata/sample_identity.hex")).unwrap().to_string();
1253 hex_data.retain(|c| !c.is_whitespace());
1254 let data = hex::decode(hex_data).unwrap();
1255 let identity = Identity::from_slice(&data).expect("identity data did not decode");
1256 identity.validate(ecdsa).expect("identity did not validate");
1257 }
1258
1259 /// This is a util method for writing tests related to the instance identifier in the vm entry of a
1260 /// pvm DICE chain. Returns the leaf private signing key, leaf CDI values and the sample DICE chain.
create_dice_cert_chain_for_guest_os( instance_hash_for_vm_entry: Option<[u8; 64]>, security_version: u64, ) -> (EcSignKey, CdiValues, Vec<u8>)1261 pub fn create_dice_cert_chain_for_guest_os(
1262 instance_hash_for_vm_entry: Option<[u8; 64]>,
1263 security_version: u64,
1264 ) -> (EcSignKey, CdiValues, Vec<u8>) {
1265 let pvt_key_seed = diced_open_dice::derive_cdi_private_key_seed(&UDS).unwrap();
1266 let (root_pub_key, _pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1267 .expect("failed to create key pair from seed.");
1268 let root_pub_cose_key = CoseKey {
1269 kty: KeyType::Assigned(iana::KeyType::OKP),
1270 alg: Some(Algorithm::Assigned(iana::Algorithm::EdDSA)),
1271 key_ops: vec![KeyOperation::Assigned(iana::KeyOperation::Verify)].into_iter().collect(),
1272 params: vec![
1273 (
1274 Label::Int(iana::Ec2KeyParameter::Crv.to_i64()),
1275 iana::EllipticCurve::Ed25519.to_i64().into(),
1276 ),
1277 (Label::Int(iana::Ec2KeyParameter::X.to_i64()), Value::Bytes(root_pub_key.to_vec())),
1278 ],
1279 ..Default::default()
1280 };
1281 let root_pub_cose_key_bstr =
1282 root_pub_cose_key.to_vec().expect("failed to serialize root pub key");
1283
1284 const CODE_HASH_TRUSTY: [u8; diced_open_dice::HASH_SIZE] = [
1285 0x16, 0x48, 0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63,
1286 0x26, 0x0f, 0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2,
1287 0xbe, 0x25, 0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91,
1288 0x4d, 0xd3, 0xfb, 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30,
1289 0xf7, 0x15, 0x98, 0x14,
1290 ];
1291 const AUTHORITY_HASH_TRUSTY: [u8; diced_open_dice::HASH_SIZE] = [
1292 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c,
1293 0xe7, 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6,
1294 0xc8, 0xdf, 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12,
1295 0x12, 0xb2, 0xfd, 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99, 0xea,
1296 0xae, 0xfd, 0xaa, 0x0d,
1297 ];
1298 const HIDDEN_TRUSTY: [u8; diced_open_dice::HIDDEN_SIZE] = [
1299 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f,
1300 0x1f, 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07,
1301 0x97, 0x4d, 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d,
1302 0x2f, 0xdf, 0x7e, 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45,
1303 0x83, 0x6b, 0x12, 0x7e,
1304 ];
1305 let comp_name_1 = CString::new("Trusty").expect("CString::new failed");
1306 let config_values_1 = diced_open_dice::DiceConfigValues {
1307 component_name: Some(&comp_name_1),
1308 component_version: Some(1),
1309 resettable: true,
1310 security_version: Some(security_version),
1311 ..Default::default()
1312 };
1313 let config_descriptor_1 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_1)
1314 .expect("failed to format config descriptor");
1315 let input_values_1 = diced_open_dice::InputValues::new(
1316 CODE_HASH_TRUSTY,
1317 diced_open_dice::Config::Descriptor(config_descriptor_1.as_slice()),
1318 AUTHORITY_HASH_TRUSTY,
1319 diced_open_dice::DiceMode::kDiceModeDebug,
1320 HIDDEN_TRUSTY,
1321 );
1322 let (cdi_values_1, cert_1) = diced_open_dice::retry_dice_main_flow(&UDS, &UDS, &input_values_1)
1323 .expect("Failed to run first main flow");
1324
1325 const CODE_HASH_ABL: [u8; diced_open_dice::HASH_SIZE] = [
1326 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83, 0x7f, 0x46,
1327 0x8d, 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56, 0xb3, 0xbf,
1328 0x2f, 0xfa, 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28, 0xe8, 0x29,
1329 0x20, 0x49, 0x0f, 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe,
1330 0x58, 0x7f, 0xd3, 0xc7,
1331 ];
1332 const AUTHORITY_HASH_ABL: [u8; diced_open_dice::HASH_SIZE] = [
1333 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b,
1334 0xaa, 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d,
1335 0xe4, 0x43, 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8, 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6,
1336 0x66, 0xef, 0xab, 0x3d, 0x0f, 0x89, 0xa4, 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a,
1337 0xef, 0xbc, 0x05, 0x98,
1338 ];
1339 const HIDDEN_ABL: [u8; diced_open_dice::HIDDEN_SIZE] = [
1340 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21,
1341 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e,
1342 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27,
1343 0x9d, 0x55, 0x8a, 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd,
1344 0x73, 0xeb, 0x35, 0x7a,
1345 ];
1346
1347 let comp_name_2 = CString::new("ABL").expect("CString::new failed");
1348 let config_values_2 = diced_open_dice::DiceConfigValues {
1349 component_name: Some(&comp_name_2),
1350 component_version: Some(12),
1351 resettable: true,
1352 ..Default::default()
1353 };
1354 let config_descriptor_2 = diced_open_dice::retry_bcc_format_config_descriptor(&config_values_2)
1355 .expect("failed to format config descriptor");
1356
1357 let input_values_2 = diced_open_dice::InputValues::new(
1358 CODE_HASH_ABL,
1359 diced_open_dice::Config::Descriptor(config_descriptor_2.as_slice()),
1360 AUTHORITY_HASH_ABL,
1361 diced_open_dice::DiceMode::kDiceModeDebug,
1362 HIDDEN_ABL,
1363 );
1364
1365 let (cdi_values_2, cert_2) = diced_open_dice::retry_dice_main_flow(
1366 &cdi_values_1.cdi_attest,
1367 &cdi_values_1.cdi_seal,
1368 &input_values_2,
1369 )
1370 .expect("Failed to run second main flow");
1371
1372 const CODE_HASH_PVMFW: [u8; diced_open_dice::HASH_SIZE] = [
1373 0x08, 0x78, 0xc2, 0x5b, 0xe7, 0xea, 0x3d, 0x62, 0x70, 0x22, 0xd9, 0x1c, 0x4f, 0x3c, 0x2e,
1374 0x2f, 0x0f, 0x97, 0xa4, 0x6f, 0x6d, 0xd5, 0xe6, 0x4a, 0x6d, 0xbe, 0x34, 0x2e, 0x56, 0x04,
1375 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05, 0xb2, 0x06, 0xa3, 0x0e,
1376 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97, 0x07, 0x86, 0x5c, 0xa1,
1377 0x42, 0x12, 0xf0, 0x34,
1378 ];
1379 const AUTHORITY_HASH_PVMFW: [u8; diced_open_dice::HASH_SIZE] = [
1380 0xc7, 0x97, 0x5b, 0xa9, 0x9e, 0xbf, 0x0b, 0xeb, 0xe7, 0x7f, 0x69, 0x8f, 0x8e, 0xcf, 0x04,
1381 0x7d, 0x2c, 0x0f, 0x4d, 0xbe, 0xcb, 0xf5, 0xf1, 0x4c, 0x1d, 0x1c, 0xb7, 0x44, 0xdf, 0xf8,
1382 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7, 0xa2, 0x3a, 0x5c, 0x4e,
1383 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4, 0xef, 0xa2, 0x4d, 0x72,
1384 0xa1, 0x21, 0xe2, 0x47,
1385 ];
1386 const HIDDEN_PVMFW: [u8; diced_open_dice::HIDDEN_SIZE] = [
1387 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f,
1388 0x1f, 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07,
1389 0x97, 0x4d, 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d,
1390 0x2f, 0xdf, 0x7e, 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45,
1391 0x83, 0x6b, 0x12, 0x7e,
1392 ];
1393 const INSTANCE_HASH_PVMFW: [u8; 64] = [
1394 0x5c, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4,
1395 0x2a, 0x7d, 0x7e, 0xa5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x9d, 0x55, 0x8a,
1396 0xe9, 0x90, 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x7d, 0x5b, 0x3f, 0xc9,
1397 0x5b, 0xe2, 0x95, 0x59, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2f, 0x7d, 0x7e,
1398 0xf5, 0x8e, 0xf5, 0x6e,
1399 ];
1400
1401 let config_descriptor_3: Vec<(Value, Value)> = vec![
1402 (Value::Integer(COMPONENT_NAME.into()), Value::Text("Protected VM firmware".to_string())),
1403 (Value::Integer(COMPONENT_VERSION.into()), Value::Integer(12.into())),
1404 (Value::Integer(RESETTABLE.into()), Value::Null),
1405 (Value::Integer(SECURITY_VERSION.into()), Value::Integer(security_version.into())),
1406 // Add an arbitrary instance hash element to the config descriptor of PVMFW
1407 (Value::Integer(INSTANCE_HASH.into()), Value::Bytes(INSTANCE_HASH_PVMFW.to_vec())),
1408 ];
1409 let config_descriptor_3 = Value::Map(config_descriptor_3)
1410 .to_vec()
1411 .expect("error in encoding the config descriptor 3");
1412 let input_values_3 = diced_open_dice::InputValues::new(
1413 CODE_HASH_PVMFW,
1414 diced_open_dice::Config::Descriptor(config_descriptor_3.as_slice()),
1415 AUTHORITY_HASH_PVMFW,
1416 diced_open_dice::DiceMode::kDiceModeDebug,
1417 HIDDEN_PVMFW,
1418 );
1419
1420 let (cdi_values_3, cert_3) = diced_open_dice::retry_dice_main_flow(
1421 &cdi_values_2.cdi_attest,
1422 &cdi_values_2.cdi_seal,
1423 &input_values_3,
1424 )
1425 .expect("Failed to run third main flow");
1426
1427 const CODE_HASH_VM: [u8; diced_open_dice::HASH_SIZE] = [
1428 0x41, 0x92, 0x0d, 0xd0, 0xf5, 0x60, 0xe3, 0x69, 0x26, 0x7f, 0xb8, 0xbc, 0x12, 0x3a, 0xd1,
1429 0x95, 0x1d, 0xb8, 0x9a, 0x9c, 0x3a, 0x3f, 0x01, 0xbf, 0xa8, 0xd9, 0x6d, 0xe9, 0x90, 0x30,
1430 0x1d, 0x0b, 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05, 0xb2, 0x06,
1431 0xa3, 0x0e, 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97, 0x07, 0x86,
1432 0x5c, 0xa1, 0x42, 0x12,
1433 ];
1434 const AUTHORITY_HASH_VM: [u8; diced_open_dice::HASH_SIZE] = [
1435 0xe3, 0xd9, 0x1c, 0xf5, 0x6f, 0xee, 0x73, 0x40, 0x3d, 0x95, 0x59, 0x67, 0xea, 0x5d, 0x01,
1436 0xfd, 0x25, 0x9d, 0x5c, 0x88, 0x94, 0x3a, 0xc6, 0xd7, 0xa9, 0xdc, 0x4c, 0x60, 0x81, 0xbe,
1437 0x2b, 0x74, 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7, 0xa2, 0x3a,
1438 0x5c, 0x4e, 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4, 0xef, 0xa2,
1439 0x4d, 0x72, 0xa1, 0x21,
1440 ];
1441 const HIDDEN_VM: [u8; diced_open_dice::HIDDEN_SIZE] = [
1442 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21,
1443 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e,
1444 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27,
1445 0x9d, 0x55, 0x8a, 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd,
1446 0x73, 0xeb, 0x35, 0x7a,
1447 ];
1448
1449 let mut config_descriptor_4: Vec<(Value, Value)> = vec![
1450 (Value::Integer(COMPONENT_NAME.into()), Value::Text(GUEST_OS_COMPONENT_NAME.to_string())),
1451 (Value::Integer(COMPONENT_VERSION.into()), Value::Integer(12.into())),
1452 (Value::Integer(RESETTABLE.into()), Value::Null),
1453 (Value::Integer(SECURITY_VERSION.into()), Value::Integer(security_version.into())),
1454 ];
1455 if let Some(instance_hash) = instance_hash_for_vm_entry {
1456 config_descriptor_4
1457 .push((Value::Integer(INSTANCE_HASH.into()), Value::Bytes(instance_hash.to_vec())));
1458 };
1459 let config_descriptor_4 = Value::Map(config_descriptor_4)
1460 .to_vec()
1461 .expect("error in encoding the config descriptor 4");
1462
1463 let input_values_4 = diced_open_dice::InputValues::new(
1464 CODE_HASH_VM,
1465 diced_open_dice::Config::Descriptor(config_descriptor_4.as_slice()),
1466 AUTHORITY_HASH_VM,
1467 diced_open_dice::DiceMode::kDiceModeDebug,
1468 HIDDEN_VM,
1469 );
1470
1471 let (cdi_values_4, cert_4) = diced_open_dice::retry_dice_main_flow(
1472 &cdi_values_3.cdi_attest,
1473 &cdi_values_3.cdi_seal,
1474 &input_values_4,
1475 )
1476 .expect("Failed to run fourth main flow");
1477
1478 const CODE_HASH_PAYLOAD: [u8; diced_open_dice::HASH_SIZE] = [
1479 0x52, 0x93, 0x2b, 0xb0, 0x8d, 0xec, 0xdf, 0x54, 0x1f, 0x5c, 0x10, 0x9d, 0x17, 0xce, 0x7f,
1480 0xac, 0xb0, 0x2b, 0xe2, 0x99, 0x05, 0x7d, 0xa3, 0x9b, 0xa6, 0x3e, 0xf9, 0x99, 0xa2, 0xea,
1481 0xd4, 0xd9, 0x1d, 0x0b, 0xaf, 0xef, 0x74, 0x3f, 0xec, 0xb8, 0x44, 0x11, 0xf4, 0x2f, 0x05,
1482 0xb2, 0x06, 0xa3, 0x0e, 0x75, 0xb7, 0x40, 0x9a, 0x4c, 0x58, 0xab, 0x96, 0xe7, 0x07, 0x97,
1483 0x07, 0x86, 0x5c, 0xa1,
1484 ];
1485 const AUTHORITY_HASH_PAYLOAD: [u8; diced_open_dice::HASH_SIZE] = [
1486 0xd1, 0xfc, 0x3d, 0x5f, 0xa0, 0x5f, 0x02, 0xd0, 0x83, 0x9b, 0x0e, 0x32, 0xc2, 0x27, 0x09,
1487 0x12, 0xcc, 0xfc, 0x42, 0xf6, 0x0d, 0xf4, 0x7d, 0xc8, 0x80, 0x1a, 0x64, 0x25, 0xa7, 0xfa,
1488 0x4a, 0x37, 0x2b, 0x74, 0x40, 0x90, 0x09, 0x65, 0xab, 0x01, 0x34, 0x3e, 0xc2, 0xc4, 0xf7,
1489 0xa2, 0x3a, 0x5c, 0x4e, 0x76, 0x4f, 0x42, 0xa8, 0x6c, 0xc9, 0xf1, 0x7b, 0x12, 0x80, 0xa4,
1490 0xef, 0xa2, 0x4d, 0x72,
1491 ];
1492 const INSTANCE_HASH_PAYLOAD: [u8; 64] = [
1493 0x4c, 0x3f, 0xa9, 0x6b, 0xa3, 0x95, 0x59, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4,
1494 0x2a, 0x7d, 0x7e, 0xa5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x9d, 0x55, 0x8a,
1495 0xe9, 0x90, 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x1a, 0x51, 0x27, 0x7d, 0x5b, 0x3f, 0xc9,
1496 0x5b, 0xe2, 0x95, 0x52, 0x40, 0x21, 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2f, 0x7d, 0x7e,
1497 0xf5, 0x8e, 0xf5, 0x6f,
1498 ];
1499
1500 let config_descriptor_5: Vec<(Value, Value)> = vec![
1501 (Value::Integer(COMPONENT_NAME.into()), Value::Text("Payload".to_string())),
1502 (Value::Integer(COMPONENT_VERSION.into()), Value::Integer(12.into())),
1503 (Value::Integer(RESETTABLE.into()), Value::Null),
1504 // Add an arbitrary instance hash element to the config descriptor of Payload
1505 (Value::Integer(INSTANCE_HASH.into()), Value::Bytes(INSTANCE_HASH_PAYLOAD.to_vec())),
1506 ];
1507 let config_descriptor_5 = Value::Map(config_descriptor_5)
1508 .to_vec()
1509 .expect("error in encoding the config descriptor 5");
1510
1511 let input_values_5 = diced_open_dice::InputValues::new(
1512 CODE_HASH_PAYLOAD,
1513 diced_open_dice::Config::Descriptor(config_descriptor_5.as_slice()),
1514 AUTHORITY_HASH_PAYLOAD,
1515 diced_open_dice::DiceMode::kDiceModeDebug,
1516 [0u8; diced_open_dice::HIDDEN_SIZE],
1517 );
1518
1519 let (cdi_values_5, cert_5) = diced_open_dice::retry_dice_main_flow(
1520 &cdi_values_4.cdi_attest,
1521 &cdi_values_4.cdi_seal,
1522 &input_values_5,
1523 )
1524 .expect("Failed to run fifth main flow");
1525
1526 let cert_chain = Value::Array(vec![
1527 Value::Integer(EXPLICIT_KEY_DICE_CERT_CHAIN_VERSION.into()),
1528 Value::Bytes(root_pub_cose_key_bstr.clone()),
1529 Value::from_slice(&cert_1).expect("failed to deserialize the certificate into CBOR"),
1530 Value::from_slice(&cert_2).expect("failed to deserialize the certificate into CBOR"),
1531 Value::from_slice(&cert_3).expect("failed to deserialize the certificate into CBOR"),
1532 Value::from_slice(&cert_4).expect("failed to deserialize the certificate into CBOR"),
1533 Value::from_slice(&cert_5).expect("failed to deserialize the certificate into CBOR"),
1534 ]);
1535 let pvt_key_seed =
1536 diced_open_dice::derive_cdi_private_key_seed(&cdi_values_5.cdi_attest).unwrap();
1537 let (_, pvt_key) = diced_open_dice::keypair_from_seed(pvt_key_seed.as_array())
1538 .expect("failed to create key pair from seed.");
1539 let pvt_key: [u8; CURVE25519_PRIV_KEY_LEN] = pvt_key.as_array()[0..CURVE25519_PRIV_KEY_LEN]
1540 .try_into()
1541 .expect("error in constructing the private signing key {:?}");
1542 (
1543 EcSignKey::Ed25519(pvt_key),
1544 cdi_values_5,
1545 cert_chain.to_vec().expect("error in encoding the cert chain to bytes"),
1546 )
1547 }
1548
1549 /// Helper function for testing which derives child DICE artifacts and creates a certificate
create_dice_leaf_cert( parent_cdi_values: CdiValues, component_name: &str, security_version: u64, ) -> Vec<u8>1550 pub fn create_dice_leaf_cert(
1551 parent_cdi_values: CdiValues,
1552 component_name: &str,
1553 security_version: u64,
1554 ) -> Vec<u8> {
1555 let comp_name = CString::new(component_name).expect("CString::new failed");
1556 let config_values = diced_open_dice::DiceConfigValues {
1557 component_name: Some(&comp_name),
1558 component_version: Some(1),
1559 resettable: true,
1560 security_version: Some(security_version),
1561 ..Default::default()
1562 };
1563 let config_descriptor = diced_open_dice::retry_bcc_format_config_descriptor(&config_values)
1564 .expect("failed to format config descriptor");
1565 let input_values = diced_open_dice::InputValues::new(
1566 [0u8; diced_open_dice::HASH_SIZE],
1567 diced_open_dice::Config::Descriptor(config_descriptor.as_slice()),
1568 [0u8; diced_open_dice::HASH_SIZE],
1569 diced_open_dice::DiceMode::kDiceModeDebug,
1570 [0u8; diced_open_dice::HASH_SIZE],
1571 );
1572 let (_, leaf_cert) = diced_open_dice::retry_dice_main_flow(
1573 &parent_cdi_values.cdi_attest,
1574 &parent_cdi_values.cdi_seal,
1575 &input_values,
1576 )
1577 .expect("Failed to run first main flow");
1578 leaf_cert
1579 }
1580