• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Export into Rust a function to create a KeyMintDevice and add it as a service.
16 
17 #[allow(missing_docs)] // TODO remove this
18 extern "C" {
addKeyMintDeviceService() -> i3219     fn addKeyMintDeviceService() -> i32;
20 }
21 
22 #[allow(missing_docs)] // TODO remove this
add_keymint_device_service() -> i3223 pub fn add_keymint_device_service() -> i32 {
24     unsafe { addKeyMintDeviceService() }
25 }
26 
27 #[cfg(test)]
28 mod tests {
29 
30     use super::*;
31     use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
32         Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
33         ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice, KeyCreationResult::KeyCreationResult,
34         KeyFormat::KeyFormat, KeyOrigin::KeyOrigin, KeyParameter::KeyParameter,
35         KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
36         SecurityLevel::SecurityLevel, Tag::Tag,
37     };
38     use android_hardware_security_keymint::binder::{self, Strong};
39     use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
40 
41     static COMPAT_NAME: &str = "android.security.compat";
42 
get_device() -> Option<Strong<dyn IKeyMintDevice>>43     fn get_device() -> Option<Strong<dyn IKeyMintDevice>> {
44         add_keymint_device_service();
45         let compat_service: Strong<dyn IKeystoreCompatService> =
46             binder::get_interface(COMPAT_NAME).ok()?;
47         compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).ok()
48     }
49 
50     macro_rules! get_device_or_skip_test {
51         () => {
52             match get_device() {
53                 Some(dev) => dev,
54                 None => return,
55             }
56         };
57     }
58 
59     #[test]
test_get_hardware_info()60     fn test_get_hardware_info() {
61         let legacy = get_device_or_skip_test!();
62         let hinfo = legacy.getHardwareInfo();
63         assert!(hinfo.is_ok());
64     }
65 
66     #[test]
test_add_rng_entropy()67     fn test_add_rng_entropy() {
68         let legacy = get_device_or_skip_test!();
69         let result = legacy.addRngEntropy(&[42; 16]);
70         assert!(result.is_ok(), "{:?}", result);
71     }
72 
73     // TODO: If I only need the key itself, don't return the other things.
generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult74     fn generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult {
75         let creation_result =
76             legacy.generateKey(&kps, None /* attest_key */).expect("Failed to generate key");
77         assert_ne!(creation_result.keyBlob.len(), 0);
78         creation_result
79     }
80 
81     // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
82     // 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
83     const UNDEFINED_NOT_AFTER: i64 = 253402300799000i64;
84 
generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8>85     fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
86         let mut kps = vec![
87             KeyParameter {
88                 tag: Tag::ALGORITHM,
89                 value: KeyParameterValue::Algorithm(Algorithm::RSA),
90             },
91             KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) },
92             KeyParameter {
93                 tag: Tag::RSA_PUBLIC_EXPONENT,
94                 value: KeyParameterValue::LongInteger(65537),
95             },
96             KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) },
97             KeyParameter {
98                 tag: Tag::PADDING,
99                 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
100             },
101             KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
102             KeyParameter {
103                 tag: Tag::PURPOSE,
104                 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
105             },
106             KeyParameter {
107                 tag: Tag::CERTIFICATE_NOT_BEFORE,
108                 value: KeyParameterValue::DateTime(0),
109             },
110             KeyParameter {
111                 tag: Tag::CERTIFICATE_NOT_AFTER,
112                 value: KeyParameterValue::DateTime(UNDEFINED_NOT_AFTER),
113             },
114         ];
115         if encrypt {
116             kps.push(KeyParameter {
117                 tag: Tag::PURPOSE,
118                 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
119             });
120         }
121         if attest {
122             kps.push(KeyParameter {
123                 tag: Tag::ATTESTATION_CHALLENGE,
124                 value: KeyParameterValue::Blob(vec![42; 8]),
125             });
126             kps.push(KeyParameter {
127                 tag: Tag::ATTESTATION_APPLICATION_ID,
128                 value: KeyParameterValue::Blob(vec![42; 8]),
129             });
130         }
131         let creation_result = generate_key(legacy, kps);
132         if attest {
133             // TODO: Will this always be greater than 1?
134             assert!(creation_result.certificateChain.len() > 1);
135         } else {
136             assert_eq!(creation_result.certificateChain.len(), 1);
137         }
138         creation_result.keyBlob
139     }
140 
141     #[test]
test_generate_key_no_encrypt()142     fn test_generate_key_no_encrypt() {
143         let legacy = get_device_or_skip_test!();
144         generate_rsa_key(legacy.as_ref(), false, false);
145     }
146 
147     #[test]
test_generate_key_encrypt()148     fn test_generate_key_encrypt() {
149         let legacy = get_device_or_skip_test!();
150         generate_rsa_key(legacy.as_ref(), true, false);
151     }
152 
153     #[test]
test_generate_key_attested()154     fn test_generate_key_attested() {
155         let legacy = get_device_or_skip_test!();
156         generate_rsa_key(legacy.as_ref(), false, true);
157     }
158 
159     #[test]
test_import_key()160     fn test_import_key() {
161         let legacy = get_device_or_skip_test!();
162         let kps = [KeyParameter {
163             tag: Tag::ALGORITHM,
164             value: KeyParameterValue::Algorithm(Algorithm::AES),
165         }];
166         let kf = KeyFormat::RAW;
167         let kd = [0; 16];
168         let creation_result =
169             legacy.importKey(&kps, kf, &kd, None /* attest_key */).expect("Failed to import key");
170         assert_ne!(creation_result.keyBlob.len(), 0);
171         assert_eq!(creation_result.certificateChain.len(), 0);
172     }
173 
174     #[test]
test_import_wrapped_key()175     fn test_import_wrapped_key() {
176         let legacy = get_device_or_skip_test!();
177         let result = legacy.importWrappedKey(&[], &[], &[], &[], 0, 0);
178         // For this test we only care that there was no crash.
179         assert!(result.is_ok() || result.is_err());
180     }
181 
182     #[test]
test_upgrade_key()183     fn test_upgrade_key() {
184         let legacy = get_device_or_skip_test!();
185         let blob = generate_rsa_key(legacy.as_ref(), false, false);
186         let result = legacy.upgradeKey(&blob, &[]);
187         // For this test we only care that there was no crash.
188         assert!(result.is_ok() || result.is_err());
189     }
190 
191     #[test]
test_delete_key()192     fn test_delete_key() {
193         let legacy = get_device_or_skip_test!();
194         let blob = generate_rsa_key(legacy.as_ref(), false, false);
195         let result = legacy.deleteKey(&blob);
196         assert!(result.is_ok(), "{:?}", result);
197     }
198 
199     #[test]
test_delete_all_keys()200     fn test_delete_all_keys() {
201         let legacy = get_device_or_skip_test!();
202         let result = legacy.deleteAllKeys();
203         assert!(result.is_ok(), "{:?}", result);
204     }
205 
206     #[test]
test_destroy_attestation_ids()207     fn test_destroy_attestation_ids() {
208         let legacy = get_device_or_skip_test!();
209         let result = legacy.destroyAttestationIds();
210         assert!(result.is_err());
211         assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
212     }
213 
generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8>214     fn generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8> {
215         let kps = vec![
216             KeyParameter {
217                 tag: Tag::ALGORITHM,
218                 value: KeyParameterValue::Algorithm(Algorithm::AES),
219             },
220             KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
221             KeyParameter {
222                 tag: Tag::BLOCK_MODE,
223                 value: KeyParameterValue::BlockMode(BlockMode::CBC),
224             },
225             KeyParameter {
226                 tag: Tag::PADDING,
227                 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
228             },
229             KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
230             KeyParameter {
231                 tag: Tag::PURPOSE,
232                 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
233             },
234             KeyParameter {
235                 tag: Tag::PURPOSE,
236                 value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
237             },
238         ];
239         let creation_result = generate_key(legacy, kps);
240         assert_eq!(creation_result.certificateChain.len(), 0);
241         creation_result.keyBlob
242     }
243 
begin( legacy: &dyn IKeyMintDevice, blob: &[u8], purpose: KeyPurpose, extra_params: Option<Vec<KeyParameter>>, ) -> BeginResult244     fn begin(
245         legacy: &dyn IKeyMintDevice,
246         blob: &[u8],
247         purpose: KeyPurpose,
248         extra_params: Option<Vec<KeyParameter>>,
249     ) -> BeginResult {
250         let mut kps = vec![
251             KeyParameter {
252                 tag: Tag::BLOCK_MODE,
253                 value: KeyParameterValue::BlockMode(BlockMode::CBC),
254             },
255             KeyParameter {
256                 tag: Tag::PADDING,
257                 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
258             },
259         ];
260         if let Some(mut extras) = extra_params {
261             kps.append(&mut extras);
262         }
263         let result = legacy.begin(purpose, &blob, &kps, None);
264         assert!(result.is_ok(), "{:?}", result);
265         result.unwrap()
266     }
267 
268     #[test]
test_begin_abort()269     fn test_begin_abort() {
270         let legacy = get_device_or_skip_test!();
271         let blob = generate_aes_key(legacy.as_ref());
272         let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
273         let operation = begin_result.operation.unwrap();
274         let result = operation.abort();
275         assert!(result.is_ok(), "{:?}", result);
276         let result = operation.abort();
277         assert!(result.is_err());
278     }
279 
280     #[test]
test_begin_update_finish()281     fn test_begin_update_finish() {
282         let legacy = get_device_or_skip_test!();
283         let blob = generate_aes_key(legacy.as_ref());
284 
285         let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
286         let operation = begin_result.operation.unwrap();
287 
288         let update_aad_result = operation.updateAad(
289             &b"foobar".to_vec(),
290             None, /* authToken */
291             None, /* timestampToken */
292         );
293         assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
294 
295         let message = [42; 128];
296         let result = operation.finish(
297             Some(&message),
298             None, /* signature */
299             None, /* authToken */
300             None, /* timestampToken */
301             None, /* confirmationToken */
302         );
303         assert!(result.is_ok(), "{:?}", result);
304         let ciphertext = result.unwrap();
305         assert!(!ciphertext.is_empty());
306 
307         let begin_result =
308             begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
309 
310         let operation = begin_result.operation.unwrap();
311 
312         let update_aad_result = operation.updateAad(
313             &b"foobar".to_vec(),
314             None, /* authToken */
315             None, /* timestampToken */
316         );
317         assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
318 
319         let result = operation.update(
320             &ciphertext,
321             None, /* authToken */
322             None, /* timestampToken */
323         );
324         assert!(result.is_ok(), "{:?}", result);
325         assert_eq!(result.unwrap(), message);
326         let result = operation.finish(
327             None, /* input */
328             None, /* signature */
329             None, /* authToken */
330             None, /* timestampToken */
331             None, /* confirmationToken */
332         );
333         assert!(result.is_ok(), "{:?}", result);
334     }
335 
336     #[test]
test_secure_clock()337     fn test_secure_clock() {
338         add_keymint_device_service();
339         let compat_service: binder::Strong<dyn IKeystoreCompatService> =
340             match binder::get_interface(COMPAT_NAME) {
341                 Ok(cs) => cs,
342                 _ => return,
343             };
344         let secure_clock = match compat_service.getSecureClock() {
345             Ok(sc) => sc,
346             _ => return,
347         };
348 
349         let challenge = 42;
350         let result = secure_clock.generateTimeStamp(challenge);
351         assert!(result.is_ok(), "{:?}", result);
352         let result = result.unwrap();
353         assert_eq!(result.challenge, challenge);
354         assert_eq!(result.mac.len(), 32);
355     }
356 
357     #[test]
test_shared_secret()358     fn test_shared_secret() {
359         add_keymint_device_service();
360         let compat_service: binder::Strong<dyn IKeystoreCompatService> =
361             match binder::get_interface(COMPAT_NAME) {
362                 Ok(cs) => cs,
363                 _ => return,
364             };
365         let shared_secret = match compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT)
366         {
367             Ok(ss) => ss,
368             _ => return,
369         };
370 
371         let result = shared_secret.getSharedSecretParameters();
372         assert!(result.is_ok(), "{:?}", result);
373         let params = result.unwrap();
374 
375         let result = shared_secret.computeSharedSecret(&[params]);
376         assert!(result.is_ok(), "{:?}", result);
377         assert_ne!(result.unwrap().len(), 0);
378     }
379 
380     #[test]
test_get_key_characteristics()381     fn test_get_key_characteristics() {
382         let legacy = get_device_or_skip_test!();
383         let hw_info = legacy.getHardwareInfo().expect("GetHardwareInfo");
384 
385         let blob = generate_rsa_key(legacy.as_ref(), false, false);
386         let characteristics =
387             legacy.getKeyCharacteristics(&blob, &[], &[]).expect("GetKeyCharacteristics.");
388 
389         assert!(characteristics.iter().any(|kc| kc.securityLevel == hw_info.securityLevel));
390         let sec_level_enforced = &characteristics
391             .iter()
392             .find(|kc| kc.securityLevel == hw_info.securityLevel)
393             .expect("There should be characteristics matching the device's security level.")
394             .authorizations;
395 
396         assert!(sec_level_enforced.iter().any(|kp| matches!(
397             kp,
398             KeyParameter {
399                 tag: Tag::PURPOSE,
400                 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN)
401             }
402         )));
403         assert!(sec_level_enforced.iter().any(|kp| matches!(
404             kp,
405             KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) }
406         )));
407         assert!(sec_level_enforced.iter().any(|kp| matches!(
408             kp,
409             KeyParameter {
410                 tag: Tag::PADDING,
411                 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS)
412             }
413         )));
414         assert!(sec_level_enforced.iter().any(|kp| matches!(
415             kp,
416             KeyParameter {
417                 tag: Tag::ALGORITHM,
418                 value: KeyParameterValue::Algorithm(Algorithm::RSA)
419             }
420         )));
421         assert!(sec_level_enforced.iter().any(|kp| matches!(
422             kp,
423             KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) }
424         )));
425         assert!(sec_level_enforced.iter().any(|kp| matches!(
426             kp,
427             KeyParameter {
428                 tag: Tag::RSA_PUBLIC_EXPONENT,
429                 value: KeyParameterValue::LongInteger(65537)
430             }
431         )));
432         assert!(sec_level_enforced.iter().any(|kp| matches!(
433             kp,
434             KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) }
435         )));
436         assert!(sec_level_enforced.iter().any(|kp| matches!(
437             kp,
438             KeyParameter {
439                 tag: Tag::ORIGIN,
440                 value: KeyParameterValue::Origin(KeyOrigin::GENERATED)
441             }
442         )));
443         assert!(sec_level_enforced.iter().any(|kp| matches!(
444             kp,
445             KeyParameter { tag: Tag::OS_VERSION, value: KeyParameterValue::Integer(_) }
446         )));
447         assert!(sec_level_enforced.iter().any(|kp| matches!(
448             kp,
449             KeyParameter { tag: Tag::OS_PATCHLEVEL, value: KeyParameterValue::Integer(_) }
450         )));
451         assert!(sec_level_enforced.iter().any(|kp| matches!(
452             kp,
453             KeyParameter { tag: Tag::VENDOR_PATCHLEVEL, value: KeyParameterValue::Integer(_) }
454         )));
455         assert!(sec_level_enforced.iter().any(|kp| matches!(
456             kp,
457             KeyParameter { tag: Tag::BOOT_PATCHLEVEL, value: KeyParameterValue::Integer(_) }
458         )));
459     }
460 }
461