xref: /aosp_15_r20/system/keymint/tests/src/lib.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! Test methods to confirm basic functionality of trait implementations.
16*9860b763SAndroid Build Coastguard Worker 
17*9860b763SAndroid Build Coastguard Worker use core::convert::TryInto;
18*9860b763SAndroid Build Coastguard Worker use kmr_common::crypto::{
19*9860b763SAndroid Build Coastguard Worker     aes, des, hmac, Aes, AesCmac, Ckdf, ConstTimeEq, Des, Hkdf, Hmac, MonotonicClock, Rng, Sha256,
20*9860b763SAndroid Build Coastguard Worker     SymmetricOperation,
21*9860b763SAndroid Build Coastguard Worker };
22*9860b763SAndroid Build Coastguard Worker use kmr_common::{keyblob, keyblob::SlotPurpose};
23*9860b763SAndroid Build Coastguard Worker use kmr_ta::device::{SigningAlgorithm, SigningKey, SigningKeyType};
24*9860b763SAndroid Build Coastguard Worker use kmr_wire::{keymint::Digest, rpc};
25*9860b763SAndroid Build Coastguard Worker use std::collections::HashMap;
26*9860b763SAndroid Build Coastguard Worker use x509_cert::der::{Decode, Encode};
27*9860b763SAndroid Build Coastguard Worker 
28*9860b763SAndroid Build Coastguard Worker /// Test basic [`Rng`] functionality.
test_rng<R: Rng>(rng: &mut R)29*9860b763SAndroid Build Coastguard Worker pub fn test_rng<R: Rng>(rng: &mut R) {
30*9860b763SAndroid Build Coastguard Worker     let u1 = rng.next_u64();
31*9860b763SAndroid Build Coastguard Worker     let u2 = rng.next_u64();
32*9860b763SAndroid Build Coastguard Worker     assert_ne!(u1, u2);
33*9860b763SAndroid Build Coastguard Worker 
34*9860b763SAndroid Build Coastguard Worker     let mut b1 = [0u8; 16];
35*9860b763SAndroid Build Coastguard Worker     let mut b2 = [0u8; 16];
36*9860b763SAndroid Build Coastguard Worker     rng.fill_bytes(&mut b1);
37*9860b763SAndroid Build Coastguard Worker     rng.fill_bytes(&mut b2);
38*9860b763SAndroid Build Coastguard Worker     assert_ne!(b1, b2);
39*9860b763SAndroid Build Coastguard Worker 
40*9860b763SAndroid Build Coastguard Worker     rng.add_entropy(&b1);
41*9860b763SAndroid Build Coastguard Worker     rng.add_entropy(&[]);
42*9860b763SAndroid Build Coastguard Worker     rng.fill_bytes(&mut b1);
43*9860b763SAndroid Build Coastguard Worker     assert_ne!(b1, b2);
44*9860b763SAndroid Build Coastguard Worker }
45*9860b763SAndroid Build Coastguard Worker 
46*9860b763SAndroid Build Coastguard Worker /// Test basic [`ConstTimeEq`] functionality. Does not test the key constant-time property though.
test_eq<E: ConstTimeEq>(comparator: E)47*9860b763SAndroid Build Coastguard Worker pub fn test_eq<E: ConstTimeEq>(comparator: E) {
48*9860b763SAndroid Build Coastguard Worker     let b0 = [];
49*9860b763SAndroid Build Coastguard Worker     let b1 = [0u8, 1u8, 2u8];
50*9860b763SAndroid Build Coastguard Worker     let b2 = [1u8, 1u8, 2u8];
51*9860b763SAndroid Build Coastguard Worker     let b3 = [0u8, 1u8, 3u8];
52*9860b763SAndroid Build Coastguard Worker     let b4 = [0u8, 1u8, 2u8, 3u8];
53*9860b763SAndroid Build Coastguard Worker     let b5 = [42; 4096];
54*9860b763SAndroid Build Coastguard Worker     let mut b6 = [42; 4096];
55*9860b763SAndroid Build Coastguard Worker     b6[4095] = 43;
56*9860b763SAndroid Build Coastguard Worker     assert!(comparator.eq(&b0, &b0));
57*9860b763SAndroid Build Coastguard Worker     assert!(comparator.eq(&b5, &b5));
58*9860b763SAndroid Build Coastguard Worker 
59*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b0, &b1));
60*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b0, &b2));
61*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b0, &b3));
62*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b0, &b4));
63*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b0, &b5));
64*9860b763SAndroid Build Coastguard Worker     assert!(comparator.eq(&b1, &b1));
65*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b1, &b2));
66*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b1, &b3));
67*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b1, &b4));
68*9860b763SAndroid Build Coastguard Worker     assert!(comparator.ne(&b5, &b6));
69*9860b763SAndroid Build Coastguard Worker }
70*9860b763SAndroid Build Coastguard Worker 
71*9860b763SAndroid Build Coastguard Worker /// Test basic [`MonotonicClock`] functionality.
test_clock<C: MonotonicClock>(clock: C)72*9860b763SAndroid Build Coastguard Worker pub fn test_clock<C: MonotonicClock>(clock: C) {
73*9860b763SAndroid Build Coastguard Worker     let t1 = clock.now();
74*9860b763SAndroid Build Coastguard Worker     let t2 = clock.now();
75*9860b763SAndroid Build Coastguard Worker     assert!(t2.0 >= t1.0);
76*9860b763SAndroid Build Coastguard Worker     std::thread::sleep(std::time::Duration::from_millis(400));
77*9860b763SAndroid Build Coastguard Worker     let t3 = clock.now();
78*9860b763SAndroid Build Coastguard Worker     assert!(t3.0 > (t1.0 + 200));
79*9860b763SAndroid Build Coastguard Worker }
80*9860b763SAndroid Build Coastguard Worker 
81*9860b763SAndroid Build Coastguard Worker /// Test basic HKDF functionality.
test_hkdf<H: Hmac>(hmac: H)82*9860b763SAndroid Build Coastguard Worker pub fn test_hkdf<H: Hmac>(hmac: H) {
83*9860b763SAndroid Build Coastguard Worker     struct TestCase {
84*9860b763SAndroid Build Coastguard Worker         ikm: &'static str,
85*9860b763SAndroid Build Coastguard Worker         salt: &'static str,
86*9860b763SAndroid Build Coastguard Worker         info: &'static str,
87*9860b763SAndroid Build Coastguard Worker         out_len: usize,
88*9860b763SAndroid Build Coastguard Worker         want: &'static str,
89*9860b763SAndroid Build Coastguard Worker     }
90*9860b763SAndroid Build Coastguard Worker 
91*9860b763SAndroid Build Coastguard Worker     const HKDF_TESTS: &[TestCase] = &[
92*9860b763SAndroid Build Coastguard Worker         // RFC 5869 section A.1
93*9860b763SAndroid Build Coastguard Worker         TestCase {
94*9860b763SAndroid Build Coastguard Worker             ikm: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
95*9860b763SAndroid Build Coastguard Worker             salt: "000102030405060708090a0b0c",
96*9860b763SAndroid Build Coastguard Worker             info: "f0f1f2f3f4f5f6f7f8f9",
97*9860b763SAndroid Build Coastguard Worker             out_len: 42,
98*9860b763SAndroid Build Coastguard Worker             want: concat!(
99*9860b763SAndroid Build Coastguard Worker                 "3cb25f25faacd57a90434f64d0362f2a",
100*9860b763SAndroid Build Coastguard Worker                 "2d2d0a90cf1a5a4c5db02d56ecc4c5bf",
101*9860b763SAndroid Build Coastguard Worker                 "34007208d5b887185865",
102*9860b763SAndroid Build Coastguard Worker             ),
103*9860b763SAndroid Build Coastguard Worker         },
104*9860b763SAndroid Build Coastguard Worker         // RFC 5869 section A.2
105*9860b763SAndroid Build Coastguard Worker         TestCase {
106*9860b763SAndroid Build Coastguard Worker             ikm: concat!(
107*9860b763SAndroid Build Coastguard Worker                 "000102030405060708090a0b0c0d0e0f",
108*9860b763SAndroid Build Coastguard Worker                 "101112131415161718191a1b1c1d1e1f",
109*9860b763SAndroid Build Coastguard Worker                 "202122232425262728292a2b2c2d2e2f",
110*9860b763SAndroid Build Coastguard Worker                 "303132333435363738393a3b3c3d3e3f",
111*9860b763SAndroid Build Coastguard Worker                 "404142434445464748494a4b4c4d4e4f",
112*9860b763SAndroid Build Coastguard Worker             ),
113*9860b763SAndroid Build Coastguard Worker             salt: concat!(
114*9860b763SAndroid Build Coastguard Worker                 "606162636465666768696a6b6c6d6e6f",
115*9860b763SAndroid Build Coastguard Worker                 "707172737475767778797a7b7c7d7e7f",
116*9860b763SAndroid Build Coastguard Worker                 "808182838485868788898a8b8c8d8e8f",
117*9860b763SAndroid Build Coastguard Worker                 "909192939495969798999a9b9c9d9e9f",
118*9860b763SAndroid Build Coastguard Worker                 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf",
119*9860b763SAndroid Build Coastguard Worker             ),
120*9860b763SAndroid Build Coastguard Worker             info: concat!(
121*9860b763SAndroid Build Coastguard Worker                 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf",
122*9860b763SAndroid Build Coastguard Worker                 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf",
123*9860b763SAndroid Build Coastguard Worker                 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf",
124*9860b763SAndroid Build Coastguard Worker                 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef",
125*9860b763SAndroid Build Coastguard Worker                 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
126*9860b763SAndroid Build Coastguard Worker             ),
127*9860b763SAndroid Build Coastguard Worker             out_len: 82,
128*9860b763SAndroid Build Coastguard Worker             want: concat!(
129*9860b763SAndroid Build Coastguard Worker                 "b11e398dc80327a1c8e7f78c596a4934",
130*9860b763SAndroid Build Coastguard Worker                 "4f012eda2d4efad8a050cc4c19afa97c",
131*9860b763SAndroid Build Coastguard Worker                 "59045a99cac7827271cb41c65e590e09",
132*9860b763SAndroid Build Coastguard Worker                 "da3275600c2f09b8367793a9aca3db71",
133*9860b763SAndroid Build Coastguard Worker                 "cc30c58179ec3e87c14c01d5c1f3434f",
134*9860b763SAndroid Build Coastguard Worker                 "1d87",
135*9860b763SAndroid Build Coastguard Worker             ),
136*9860b763SAndroid Build Coastguard Worker         },
137*9860b763SAndroid Build Coastguard Worker         // RFC 5869 section A.3
138*9860b763SAndroid Build Coastguard Worker         TestCase {
139*9860b763SAndroid Build Coastguard Worker             ikm: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
140*9860b763SAndroid Build Coastguard Worker             salt: "",
141*9860b763SAndroid Build Coastguard Worker             info: "",
142*9860b763SAndroid Build Coastguard Worker             out_len: 42,
143*9860b763SAndroid Build Coastguard Worker             want: concat!(
144*9860b763SAndroid Build Coastguard Worker                 "8da4e775a563c18f715f802a063c5a31",
145*9860b763SAndroid Build Coastguard Worker                 "b8a11f5c5ee1879ec3454e5f3c738d2d",
146*9860b763SAndroid Build Coastguard Worker                 "9d201395faa4b61a96c8",
147*9860b763SAndroid Build Coastguard Worker             ),
148*9860b763SAndroid Build Coastguard Worker         },
149*9860b763SAndroid Build Coastguard Worker     ];
150*9860b763SAndroid Build Coastguard Worker 
151*9860b763SAndroid Build Coastguard Worker     for (i, test) in HKDF_TESTS.iter().enumerate() {
152*9860b763SAndroid Build Coastguard Worker         let ikm = hex::decode(test.ikm).unwrap();
153*9860b763SAndroid Build Coastguard Worker         let salt = hex::decode(test.salt).unwrap();
154*9860b763SAndroid Build Coastguard Worker         let info = hex::decode(test.info).unwrap();
155*9860b763SAndroid Build Coastguard Worker 
156*9860b763SAndroid Build Coastguard Worker         let got = hmac.hkdf(&salt, &ikm, &info, test.out_len).unwrap();
157*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(got), test.want, "incorrect HKDF result for case {}", i);
158*9860b763SAndroid Build Coastguard Worker     }
159*9860b763SAndroid Build Coastguard Worker }
160*9860b763SAndroid Build Coastguard Worker 
161*9860b763SAndroid Build Coastguard Worker /// Test basic [`Hmac`] functionality.
test_hmac<H: Hmac>(hmac: H)162*9860b763SAndroid Build Coastguard Worker pub fn test_hmac<H: Hmac>(hmac: H) {
163*9860b763SAndroid Build Coastguard Worker     struct TestCase {
164*9860b763SAndroid Build Coastguard Worker         digest: Digest,
165*9860b763SAndroid Build Coastguard Worker         tag_size: usize,
166*9860b763SAndroid Build Coastguard Worker         key: &'static [u8],
167*9860b763SAndroid Build Coastguard Worker         data: &'static [u8],
168*9860b763SAndroid Build Coastguard Worker         expected_mac: &'static str,
169*9860b763SAndroid Build Coastguard Worker     }
170*9860b763SAndroid Build Coastguard Worker 
171*9860b763SAndroid Build Coastguard Worker     const HMAC_TESTS : &[TestCase] = &[
172*9860b763SAndroid Build Coastguard Worker         TestCase {
173*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha256,
174*9860b763SAndroid Build Coastguard Worker             tag_size:     32,
175*9860b763SAndroid Build Coastguard Worker             data:         b"Hello",
176*9860b763SAndroid Build Coastguard Worker             key:          b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
177*9860b763SAndroid Build Coastguard Worker             expected_mac: "e0ff02553d9a619661026c7aa1ddf59b7b44eac06a9908ff9e19961d481935d4",
178*9860b763SAndroid Build Coastguard Worker         },
179*9860b763SAndroid Build Coastguard Worker         TestCase {
180*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha512,
181*9860b763SAndroid Build Coastguard Worker             tag_size:     64,
182*9860b763SAndroid Build Coastguard Worker             data:         b"Hello",
183*9860b763SAndroid Build Coastguard Worker             key:          b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
184*9860b763SAndroid Build Coastguard Worker             expected_mac: "481e10d823ba64c15b94537a3de3f253c16642451ac45124dd4dde120bf1e5c15e55487d55ba72b43039f235226e7954cd5854b30abc4b5b53171a4177047c9b",
185*9860b763SAndroid Build Coastguard Worker         },
186*9860b763SAndroid Build Coastguard Worker         // empty data
187*9860b763SAndroid Build Coastguard Worker         TestCase {
188*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha256,
189*9860b763SAndroid Build Coastguard Worker             tag_size:     32,
190*9860b763SAndroid Build Coastguard Worker             data:         &[],
191*9860b763SAndroid Build Coastguard Worker             key:          b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
192*9860b763SAndroid Build Coastguard Worker             expected_mac: "07eff8b326b7798c9ccfcbdbe579489ac785a7995a04618b1a2813c26744777d",
193*9860b763SAndroid Build Coastguard Worker         },
194*9860b763SAndroid Build Coastguard Worker 
195*9860b763SAndroid Build Coastguard Worker         // Test cases from RFC 4231 Section 4.2
196*9860b763SAndroid Build Coastguard Worker         TestCase {
197*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha224,
198*9860b763SAndroid Build Coastguard Worker             tag_size: 224/8,
199*9860b763SAndroid Build Coastguard Worker             key: &[0x0b; 20],
200*9860b763SAndroid Build Coastguard Worker             data: b"Hi There",
201*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
202*9860b763SAndroid Build Coastguard Worker                 "896fb1128abbdf196832107cd49df33f",
203*9860b763SAndroid Build Coastguard Worker                 "47b4b1169912ba4f53684b22",
204*9860b763SAndroid Build Coastguard Worker             ),
205*9860b763SAndroid Build Coastguard Worker         },
206*9860b763SAndroid Build Coastguard Worker         TestCase {
207*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha256,
208*9860b763SAndroid Build Coastguard Worker             tag_size: 256/8,
209*9860b763SAndroid Build Coastguard Worker             key: &[0x0b; 20],
210*9860b763SAndroid Build Coastguard Worker             data: b"Hi There",
211*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
212*9860b763SAndroid Build Coastguard Worker                 "b0344c61d8db38535ca8afceaf0bf12b",
213*9860b763SAndroid Build Coastguard Worker                 "881dc200c9833da726e9376c2e32cff7",
214*9860b763SAndroid Build Coastguard Worker             ),
215*9860b763SAndroid Build Coastguard Worker         },
216*9860b763SAndroid Build Coastguard Worker         TestCase {
217*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha384,
218*9860b763SAndroid Build Coastguard Worker             tag_size: 384/8,
219*9860b763SAndroid Build Coastguard Worker             key: &[0x0b; 20],
220*9860b763SAndroid Build Coastguard Worker             data: b"Hi There",
221*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
222*9860b763SAndroid Build Coastguard Worker                 "afd03944d84895626b0825f4ab46907f",
223*9860b763SAndroid Build Coastguard Worker                 "15f9dadbe4101ec682aa034c7cebc59c",
224*9860b763SAndroid Build Coastguard Worker                 "faea9ea9076ede7f4af152e8b2fa9cb6",
225*9860b763SAndroid Build Coastguard Worker             ),
226*9860b763SAndroid Build Coastguard Worker         },
227*9860b763SAndroid Build Coastguard Worker         TestCase {
228*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha512,
229*9860b763SAndroid Build Coastguard Worker             tag_size: 512/8,
230*9860b763SAndroid Build Coastguard Worker             key: &[0x0b; 20],
231*9860b763SAndroid Build Coastguard Worker             data: b"Hi There",
232*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
233*9860b763SAndroid Build Coastguard Worker                 "87aa7cdea5ef619d4ff0b4241a1d6cb0",
234*9860b763SAndroid Build Coastguard Worker                 "2379f4e2ce4ec2787ad0b30545e17cde",
235*9860b763SAndroid Build Coastguard Worker                 "daa833b7d6b8a702038b274eaea3f4e4",
236*9860b763SAndroid Build Coastguard Worker                 "be9d914eeb61f1702e696c203a126854"
237*9860b763SAndroid Build Coastguard Worker             ),
238*9860b763SAndroid Build Coastguard Worker         },
239*9860b763SAndroid Build Coastguard Worker         // Test cases from RFC 4231 Section 4.3
240*9860b763SAndroid Build Coastguard Worker         TestCase {
241*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha224,
242*9860b763SAndroid Build Coastguard Worker             tag_size: 224/8,
243*9860b763SAndroid Build Coastguard Worker             key: b"Jefe",
244*9860b763SAndroid Build Coastguard Worker             data: b"what do ya want for nothing?",
245*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
246*9860b763SAndroid Build Coastguard Worker                 "a30e01098bc6dbbf45690f3a7e9e6d0f",
247*9860b763SAndroid Build Coastguard Worker                 "8bbea2a39e6148008fd05e44"
248*9860b763SAndroid Build Coastguard Worker             ),
249*9860b763SAndroid Build Coastguard Worker         },
250*9860b763SAndroid Build Coastguard Worker         TestCase {
251*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha256,
252*9860b763SAndroid Build Coastguard Worker             tag_size: 256/8,
253*9860b763SAndroid Build Coastguard Worker             key: b"Jefe",
254*9860b763SAndroid Build Coastguard Worker             data: b"what do ya want for nothing?",
255*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
256*9860b763SAndroid Build Coastguard Worker                 "5bdcc146bf60754e6a042426089575c7",
257*9860b763SAndroid Build Coastguard Worker                 "5a003f089d2739839dec58b964ec3843"
258*9860b763SAndroid Build Coastguard Worker             ),
259*9860b763SAndroid Build Coastguard Worker         },
260*9860b763SAndroid Build Coastguard Worker         TestCase {
261*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha384,
262*9860b763SAndroid Build Coastguard Worker             tag_size: 384/8,
263*9860b763SAndroid Build Coastguard Worker             key: b"Jefe",
264*9860b763SAndroid Build Coastguard Worker             data: b"what do ya want for nothing?",
265*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
266*9860b763SAndroid Build Coastguard Worker                 "af45d2e376484031617f78d2b58a6b1b",
267*9860b763SAndroid Build Coastguard Worker                 "9c7ef464f5a01b47e42ec3736322445e",
268*9860b763SAndroid Build Coastguard Worker                 "8e2240ca5e69e2c78b3239ecfab21649"
269*9860b763SAndroid Build Coastguard Worker             ),
270*9860b763SAndroid Build Coastguard Worker         },
271*9860b763SAndroid Build Coastguard Worker         TestCase {
272*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha512,
273*9860b763SAndroid Build Coastguard Worker             tag_size: 512/8,
274*9860b763SAndroid Build Coastguard Worker             key: b"Jefe",
275*9860b763SAndroid Build Coastguard Worker             data: b"what do ya want for nothing?",
276*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
277*9860b763SAndroid Build Coastguard Worker                 "164b7a7bfcf819e2e395fbe73b56e0a3",
278*9860b763SAndroid Build Coastguard Worker                 "87bd64222e831fd610270cd7ea250554",
279*9860b763SAndroid Build Coastguard Worker                 "9758bf75c05a994a6d034f65f8f0e6fd",
280*9860b763SAndroid Build Coastguard Worker                 "caeab1a34d4a6b4b636e070a38bce737"
281*9860b763SAndroid Build Coastguard Worker             ),
282*9860b763SAndroid Build Coastguard Worker         },
283*9860b763SAndroid Build Coastguard Worker         // Test cases from RFC 4231 Section 4.4
284*9860b763SAndroid Build Coastguard Worker         TestCase {
285*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha224,
286*9860b763SAndroid Build Coastguard Worker             tag_size: 224/8,
287*9860b763SAndroid Build Coastguard Worker             key: &[0xaa; 20],
288*9860b763SAndroid Build Coastguard Worker             data: &[0xdd; 50],
289*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
290*9860b763SAndroid Build Coastguard Worker                 "7fb3cb3588c6c1f6ffa9694d7d6ad264",
291*9860b763SAndroid Build Coastguard Worker                 "9365b0c1f65d69d1ec8333ea"
292*9860b763SAndroid Build Coastguard Worker             ),
293*9860b763SAndroid Build Coastguard Worker         },
294*9860b763SAndroid Build Coastguard Worker         TestCase {
295*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha256,
296*9860b763SAndroid Build Coastguard Worker             tag_size: 256/8,
297*9860b763SAndroid Build Coastguard Worker             key: &[0xaa; 20],
298*9860b763SAndroid Build Coastguard Worker             data: &[0xdd; 50],
299*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
300*9860b763SAndroid Build Coastguard Worker                 "773ea91e36800e46854db8ebd09181a7",
301*9860b763SAndroid Build Coastguard Worker                 "2959098b3ef8c122d9635514ced565fe"
302*9860b763SAndroid Build Coastguard Worker             ),
303*9860b763SAndroid Build Coastguard Worker         },
304*9860b763SAndroid Build Coastguard Worker         TestCase {
305*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha384,
306*9860b763SAndroid Build Coastguard Worker             tag_size: 384/8,
307*9860b763SAndroid Build Coastguard Worker             key: &[0xaa; 20],
308*9860b763SAndroid Build Coastguard Worker             data: &[0xdd; 50],
309*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
310*9860b763SAndroid Build Coastguard Worker                 "88062608d3e6ad8a0aa2ace014c8a86f",
311*9860b763SAndroid Build Coastguard Worker                 "0aa635d947ac9febe83ef4e55966144b",
312*9860b763SAndroid Build Coastguard Worker                 "2a5ab39dc13814b94e3ab6e101a34f27"
313*9860b763SAndroid Build Coastguard Worker             ),
314*9860b763SAndroid Build Coastguard Worker         },
315*9860b763SAndroid Build Coastguard Worker         TestCase {
316*9860b763SAndroid Build Coastguard Worker             digest: Digest::Sha512,
317*9860b763SAndroid Build Coastguard Worker             tag_size: 512/8,
318*9860b763SAndroid Build Coastguard Worker             key: &[0xaa; 20],
319*9860b763SAndroid Build Coastguard Worker             data: &[0xdd; 50],
320*9860b763SAndroid Build Coastguard Worker             expected_mac: concat!(
321*9860b763SAndroid Build Coastguard Worker                 "fa73b0089d56a284efb0f0756c890be9",
322*9860b763SAndroid Build Coastguard Worker                 "b1b5dbdd8ee81a3655f83e33b2279d39",
323*9860b763SAndroid Build Coastguard Worker                 "bf3e848279a722c806b485a47e67c807",
324*9860b763SAndroid Build Coastguard Worker                 "b946a337bee8942674278859e13292fb"
325*9860b763SAndroid Build Coastguard Worker             ),
326*9860b763SAndroid Build Coastguard Worker         },
327*9860b763SAndroid Build Coastguard Worker     ];
328*9860b763SAndroid Build Coastguard Worker 
329*9860b763SAndroid Build Coastguard Worker     for (i, test) in HMAC_TESTS.iter().enumerate() {
330*9860b763SAndroid Build Coastguard Worker         let mut op = hmac.begin(hmac::Key(test.key.to_vec()).into(), test.digest).unwrap();
331*9860b763SAndroid Build Coastguard Worker         op.update(test.data).unwrap();
332*9860b763SAndroid Build Coastguard Worker         let mut mac = op.finish().unwrap();
333*9860b763SAndroid Build Coastguard Worker         mac.truncate(test.tag_size);
334*9860b763SAndroid Build Coastguard Worker 
335*9860b763SAndroid Build Coastguard Worker         assert_eq!(
336*9860b763SAndroid Build Coastguard Worker             hex::encode(&mac),
337*9860b763SAndroid Build Coastguard Worker             test.expected_mac[..(test.tag_size * 2)],
338*9860b763SAndroid Build Coastguard Worker             "incorrect mac in test case {}",
339*9860b763SAndroid Build Coastguard Worker             i
340*9860b763SAndroid Build Coastguard Worker         );
341*9860b763SAndroid Build Coastguard Worker     }
342*9860b763SAndroid Build Coastguard Worker }
343*9860b763SAndroid Build Coastguard Worker 
344*9860b763SAndroid Build Coastguard Worker /// Test basic [`AesCmac`] functionality.
test_aes_cmac<M: AesCmac>(cmac: M)345*9860b763SAndroid Build Coastguard Worker pub fn test_aes_cmac<M: AesCmac>(cmac: M) {
346*9860b763SAndroid Build Coastguard Worker     // Test vectors from RFC 4493.
347*9860b763SAndroid Build Coastguard Worker     let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").expect("Could not decode key");
348*9860b763SAndroid Build Coastguard Worker     let key = aes::Key::new(key).unwrap();
349*9860b763SAndroid Build Coastguard Worker     let data = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710").expect("Could not decode data");
350*9860b763SAndroid Build Coastguard Worker     let expected = vec![
351*9860b763SAndroid Build Coastguard Worker         (0usize, "bb1d6929e95937287fa37d129b756746"),
352*9860b763SAndroid Build Coastguard Worker         (16usize, "070a16b46b4d4144f79bdd9dd04a287c"),
353*9860b763SAndroid Build Coastguard Worker         (40usize, "dfa66747de9ae63030ca32611497c827"),
354*9860b763SAndroid Build Coastguard Worker         (64usize, "51f0bebf7e3b9d92fc49741779363cfe"),
355*9860b763SAndroid Build Coastguard Worker     ]
356*9860b763SAndroid Build Coastguard Worker     .into_iter()
357*9860b763SAndroid Build Coastguard Worker     .collect::<HashMap<usize, &'static str>>();
358*9860b763SAndroid Build Coastguard Worker 
359*9860b763SAndroid Build Coastguard Worker     for (len, want) in expected {
360*9860b763SAndroid Build Coastguard Worker         let mut op = cmac.begin(key.clone().into()).unwrap();
361*9860b763SAndroid Build Coastguard Worker         op.update(&data[..len]).unwrap();
362*9860b763SAndroid Build Coastguard Worker         let cmac = op.finish().unwrap();
363*9860b763SAndroid Build Coastguard Worker 
364*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(&cmac[..16]), want);
365*9860b763SAndroid Build Coastguard Worker     }
366*9860b763SAndroid Build Coastguard Worker }
367*9860b763SAndroid Build Coastguard Worker 
368*9860b763SAndroid Build Coastguard Worker /// Test `ckdf()` functionality based on an underlying [`AesCmac`] implementation.
test_ckdf<T: Ckdf>(kdf: T)369*9860b763SAndroid Build Coastguard Worker pub fn test_ckdf<T: Ckdf>(kdf: T) {
370*9860b763SAndroid Build Coastguard Worker     // Test data manually generated from Android C++ implementation.
371*9860b763SAndroid Build Coastguard Worker     let key = aes::Key::new(vec![0; 32]).unwrap();
372*9860b763SAndroid Build Coastguard Worker     let label = b"KeymasterSharedMac";
373*9860b763SAndroid Build Coastguard Worker     let v0 = vec![0x00, 0x00, 0x00, 0x00];
374*9860b763SAndroid Build Coastguard Worker     let v1 = vec![0x01, 0x01, 0x01, 0x01];
375*9860b763SAndroid Build Coastguard Worker     let v2 = vec![0x02, 0x02, 0x02, 0x02];
376*9860b763SAndroid Build Coastguard Worker     let v3 = vec![0x03, 0x03, 0x03, 0x03];
377*9860b763SAndroid Build Coastguard Worker 
378*9860b763SAndroid Build Coastguard Worker     let result = kdf.ckdf(&key.into(), label, &[&v0, &v1, &v2, &v3], 32).unwrap();
379*9860b763SAndroid Build Coastguard Worker     assert_eq!(
380*9860b763SAndroid Build Coastguard Worker         hex::encode(result),
381*9860b763SAndroid Build Coastguard Worker         concat!("ac9af88a02241f53d43056a4676c42ee", "f06825755e419e7bd20f4e57487717aa")
382*9860b763SAndroid Build Coastguard Worker     );
383*9860b763SAndroid Build Coastguard Worker }
384*9860b763SAndroid Build Coastguard Worker 
385*9860b763SAndroid Build Coastguard Worker /// Test AES-GCM functionality.
test_aes_gcm<A: Aes>(aes: A)386*9860b763SAndroid Build Coastguard Worker pub fn test_aes_gcm<A: Aes>(aes: A) {
387*9860b763SAndroid Build Coastguard Worker     struct TestCase {
388*9860b763SAndroid Build Coastguard Worker         key: &'static str,
389*9860b763SAndroid Build Coastguard Worker         iv: &'static str,
390*9860b763SAndroid Build Coastguard Worker         aad: &'static str,
391*9860b763SAndroid Build Coastguard Worker         msg: &'static str,
392*9860b763SAndroid Build Coastguard Worker         ct: &'static str,
393*9860b763SAndroid Build Coastguard Worker         tag: &'static str,
394*9860b763SAndroid Build Coastguard Worker     }
395*9860b763SAndroid Build Coastguard Worker     // Test vectors from https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_test.json
396*9860b763SAndroid Build Coastguard Worker     let tests = vec![
397*9860b763SAndroid Build Coastguard Worker         TestCase {
398*9860b763SAndroid Build Coastguard Worker             key: "5b9604fe14eadba931b0ccf34843dab9",
399*9860b763SAndroid Build Coastguard Worker             iv: "028318abc1824029138141a2",
400*9860b763SAndroid Build Coastguard Worker             aad: "",
401*9860b763SAndroid Build Coastguard Worker             msg: "001d0c231287c1182784554ca3a21908",
402*9860b763SAndroid Build Coastguard Worker             ct: "26073cc1d851beff176384dc9896d5ff",
403*9860b763SAndroid Build Coastguard Worker             tag: "0a3ea7a5487cb5f7d70fb6c58d038554",
404*9860b763SAndroid Build Coastguard Worker         },
405*9860b763SAndroid Build Coastguard Worker         TestCase {
406*9860b763SAndroid Build Coastguard Worker             key: "5b9604fe14eadba931b0ccf34843dab9",
407*9860b763SAndroid Build Coastguard Worker             iv: "921d2507fa8007b7bd067d34",
408*9860b763SAndroid Build Coastguard Worker             aad: "00112233445566778899aabbccddeeff",
409*9860b763SAndroid Build Coastguard Worker             msg: "001d0c231287c1182784554ca3a21908",
410*9860b763SAndroid Build Coastguard Worker             ct: "49d8b9783e911913d87094d1f63cc765",
411*9860b763SAndroid Build Coastguard Worker             tag: "1e348ba07cca2cf04c618cb4d43a5b92",
412*9860b763SAndroid Build Coastguard Worker         },
413*9860b763SAndroid Build Coastguard Worker     ];
414*9860b763SAndroid Build Coastguard Worker     for test in tests {
415*9860b763SAndroid Build Coastguard Worker         let key = hex::decode(test.key).unwrap();
416*9860b763SAndroid Build Coastguard Worker         let iv = hex::decode(test.iv).unwrap();
417*9860b763SAndroid Build Coastguard Worker         assert_eq!(iv.len(), 12); // Only 96-bit nonces supported.
418*9860b763SAndroid Build Coastguard Worker         let aad = hex::decode(test.aad).unwrap();
419*9860b763SAndroid Build Coastguard Worker         let msg = hex::decode(test.msg).unwrap();
420*9860b763SAndroid Build Coastguard Worker         let tag = hex::decode(test.tag).unwrap();
421*9860b763SAndroid Build Coastguard Worker         assert_eq!(tag.len(), 16); // Test data includes full 128-bit tag
422*9860b763SAndroid Build Coastguard Worker 
423*9860b763SAndroid Build Coastguard Worker         let aes_key = aes::Key::new(key.clone()).unwrap();
424*9860b763SAndroid Build Coastguard Worker         let mut op = aes
425*9860b763SAndroid Build Coastguard Worker             .begin_aead(
426*9860b763SAndroid Build Coastguard Worker                 aes_key.into(),
427*9860b763SAndroid Build Coastguard Worker                 aes::GcmMode::GcmTag16 { nonce: iv.clone().try_into().unwrap() },
428*9860b763SAndroid Build Coastguard Worker                 SymmetricOperation::Encrypt,
429*9860b763SAndroid Build Coastguard Worker             )
430*9860b763SAndroid Build Coastguard Worker             .unwrap();
431*9860b763SAndroid Build Coastguard Worker         op.update_aad(&aad).unwrap();
432*9860b763SAndroid Build Coastguard Worker         let mut got_ct = op.update(&msg).unwrap();
433*9860b763SAndroid Build Coastguard Worker         got_ct.extend_from_slice(&op.finish().unwrap());
434*9860b763SAndroid Build Coastguard Worker         assert_eq!(format!("{}{}", test.ct, test.tag), hex::encode(&got_ct));
435*9860b763SAndroid Build Coastguard Worker 
436*9860b763SAndroid Build Coastguard Worker         let aes_key = aes::Key::new(key.clone()).unwrap();
437*9860b763SAndroid Build Coastguard Worker         let mut op = aes
438*9860b763SAndroid Build Coastguard Worker             .begin_aead(
439*9860b763SAndroid Build Coastguard Worker                 aes_key.into(),
440*9860b763SAndroid Build Coastguard Worker                 aes::GcmMode::GcmTag16 { nonce: iv.clone().try_into().unwrap() },
441*9860b763SAndroid Build Coastguard Worker                 SymmetricOperation::Decrypt,
442*9860b763SAndroid Build Coastguard Worker             )
443*9860b763SAndroid Build Coastguard Worker             .unwrap();
444*9860b763SAndroid Build Coastguard Worker         op.update_aad(&aad).unwrap();
445*9860b763SAndroid Build Coastguard Worker         let mut got_pt = op.update(&got_ct).unwrap();
446*9860b763SAndroid Build Coastguard Worker         got_pt.extend_from_slice(&op.finish().unwrap());
447*9860b763SAndroid Build Coastguard Worker         assert_eq!(test.msg, hex::encode(&got_pt));
448*9860b763SAndroid Build Coastguard Worker 
449*9860b763SAndroid Build Coastguard Worker         // Truncated tag should still decrypt.
450*9860b763SAndroid Build Coastguard Worker         let aes_key = aes::Key::new(key.clone()).unwrap();
451*9860b763SAndroid Build Coastguard Worker         let mut op = match aes.begin_aead(
452*9860b763SAndroid Build Coastguard Worker             aes_key.into(),
453*9860b763SAndroid Build Coastguard Worker             aes::GcmMode::GcmTag12 { nonce: iv.clone().try_into().unwrap() },
454*9860b763SAndroid Build Coastguard Worker             SymmetricOperation::Decrypt,
455*9860b763SAndroid Build Coastguard Worker         ) {
456*9860b763SAndroid Build Coastguard Worker             Ok(c) => c,
457*9860b763SAndroid Build Coastguard Worker             Err(_) => return,
458*9860b763SAndroid Build Coastguard Worker         };
459*9860b763SAndroid Build Coastguard Worker         op.update_aad(&aad).unwrap();
460*9860b763SAndroid Build Coastguard Worker         let mut got_pt = op.update(&got_ct[..got_ct.len() - 4]).unwrap();
461*9860b763SAndroid Build Coastguard Worker         got_pt.extend_from_slice(&op.finish().unwrap());
462*9860b763SAndroid Build Coastguard Worker         assert_eq!(test.msg, hex::encode(&got_pt));
463*9860b763SAndroid Build Coastguard Worker 
464*9860b763SAndroid Build Coastguard Worker         // Corrupted ciphertext should not decrypt.
465*9860b763SAndroid Build Coastguard Worker         let aes_key = aes::Key::new(key).unwrap();
466*9860b763SAndroid Build Coastguard Worker         let mut op = match aes.begin_aead(
467*9860b763SAndroid Build Coastguard Worker             aes_key.into(),
468*9860b763SAndroid Build Coastguard Worker             aes::GcmMode::GcmTag12 { nonce: iv.try_into().unwrap() },
469*9860b763SAndroid Build Coastguard Worker             SymmetricOperation::Decrypt,
470*9860b763SAndroid Build Coastguard Worker         ) {
471*9860b763SAndroid Build Coastguard Worker             Ok(c) => c,
472*9860b763SAndroid Build Coastguard Worker             Err(_) => return,
473*9860b763SAndroid Build Coastguard Worker         };
474*9860b763SAndroid Build Coastguard Worker         op.update_aad(&aad).unwrap();
475*9860b763SAndroid Build Coastguard Worker         let mut corrupt_ct = got_ct.clone();
476*9860b763SAndroid Build Coastguard Worker         corrupt_ct[0] ^= 0x01;
477*9860b763SAndroid Build Coastguard Worker         let _corrupt_pt = op.update(&corrupt_ct).unwrap();
478*9860b763SAndroid Build Coastguard Worker         let result = op.finish();
479*9860b763SAndroid Build Coastguard Worker         assert!(result.is_err());
480*9860b763SAndroid Build Coastguard Worker     }
481*9860b763SAndroid Build Coastguard Worker }
482*9860b763SAndroid Build Coastguard Worker 
483*9860b763SAndroid Build Coastguard Worker /// Test basic triple-DES functionality.
test_des<D: Des>(des: D)484*9860b763SAndroid Build Coastguard Worker pub fn test_des<D: Des>(des: D) {
485*9860b763SAndroid Build Coastguard Worker     struct TestCase {
486*9860b763SAndroid Build Coastguard Worker         key: &'static str,
487*9860b763SAndroid Build Coastguard Worker         msg: &'static str,
488*9860b763SAndroid Build Coastguard Worker         ct: &'static str,
489*9860b763SAndroid Build Coastguard Worker     }
490*9860b763SAndroid Build Coastguard Worker     let tests = vec![
491*9860b763SAndroid Build Coastguard Worker         TestCase {
492*9860b763SAndroid Build Coastguard Worker             key: "800000000000000000000000000000000000000000000000",
493*9860b763SAndroid Build Coastguard Worker             msg: "0000000000000000",
494*9860b763SAndroid Build Coastguard Worker             ct: "95a8d72813daa94d",
495*9860b763SAndroid Build Coastguard Worker         },
496*9860b763SAndroid Build Coastguard Worker         TestCase {
497*9860b763SAndroid Build Coastguard Worker             key: "000000000000000000000000000000002000000000000000",
498*9860b763SAndroid Build Coastguard Worker             msg: "0000000000000000",
499*9860b763SAndroid Build Coastguard Worker             ct: "7ad16ffb79c45926",
500*9860b763SAndroid Build Coastguard Worker         },
501*9860b763SAndroid Build Coastguard Worker     ];
502*9860b763SAndroid Build Coastguard Worker     for test in tests {
503*9860b763SAndroid Build Coastguard Worker         let key = hex::decode(test.key).unwrap();
504*9860b763SAndroid Build Coastguard Worker         let msg = hex::decode(test.msg).unwrap();
505*9860b763SAndroid Build Coastguard Worker 
506*9860b763SAndroid Build Coastguard Worker         let des_key = des::Key::new(key.clone()).unwrap();
507*9860b763SAndroid Build Coastguard Worker         let mut op = des
508*9860b763SAndroid Build Coastguard Worker             .begin(des_key.clone().into(), des::Mode::EcbNoPadding, SymmetricOperation::Encrypt)
509*9860b763SAndroid Build Coastguard Worker             .unwrap();
510*9860b763SAndroid Build Coastguard Worker         let mut got_ct = op.update(&msg).unwrap();
511*9860b763SAndroid Build Coastguard Worker         got_ct.extend_from_slice(&op.finish().unwrap());
512*9860b763SAndroid Build Coastguard Worker         assert_eq!(test.ct, hex::encode(&got_ct));
513*9860b763SAndroid Build Coastguard Worker 
514*9860b763SAndroid Build Coastguard Worker         let mut op = des
515*9860b763SAndroid Build Coastguard Worker             .begin(des_key.into(), des::Mode::EcbNoPadding, SymmetricOperation::Decrypt)
516*9860b763SAndroid Build Coastguard Worker             .unwrap();
517*9860b763SAndroid Build Coastguard Worker         let mut got_pt = op.update(&got_ct).unwrap();
518*9860b763SAndroid Build Coastguard Worker         got_pt.extend_from_slice(&op.finish().unwrap());
519*9860b763SAndroid Build Coastguard Worker         assert_eq!(test.msg, hex::encode(&got_pt));
520*9860b763SAndroid Build Coastguard Worker     }
521*9860b763SAndroid Build Coastguard Worker }
522*9860b763SAndroid Build Coastguard Worker 
523*9860b763SAndroid Build Coastguard Worker /// Test basic SHA-256 functionality.
test_sha256<S: Sha256>(sha256: S)524*9860b763SAndroid Build Coastguard Worker pub fn test_sha256<S: Sha256>(sha256: S) {
525*9860b763SAndroid Build Coastguard Worker     struct TestCase {
526*9860b763SAndroid Build Coastguard Worker         msg: &'static [u8],
527*9860b763SAndroid Build Coastguard Worker         want: &'static str,
528*9860b763SAndroid Build Coastguard Worker     }
529*9860b763SAndroid Build Coastguard Worker     let tests = vec![
530*9860b763SAndroid Build Coastguard Worker         TestCase {
531*9860b763SAndroid Build Coastguard Worker             msg: b"",
532*9860b763SAndroid Build Coastguard Worker             want: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
533*9860b763SAndroid Build Coastguard Worker         },
534*9860b763SAndroid Build Coastguard Worker         TestCase {
535*9860b763SAndroid Build Coastguard Worker             msg: b"abc",
536*9860b763SAndroid Build Coastguard Worker             want: "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
537*9860b763SAndroid Build Coastguard Worker         },
538*9860b763SAndroid Build Coastguard Worker     ];
539*9860b763SAndroid Build Coastguard Worker     for test in tests {
540*9860b763SAndroid Build Coastguard Worker         let got = sha256.hash(test.msg).unwrap();
541*9860b763SAndroid Build Coastguard Worker         assert_eq!(hex::encode(got), test.want, "for input {}", hex::encode(test.msg));
542*9860b763SAndroid Build Coastguard Worker     }
543*9860b763SAndroid Build Coastguard Worker }
544*9860b763SAndroid Build Coastguard Worker 
545*9860b763SAndroid Build Coastguard Worker /// Test secure deletion secret management.
546*9860b763SAndroid Build Coastguard Worker ///
547*9860b763SAndroid Build Coastguard Worker /// Warning: this test will use slots in the provided manager, and may leak slots on failure.
test_sdd_mgr<M: keyblob::SecureDeletionSecretManager, R: Rng>(mut sdd_mgr: M, mut rng: R)548*9860b763SAndroid Build Coastguard Worker pub fn test_sdd_mgr<M: keyblob::SecureDeletionSecretManager, R: Rng>(mut sdd_mgr: M, mut rng: R) {
549*9860b763SAndroid Build Coastguard Worker     let (slot1, sdd1) = sdd_mgr.new_secret(&mut rng, SlotPurpose::KeyGeneration).unwrap();
550*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.get_secret(slot1).unwrap() == sdd1);
551*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.get_secret(slot1).unwrap() == sdd1);
552*9860b763SAndroid Build Coastguard Worker 
553*9860b763SAndroid Build Coastguard Worker     // A second instance should share factory reset secret but not per-key secret.
554*9860b763SAndroid Build Coastguard Worker     let (slot2, sdd2) = sdd_mgr.new_secret(&mut rng, SlotPurpose::KeyGeneration).unwrap();
555*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.get_secret(slot2).unwrap() == sdd2);
556*9860b763SAndroid Build Coastguard Worker     assert_eq!(sdd1.factory_reset_secret, sdd2.factory_reset_secret);
557*9860b763SAndroid Build Coastguard Worker     assert_ne!(sdd1.secure_deletion_secret, sdd2.secure_deletion_secret);
558*9860b763SAndroid Build Coastguard Worker 
559*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.delete_secret(slot1).is_ok());
560*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.get_secret(slot1).is_err());
561*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.delete_secret(slot1).is_err());
562*9860b763SAndroid Build Coastguard Worker 
563*9860b763SAndroid Build Coastguard Worker     assert!(sdd_mgr.delete_secret(slot2).is_ok());
564*9860b763SAndroid Build Coastguard Worker }
565*9860b763SAndroid Build Coastguard Worker 
566*9860b763SAndroid Build Coastguard Worker /// Test that attestation certificates parse as X.509 structures.
test_signing_cert_parse<T: kmr_ta::device::RetrieveCertSigningInfo>( certs: T, is_strongbox: bool, )567*9860b763SAndroid Build Coastguard Worker pub fn test_signing_cert_parse<T: kmr_ta::device::RetrieveCertSigningInfo>(
568*9860b763SAndroid Build Coastguard Worker     certs: T,
569*9860b763SAndroid Build Coastguard Worker     is_strongbox: bool,
570*9860b763SAndroid Build Coastguard Worker ) {
571*9860b763SAndroid Build Coastguard Worker     let avail = if is_strongbox {
572*9860b763SAndroid Build Coastguard Worker         vec![SigningKey::Batch, SigningKey::DeviceUnique]
573*9860b763SAndroid Build Coastguard Worker     } else {
574*9860b763SAndroid Build Coastguard Worker         vec![SigningKey::Batch]
575*9860b763SAndroid Build Coastguard Worker     };
576*9860b763SAndroid Build Coastguard Worker     for which in avail {
577*9860b763SAndroid Build Coastguard Worker         for algo_hint in [SigningAlgorithm::Ec, SigningAlgorithm::Rsa] {
578*9860b763SAndroid Build Coastguard Worker             let info = SigningKeyType { which, algo_hint };
579*9860b763SAndroid Build Coastguard Worker             let chain = certs
580*9860b763SAndroid Build Coastguard Worker                 .cert_chain(info)
581*9860b763SAndroid Build Coastguard Worker                 .unwrap_or_else(|_| panic!("failed to retrieve chain for {:?}", info));
582*9860b763SAndroid Build Coastguard Worker 
583*9860b763SAndroid Build Coastguard Worker             // Check that the attestation chain looks basically valid (parses as DER,
584*9860b763SAndroid Build Coastguard Worker             // has subject/issuer match).
585*9860b763SAndroid Build Coastguard Worker             let mut prev_subject_data = vec![];
586*9860b763SAndroid Build Coastguard Worker             for (idx, cert) in chain.iter().rev().enumerate() {
587*9860b763SAndroid Build Coastguard Worker                 let cert = x509_cert::Certificate::from_der(&cert.encoded_certificate)
588*9860b763SAndroid Build Coastguard Worker                     .expect("failed to parse cert");
589*9860b763SAndroid Build Coastguard Worker 
590*9860b763SAndroid Build Coastguard Worker                 let subject_data = cert.tbs_certificate.subject.to_der().unwrap();
591*9860b763SAndroid Build Coastguard Worker                 let issuer_data = cert.tbs_certificate.issuer.to_der().unwrap();
592*9860b763SAndroid Build Coastguard Worker                 if idx == 0 {
593*9860b763SAndroid Build Coastguard Worker                     // First cert should be self-signed, and so have subject==issuer.
594*9860b763SAndroid Build Coastguard Worker                     assert_eq!(
595*9860b763SAndroid Build Coastguard Worker                         hex::encode(&subject_data),
596*9860b763SAndroid Build Coastguard Worker                         hex::encode(&issuer_data),
597*9860b763SAndroid Build Coastguard Worker                         "root cert has subject != issuer for {:?}",
598*9860b763SAndroid Build Coastguard Worker                         info
599*9860b763SAndroid Build Coastguard Worker                     );
600*9860b763SAndroid Build Coastguard Worker                 } else {
601*9860b763SAndroid Build Coastguard Worker                     // Issuer of cert should be the subject of the previous cert.
602*9860b763SAndroid Build Coastguard Worker                     assert_eq!(
603*9860b763SAndroid Build Coastguard Worker                         hex::encode(&prev_subject_data),
604*9860b763SAndroid Build Coastguard Worker                         hex::encode(&issuer_data),
605*9860b763SAndroid Build Coastguard Worker                         "cert {} has issuer != prev_cert.subject for {:?}",
606*9860b763SAndroid Build Coastguard Worker                         idx,
607*9860b763SAndroid Build Coastguard Worker                         info
608*9860b763SAndroid Build Coastguard Worker                     )
609*9860b763SAndroid Build Coastguard Worker                 }
610*9860b763SAndroid Build Coastguard Worker                 prev_subject_data.clone_from(&subject_data);
611*9860b763SAndroid Build Coastguard Worker             }
612*9860b763SAndroid Build Coastguard Worker         }
613*9860b763SAndroid Build Coastguard Worker     }
614*9860b763SAndroid Build Coastguard Worker }
615*9860b763SAndroid Build Coastguard Worker 
616*9860b763SAndroid Build Coastguard Worker /// Simple smoke test for an `RetrieveRpcArtifacts` trait implementation.
test_retrieve_rpc_artifacts<T: kmr_ta::device::RetrieveRpcArtifacts>( rpc: T, hmac: &dyn Hmac, hkdf: &dyn Hkdf, )617*9860b763SAndroid Build Coastguard Worker pub fn test_retrieve_rpc_artifacts<T: kmr_ta::device::RetrieveRpcArtifacts>(
618*9860b763SAndroid Build Coastguard Worker     rpc: T,
619*9860b763SAndroid Build Coastguard Worker     hmac: &dyn Hmac,
620*9860b763SAndroid Build Coastguard Worker     hkdf: &dyn Hkdf,
621*9860b763SAndroid Build Coastguard Worker ) {
622*9860b763SAndroid Build Coastguard Worker     assert!(rpc.get_dice_info(rpc::TestMode(false)).is_ok());
623*9860b763SAndroid Build Coastguard Worker 
624*9860b763SAndroid Build Coastguard Worker     let context = b"abcdef";
625*9860b763SAndroid Build Coastguard Worker     let data1 = rpc.derive_bytes_from_hbk(hkdf, context, 16).expect("failed to derive from HBK");
626*9860b763SAndroid Build Coastguard Worker     let data2 = rpc.derive_bytes_from_hbk(hkdf, context, 16).expect("failed to derive from HBK");
627*9860b763SAndroid Build Coastguard Worker     assert_eq!(data1, data2, "derive_bytes_from_hbk() method should be deterministic");
628*9860b763SAndroid Build Coastguard Worker 
629*9860b763SAndroid Build Coastguard Worker     let data1 = rpc.compute_hmac_sha256(hmac, hkdf, context).expect("failed to perform HMAC");
630*9860b763SAndroid Build Coastguard Worker     let data2 = rpc.compute_hmac_sha256(hmac, hkdf, context).expect("failed to perform HMAC");
631*9860b763SAndroid Build Coastguard Worker     assert_eq!(data1, data2, "compute_hmac_sha256() method should be deterministic");
632*9860b763SAndroid Build Coastguard Worker }
633