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