1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use super::*;
18 use ::test::{assert, assert_eq, assert_ne};
19 
20 ::test::init!();
21 
22 const HWCRYPTO_UNITTEST_DERIVED_KEYBOX_ID: &'static [u8] =
23     b"com.android.trusty.hwcrypto.unittest.derived_key32\0";
24 const HWCRYPTO_UNITTEST_KEYBOX_ID: &'static [u8] = b"com.android.trusty.hwcrypto.unittest.key32\0";
25 const RPMB_STORAGE_AUTH_KEY_ID: &'static [u8] = b"com.android.trusty.storage_auth.rpmb\0";
26 const HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID: &'static [u8] =
27     b"com.android.trusty.hwcrypto.unittest.opaque_handle\0";
28 
29 #[cfg(feature = "hwcrypto-unittest")]
30 const HWCRYPTO_UNITTEST_OPAQUE_HANDLE_NOACCESS_ID: &'static [u8] =
31     b"com.android.trusty.hwcrypto.unittest.opaque_handle_noaccess\0";
32 
33 const UNITTEST_KEYSLOT: &'static [u8] = b"unittestkeyslotunittestkeyslotun";
34 const UNITTEST_DERIVED_KEYSLOT: &'static [u8] = b"unittestderivedkeyslotunittestde";
35 
36 const NONSENSE_DATA_32B: &'static [u8] = b"thirtytwo-bytes-of-nonsense-data";
37 
38 const KEY_SIZE: usize = 32;
39 
keys_are_sufficiently_distinct(key1: &[u8], key2: &[u8]) -> bool40 fn keys_are_sufficiently_distinct(key1: &[u8], key2: &[u8]) -> bool {
41     let (sk, lk) = if key1.len() < key2.len() { (key1, key2) } else { (key2, key1) };
42     let differing_bytes = sk.iter().zip(lk).filter(|&(s, l)| s ^ l != 0).count();
43     sk.len() - differing_bytes <= 4
44 }
45 
46 #[test]
test_hwkey_derive_repeatable_versioned()47 fn test_hwkey_derive_repeatable_versioned() {
48     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
49 
50     // derive key once
51     let buf = &mut [0u8; KEY_SIZE as usize];
52     let DeriveResult { kdf_version, os_rollback_version } = hwkey_session
53         .derive_key_req()
54         .unique_key()
55         .kdf(KdfVersion::Best)
56         .os_rollback_version(OsRollbackVersion::Version(0))
57         .rollback_version_source(RollbackVersionSource::CommittedVersion)
58         .derive(NONSENSE_DATA_32B, buf)
59         .expect("could not derive key");
60     assert_ne!(kdf_version, KdfVersion::Best);
61 
62     // derive key again
63     let buf2 = &mut [0u8; KEY_SIZE as usize];
64     let _ = hwkey_session
65         .derive_key_req()
66         .unique_key()
67         .kdf(kdf_version)
68         .os_rollback_version(os_rollback_version)
69         .rollback_version_source(RollbackVersionSource::CommittedVersion)
70         .derive(NONSENSE_DATA_32B, buf2)
71         .expect("could not derive key");
72 
73     // ensure they are the same
74     assert_eq!(buf, buf2);
75     assert_ne!(buf, NONSENSE_DATA_32B);
76 
77     // ensure that we don't derive the same key if deriving a shared key
78     buf2.fill(0);
79     let _ = hwkey_session
80         .derive_key_req()
81         .shared_key()
82         .kdf(kdf_version)
83         .os_rollback_version(os_rollback_version)
84         .rollback_version_source(RollbackVersionSource::CommittedVersion)
85         .derive(NONSENSE_DATA_32B, buf2)
86         .expect("could not derive key");
87     assert_ne!(buf, buf2);
88 
89     assert!(keys_are_sufficiently_distinct(buf, buf2));
90 
91     // ensure that we don't derive the same key if deriving
92     // a device-unique key that specifies the running version
93     // as the rollback version source
94     buf2.fill(0);
95     let DeriveResult { os_rollback_version, .. } = hwkey_session
96         .derive_key_req()
97         .unique_key()
98         .kdf(kdf_version)
99         .os_rollback_version(os_rollback_version)
100         .rollback_version_source(RollbackVersionSource::RunningVersion)
101         .derive(NONSENSE_DATA_32B, buf2)
102         .expect("could not derive key");
103 
104     match os_rollback_version {
105         OsRollbackVersion::Version(v) if v > 0 => {
106             assert_ne!(buf, buf2);
107             assert!(keys_are_sufficiently_distinct(buf, buf2))
108         }
109         OsRollbackVersion::Version(_) => {
110             assert_eq!(buf, buf2);
111         }
112         _ => {
113             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
114         }
115     }
116 }
117 
118 #[test]
test_hwkey_derive_different_default()119 fn test_hwkey_derive_different_default() {
120     const SRC_DATA2: &'static [u8] = b"thirtytwo-byt3s-of-nons3ns3-data";
121 
122     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
123 
124     // derive key once
125     let buf1 = &mut [0u8; KEY_SIZE as usize];
126     let DeriveResult { kdf_version, .. } = hwkey_session
127         .derive_key_req()
128         .derive(NONSENSE_DATA_32B, buf1)
129         .expect("could not derive key");
130 
131     assert_ne!(kdf_version, KdfVersion::Best);
132 
133     // derive key again, with different source data
134     let buf2 = &mut [0u8; KEY_SIZE as usize];
135     let _ = hwkey_session.derive_key_req().derive(SRC_DATA2, buf2).expect("could not derive key");
136 
137     // ensure they are not the same
138     assert_ne!(buf1, buf2);
139     assert_ne!(buf1, NONSENSE_DATA_32B);
140     assert_ne!(buf2, SRC_DATA2);
141     assert!(keys_are_sufficiently_distinct(buf1, buf2));
142 }
143 
144 #[test]
test_hwkey_derive_different_specified()145 fn test_hwkey_derive_different_specified() {
146     const SRC_DATA2: &'static [u8] = b"thirtytwo-byt3s-of-nons3ns3-data";
147 
148     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
149 
150     // derive key once
151     let buf1 = &mut [0u8; KEY_SIZE as usize];
152     let DeriveResult { kdf_version, os_rollback_version } = hwkey_session
153         .derive_key_req()
154         .kdf(KdfVersion::Best)
155         .rollback_version_source(RollbackVersionSource::RunningVersion)
156         .os_rollback_version(OsRollbackVersion::Current)
157         .unique_key()
158         .derive(NONSENSE_DATA_32B, buf1)
159         .expect("could not derive key");
160 
161     assert_ne!(kdf_version, KdfVersion::Best);
162 
163     let buf2 = &mut [0u8; KEY_SIZE as usize];
164     // derive with the same input but an older OS version
165     match os_rollback_version {
166         OsRollbackVersion::Version(n) if n >= 1 => {
167             let _ = hwkey_session
168                 .derive_key_req()
169                 .kdf(kdf_version)
170                 .rollback_version_source(RollbackVersionSource::RunningVersion)
171                 .os_rollback_version(OsRollbackVersion::Version(n - 1))
172                 .unique_key()
173                 .derive(NONSENSE_DATA_32B, buf2)
174                 .expect("could not derive key");
175 
176             assert_ne!(buf1, buf2);
177             assert_ne!(buf1, NONSENSE_DATA_32B);
178             assert_ne!(buf2, SRC_DATA2);
179             assert!(keys_are_sufficiently_distinct(buf1, buf2));
180         }
181         OsRollbackVersion::Version(_) => (),
182         _ => {
183             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
184         }
185     }
186 
187     // derive key again, with different source data
188     buf2.fill(0);
189     let _ = hwkey_session
190         .derive_key_req()
191         .kdf(kdf_version)
192         .rollback_version_source(RollbackVersionSource::RunningVersion)
193         .os_rollback_version(OsRollbackVersion::Current)
194         .unique_key()
195         .derive(SRC_DATA2, buf2)
196         .expect("could not derive key");
197 
198     // ensure they are not the same
199     assert_ne!(buf1, buf2);
200     assert_ne!(buf1, NONSENSE_DATA_32B);
201     assert_ne!(buf2, SRC_DATA2);
202     assert!(keys_are_sufficiently_distinct(buf1, buf2));
203 
204     // derive a shared key from the same input and ensure different
205     let buf_shared = &mut [0u8; KEY_SIZE as usize];
206     let _ = hwkey_session
207         .derive_key_req()
208         .kdf(kdf_version)
209         .rollback_version_source(RollbackVersionSource::RunningVersion)
210         .os_rollback_version(os_rollback_version)
211         .shared_key()
212         .derive(NONSENSE_DATA_32B, buf_shared)
213         .expect("could not derive key");
214 
215     // ensure they are not the same
216     assert_ne!(buf1, buf_shared);
217     assert_ne!(buf2, buf_shared);
218     assert_ne!(buf_shared, NONSENSE_DATA_32B);
219     assert!(keys_are_sufficiently_distinct(buf1, buf_shared));
220     assert!(keys_are_sufficiently_distinct(buf2, buf_shared));
221 
222     // shared key, different input
223     let buf_shared2 = &mut [0u8; KEY_SIZE as usize];
224     let DeriveResult { os_rollback_version, kdf_version } = hwkey_session
225         .derive_key_req()
226         .kdf(kdf_version)
227         .rollback_version_source(RollbackVersionSource::RunningVersion)
228         .os_rollback_version(OsRollbackVersion::Current)
229         .shared_key()
230         .derive(SRC_DATA2, buf_shared2)
231         .expect("could not derive key");
232 
233     // ensure they are not the same
234     assert_ne!(buf1, buf_shared2);
235     assert_ne!(buf2, buf_shared2);
236     assert_ne!(buf_shared, buf_shared2);
237     assert_ne!(buf_shared2, NONSENSE_DATA_32B);
238     assert!(keys_are_sufficiently_distinct(buf1, buf_shared2));
239     assert!(keys_are_sufficiently_distinct(buf2, buf_shared2));
240     assert!(keys_are_sufficiently_distinct(buf_shared, buf_shared2));
241 
242     // derive with the same input but an older OS version
243     match os_rollback_version {
244         OsRollbackVersion::Version(n) if n >= 1 => {
245             let _ = hwkey_session
246                 .derive_key_req()
247                 .kdf(kdf_version)
248                 .rollback_version_source(RollbackVersionSource::RunningVersion)
249                 .os_rollback_version(OsRollbackVersion::Version(n - 1))
250                 .shared_key()
251                 .derive(NONSENSE_DATA_32B, buf_shared2)
252                 .expect("could not derive key");
253 
254             // ensure they are not the same
255             assert_ne!(buf1, buf_shared2);
256             assert_ne!(buf2, buf_shared2);
257             assert_ne!(buf_shared, buf_shared2);
258             assert_ne!(buf_shared2, NONSENSE_DATA_32B);
259             assert!(keys_are_sufficiently_distinct(buf1, buf_shared2));
260             assert!(keys_are_sufficiently_distinct(buf2, buf_shared2));
261             assert!(keys_are_sufficiently_distinct(buf_shared, buf_shared2));
262         }
263         OsRollbackVersion::Version(_) => (),
264         _ => {
265             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
266         }
267     }
268 }
269 
270 #[test]
test_hwkey_derive_different_version_source()271 fn test_hwkey_derive_different_version_source() {
272     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
273 
274     // derive with current committed version
275     let buf1 = &mut [0u8; KEY_SIZE as usize];
276     let DeriveResult { kdf_version, os_rollback_version } = hwkey_session
277         .derive_key_req()
278         .kdf(KdfVersion::Best)
279         .rollback_version_source(RollbackVersionSource::CommittedVersion)
280         .os_rollback_version(OsRollbackVersion::Current)
281         .unique_key()
282         .derive(NONSENSE_DATA_32B, buf1)
283         .expect("could not derive key");
284 
285     assert_ne!(kdf_version, KdfVersion::Best);
286 
287     // derive with same input and rollback version, different version source
288     let buf2 = &mut [0u8; KEY_SIZE as usize];
289     let DeriveResult { os_rollback_version, .. } = hwkey_session
290         .derive_key_req()
291         .kdf(kdf_version)
292         .rollback_version_source(RollbackVersionSource::RunningVersion)
293         .os_rollback_version(os_rollback_version)
294         .unique_key()
295         .derive(NONSENSE_DATA_32B, buf2)
296         .expect("could not derive key");
297 
298     match os_rollback_version {
299         OsRollbackVersion::Version(n) if n > 0 => {
300             assert_ne!(buf1, buf2);
301             assert_ne!(buf1, NONSENSE_DATA_32B);
302             assert!(keys_are_sufficiently_distinct(buf1, buf2));
303         }
304         OsRollbackVersion::Version(_) => {
305             assert_eq!(buf1, buf2);
306         }
307         _ => {
308             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
309         }
310     }
311 
312     // derive shared key with 0 committed version
313     let buf_shared = &mut [0u8; KEY_SIZE as usize];
314     let DeriveResult { kdf_version, .. } = hwkey_session
315         .derive_key_req()
316         .kdf(KdfVersion::Best)
317         .rollback_version_source(RollbackVersionSource::CommittedVersion)
318         .os_rollback_version(OsRollbackVersion::Version(0))
319         .shared_key()
320         .derive(NONSENSE_DATA_32B, buf_shared)
321         .expect("could not derive key");
322 
323     assert_ne!(buf1, buf_shared);
324     assert_ne!(buf2, buf_shared);
325     assert_ne!(buf_shared, NONSENSE_DATA_32B);
326     assert!(keys_are_sufficiently_distinct(buf1, buf_shared));
327     assert!(keys_are_sufficiently_distinct(buf2, buf_shared));
328 
329     // derive shared key with 0 running version
330     let buf_shared2 = &mut [0u8; KEY_SIZE as usize];
331     let _ = hwkey_session
332         .derive_key_req()
333         .kdf(kdf_version)
334         .rollback_version_source(RollbackVersionSource::RunningVersion)
335         .os_rollback_version(OsRollbackVersion::Version(0))
336         .shared_key()
337         .derive(NONSENSE_DATA_32B, buf_shared2)
338         .expect("could not derive key");
339 
340     assert_ne!(buf1, buf_shared2);
341     assert_ne!(buf2, buf_shared2);
342     assert_ne!(buf_shared, buf_shared2);
343     assert_ne!(buf_shared2, NONSENSE_DATA_32B);
344     assert!(keys_are_sufficiently_distinct(buf1, buf_shared2));
345     assert!(keys_are_sufficiently_distinct(buf2, buf_shared2));
346     assert!(keys_are_sufficiently_distinct(buf_shared, buf_shared2));
347 }
348 
349 #[test]
test_hwkey_derive_null_context()350 fn test_hwkey_derive_null_context() {
351     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
352 
353     let buf1 = &mut [0u8; KEY_SIZE as usize];
354     let _ = hwkey_session
355         .derive_key_req()
356         .derive(&[], buf1)
357         .expect_err("able to derive with empty context");
358 }
359 
360 #[test]
test_hwkey_derive_newer_versions()361 fn test_hwkey_derive_newer_versions() {
362     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
363     let buf1 = &mut [0u8; KEY_SIZE as usize];
364 
365     let os_rollback_version = hwkey_session
366         .query_current_os_version(RollbackVersionSource::RunningVersion)
367         .expect("could not query version");
368 
369     match os_rollback_version {
370         OsRollbackVersion::Version(n) => {
371             // request a newer version
372             let _ = hwkey_session
373                 .derive_key_req()
374                 .kdf(KdfVersion::Best)
375                 .rollback_version_source(RollbackVersionSource::RunningVersion)
376                 .os_rollback_version(OsRollbackVersion::Version(n + 1))
377                 .derive(NONSENSE_DATA_32B, buf1)
378                 .expect_err("versioned derive with too new running version");
379         }
380         _ => {
381             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
382         }
383     }
384 
385     // query committed version
386     let os_rollback_version = hwkey_session
387         .query_current_os_version(RollbackVersionSource::CommittedVersion)
388         .expect("could not query version");
389 
390     match os_rollback_version {
391         OsRollbackVersion::Version(n) => {
392             // request a newer version
393             let _ = hwkey_session
394                 .derive_key_req()
395                 .kdf(KdfVersion::Best)
396                 .rollback_version_source(RollbackVersionSource::CommittedVersion)
397                 .os_rollback_version(OsRollbackVersion::Version(n + 1))
398                 .derive(NONSENSE_DATA_32B, buf1)
399                 .expect_err("versioned derive with too new running version");
400 
401             // try a very large version
402             let _ = hwkey_session
403                 .derive_key_req()
404                 .kdf(KdfVersion::Best)
405                 .rollback_version_source(RollbackVersionSource::CommittedVersion)
406                 .os_rollback_version(OsRollbackVersion::Version(u32::MAX))
407                 .derive(NONSENSE_DATA_32B, buf1)
408                 .expect_err("versioned derive with far too large version");
409         }
410         _ => {
411             assert_ne!(os_rollback_version, OsRollbackVersion::Current);
412         }
413     }
414 }
415 
416 #[test]
test_hwkey_derive_large_payload()417 fn test_hwkey_derive_large_payload() {
418     const HEADER_SIZE: usize = mem::size_of::<hwkey_derive_versioned_msg>();
419     const MAX_PAYLOAD_LEN: usize = HWKEY_MAX_MSG_SIZE as usize - HEADER_SIZE;
420 
421     // A payload length that should be supported everywhere, copied from the C
422     // tests. If you increase this, make sure that all hwkey implementations
423     // support a larger payload.
424     const PAYLOAD_LEN: usize = 128;
425 
426     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
427     let ctx = &[0u8; MAX_PAYLOAD_LEN + 1 as usize];
428     let buf1 = &mut [0u8; MAX_PAYLOAD_LEN + 1 as usize];
429 
430     let _ = hwkey_session
431         .derive_key_req()
432         .kdf(KdfVersion::Best)
433         .rollback_version_source(RollbackVersionSource::RunningVersion)
434         .os_rollback_version(OsRollbackVersion::Current)
435         .derive(&ctx[..PAYLOAD_LEN], &mut buf1[..PAYLOAD_LEN])
436         .expect("versioned derive with large context and key");
437 
438     let err = hwkey_session
439         .derive_key_req()
440         .kdf(KdfVersion::Best)
441         .rollback_version_source(RollbackVersionSource::RunningVersion)
442         .os_rollback_version(OsRollbackVersion::Current)
443         .derive(ctx, &mut buf1[..MAX_PAYLOAD_LEN as usize - 1])
444         .expect_err("versioned derive with too large context");
445 
446     assert_eq!(err, HwkeyError::BadLen);
447 
448     let err = hwkey_session
449         .derive_key_req()
450         .kdf(KdfVersion::Best)
451         .rollback_version_source(RollbackVersionSource::RunningVersion)
452         .os_rollback_version(OsRollbackVersion::Current)
453         .derive(&ctx[..MAX_PAYLOAD_LEN as usize - 1], buf1)
454         .expect_err("versioned derive with too large key");
455 
456     assert_eq!(err, HwkeyError::BadLen);
457 }
458 
459 #[test]
test_query_current_os_version()460 fn test_query_current_os_version() {
461     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
462 
463     let os_rollback_version = hwkey_session
464         .query_current_os_version(RollbackVersionSource::RunningVersion)
465         .expect("could not query version");
466     assert_ne!(os_rollback_version, OsRollbackVersion::Current);
467 
468     let os_rollback_version = hwkey_session
469         .query_current_os_version(RollbackVersionSource::CommittedVersion)
470         .expect("could not query version");
471     assert_ne!(os_rollback_version, OsRollbackVersion::Current);
472 }
473 
474 #[test]
test_get_keyslot_storage_auth()475 fn test_get_keyslot_storage_auth() {
476     let keyslot = CStr::from_bytes_with_nul(RPMB_STORAGE_AUTH_KEY_ID).unwrap();
477     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
478     let buf = &mut [0u8; KEY_SIZE as usize];
479     let err = hwkey_session
480         .get_keyslot_data(keyslot, buf)
481         .expect_err("auth key accessible when it shouldn't be");
482     assert_eq!(err, HwkeyError::NotFound);
483 }
484 
485 #[test]
test_get_keybox()486 fn test_get_keybox() {
487     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_KEYBOX_ID).unwrap();
488     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
489     let buf = &mut [0u8; KEY_SIZE as usize];
490     let keyslot_res = hwkey_session.get_keyslot_data(keyslot, buf);
491     if cfg!(feature = "hwcrypto-unittest") {
492         assert_eq!(UNITTEST_KEYSLOT, keyslot_res.expect("could not get keyslot data"))
493     } else {
494         assert!(keyslot_res.is_err());
495     }
496 }
497 
498 #[test]
test_get_derived_keybox()499 fn test_get_derived_keybox() {
500     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_DERIVED_KEYBOX_ID).unwrap();
501     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
502     let buf = &mut [0u8; KEY_SIZE as usize];
503     let keyslot_res = hwkey_session.get_keyslot_data(keyslot, buf);
504     if cfg!(feature = "hwcrypto-unittest") {
505         assert_eq!(UNITTEST_DERIVED_KEYSLOT, keyslot_res.expect("could not get keyslot data"))
506     } else {
507         assert!(keyslot_res.is_err());
508     }
509 }
510 
511 #[test]
test_get_opaque_handle()512 fn test_get_opaque_handle() {
513     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID).unwrap();
514     const HWKEY_OPAQUE_HANDLE_MAX_SIZE: usize = 128;
515     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
516     let buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
517     let keyslot_res = hwkey_session.get_keyslot_data(keyslot, buf);
518     if cfg!(feature = "hwcrypto-unittest") {
519         assert!(
520             keyslot_res.expect("could not retrieve keyslot data").len()
521                 <= HWKEY_OPAQUE_HANDLE_MAX_SIZE
522         )
523     } else {
524         assert!(keyslot_res.is_err());
525     }
526 }
527 
528 #[test]
529 #[cfg(feature = "hwcrypto-unittest")]
test_get_opaque_key()530 fn test_get_opaque_key() {
531     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID).unwrap();
532     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
533     let buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
534     let opaque_handle =
535         hwkey_session.get_keyslot_data(keyslot, buf).expect("could not retrieve keyslot data");
536     assert!(opaque_handle.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
537 
538     let key_buf = &mut [0u8; KEY_SIZE as usize];
539     let keyslot_data = hwkey_session
540         .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
541         .expect("could not retrieve keyslot data");
542     assert_eq!(UNITTEST_KEYSLOT, keyslot_data)
543 }
544 
545 #[test]
546 #[cfg(feature = "hwcrypto-unittest")]
test_get_multiple_opaque_keys()547 fn test_get_multiple_opaque_keys() {
548     let handle_buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
549     let handle: &[u8];
550     let no_access_handle_buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
551     let no_access_handle: &[u8];
552     {
553         // close hwkey session when scope ends
554         let hwkey_session = Hwkey::open().expect("could not open hwkey session");
555 
556         // get handle of opaque key
557         let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID).unwrap();
558         handle = hwkey_session
559             .get_keyslot_data(keyslot, handle_buf)
560             .expect("could not retrieve keyslot data");
561         assert!(handle.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
562 
563         // get handle of opaque key that there is no access to
564         let keyslot =
565             CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_NOACCESS_ID).unwrap();
566         no_access_handle = hwkey_session
567             .get_keyslot_data(keyslot, no_access_handle_buf)
568             .expect("could not retrieve keyslot data");
569         assert!(no_access_handle.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
570 
571         // the handles should be different
572         assert_ne!(handle, no_access_handle);
573 
574         // test the key belonging to the key slot
575         let key_buf = &mut [0u8; KEY_SIZE as usize];
576         let handle_keyslot_data = hwkey_session
577             .get_keyslot_data(CStr::from_bytes_with_nul(handle).unwrap(), key_buf)
578             .expect("could not retrieve keyslot data");
579         assert_eq!(UNITTEST_KEYSLOT, handle_keyslot_data);
580 
581         // test no access
582         let key_buf = &mut [0u8; KEY_SIZE as usize];
583         let err = hwkey_session
584             .get_keyslot_data(CStr::from_bytes_with_nul(no_access_handle).unwrap(), key_buf)
585             .expect_err("key accessible when it shouldn't be");
586         assert_eq!(err, HwkeyError::NotFound);
587     }
588 
589     // session has closed following end of scope above, open a new session
590     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
591 
592     // ensure that the tokens have been dropped and cleared
593     let key_buf = &mut [0u8; KEY_SIZE as usize];
594     let err = hwkey_session
595         .get_keyslot_data(CStr::from_bytes_with_nul(handle).unwrap(), key_buf)
596         .expect_err("key accessible when it shouldn't be");
597     assert_eq!(err, HwkeyError::NotFound);
598 
599     let key_buf = &mut [0u8; KEY_SIZE as usize];
600     let err = hwkey_session
601         .get_keyslot_data(CStr::from_bytes_with_nul(no_access_handle).unwrap(), key_buf)
602         .expect_err("key accessible when it shouldn't be");
603     assert_eq!(err, HwkeyError::NotFound);
604 }
605 
606 #[test]
607 #[cfg(feature = "hwcrypto-unittest")]
test_get_opaque_handle_multiple_sessions()608 fn test_get_opaque_handle_multiple_sessions() {
609     const HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID2: &'static [u8] =
610         b"com.android.trusty.hwcrypto.unittest.opaque_handle2\0";
611     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID).unwrap();
612     let key_buf = &mut [0u8; KEY_SIZE as usize];
613     let buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
614     let buf2 = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
615     let opaque_handle;
616     let opaque_handle2;
617 
618     {
619         // scope of first hwkey session
620         let hwkey_session = Hwkey::open().expect("could not open hwkey session");
621         opaque_handle = hwkey_session
622             .get_keyslot_data(keyslot, buf)
623             .expect("get hwcrypto-unittest opaque keybox");
624         assert!(opaque_handle.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
625 
626         {
627             // scope of second hwkey session
628             let hwkey_session2 = Hwkey::open().expect("could not open hwkey session");
629             let _ = hwkey_session2
630                 .get_keyslot_data(keyslot, buf2)
631                 .expect_err("retrieve same handle twice");
632 
633             let keyslot2 = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_HANDLE_ID2).unwrap();
634             opaque_handle2 = hwkey_session2
635                 .get_keyslot_data(keyslot2, buf2)
636                 .expect("get hwcrypto-unittest opaque keybox");
637             assert!(opaque_handle2.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
638 
639             // fetch the keys via the first session
640             let keyslot_data = hwkey_session
641                 .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
642                 .expect("could not retrieve keyslot data");
643             assert_eq!(UNITTEST_KEYSLOT, keyslot_data);
644 
645             key_buf.fill(0);
646             let keyslot_data = hwkey_session
647                 .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle2).unwrap(), key_buf)
648                 .expect("could not retrieve keyslot data");
649             assert_eq!(UNITTEST_KEYSLOT, keyslot_data);
650 
651             // fetch the same key via the second session
652             key_buf.fill(0);
653             let keyslot_data = hwkey_session2
654                 .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
655                 .expect("could not retrieve keyslot data");
656             assert_eq!(UNITTEST_KEYSLOT, keyslot_data);
657 
658             key_buf.fill(0);
659             let keyslot_data = hwkey_session2
660                 .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle2).unwrap(), key_buf)
661                 .expect("could not retrieve keyslot data");
662             assert_eq!(UNITTEST_KEYSLOT, keyslot_data);
663         } // end of second hwkey session scope
664 
665         // second session is now closed, make sure the first session
666         // handle is still valid while the second is invalid
667 
668         let _ = hwkey_session
669             .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
670             .expect("first session handle wasn't valid");
671 
672         let _ = hwkey_session
673             .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle2).unwrap(), key_buf)
674             .expect_err("second session handle was still valid");
675     } // end of first hwkey session scope
676 
677     // disconnect the original session which retrieved the handle, open a new one
678     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
679 
680     let _ = hwkey_session
681         .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
682         .expect_err("first session handle was still valid");
683 
684     let _ = hwkey_session
685         .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle2).unwrap(), key_buf)
686         .expect_err("second session handle was still valid");
687 }
688 
689 #[test]
690 #[cfg(feature = "hwcrypto-unittest")]
test_try_empty_opaque_handle()691 fn test_try_empty_opaque_handle() {
692     let keyslot = CStr::from_bytes_with_nul(b"\0").unwrap();
693     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
694     let buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
695     let _ = hwkey_session
696         .get_keyslot_data(keyslot, buf)
697         .expect_err("retrieving a key with an empty access token succeeded");
698 }
699 
700 #[test]
701 #[cfg(feature = "hwcrypto-unittest")]
test_get_opaque_derived_key()702 fn test_get_opaque_derived_key() {
703     const HWCRYPTO_UNITTEST_OPAQUE_DERIVED_ID: &'static [u8] =
704         b"com.android.trusty.hwcrypto.unittest.opaque_derived\0";
705     let keyslot = CStr::from_bytes_with_nul(HWCRYPTO_UNITTEST_OPAQUE_DERIVED_ID).unwrap();
706     let hwkey_session = Hwkey::open().expect("could not open hwkey session");
707     let buf = &mut [0u8; HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize];
708     let opaque_handle =
709         hwkey_session.get_keyslot_data(keyslot, buf).expect("could not retrieve keyslot data");
710     assert!(opaque_handle.len() <= HWKEY_OPAQUE_HANDLE_MAX_SIZE as usize);
711 
712     let key_buf = &mut [0u8; KEY_SIZE as usize];
713     let keyslot_data = hwkey_session
714         .get_keyslot_data(CStr::from_bytes_with_nul(opaque_handle).unwrap(), key_buf)
715         .expect("could not retrieve keyslot data");
716     assert_eq!(UNITTEST_DERIVED_KEYSLOT, keyslot_data)
717 }
718