• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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