blob: eddd6842e57854a67b0b328ef598fc6e6eacc63c [file] [log] [blame]
Joel Galensonde386b42020-09-30 10:53:05 -07001// 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
Paul Crowleyd5653e52021-03-25 09:46:31 -070015//! Export into Rust a function to create a KeyMintDevice and add it as a service.
Joel Galensonde386b42020-09-30 10:53:05 -070016
Paul Crowleyd5653e52021-03-25 09:46:31 -070017#[allow(missing_docs)] // TODO remove this
Joel Galensonde386b42020-09-30 10:53:05 -070018extern "C" {
19 fn addKeyMintDeviceService() -> i32;
20}
21
Paul Crowleyd5653e52021-03-25 09:46:31 -070022#[allow(missing_docs)] // TODO remove this
Joel Galensonde386b42020-09-30 10:53:05 -070023pub fn add_keymint_device_service() -> i32 {
24 unsafe { addKeyMintDeviceService() }
25}
26
27#[cfg(test)]
28mod tests {
29
30 use super::*;
31 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Shawn Willdendbdac602021-01-12 22:35:16 -070032 Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
David Drysdalef5c1ab02021-04-19 19:08:14 +010033 ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice, KeyCreationResult::KeyCreationResult,
34 KeyFormat::KeyFormat, KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue,
35 KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Joel Galensonde386b42020-09-30 10:53:05 -070036 };
Stephen Crane221bbb52020-12-16 15:52:10 -080037 use android_hardware_security_keymint::binder::{self, Strong};
Joel Galensonde386b42020-09-30 10:53:05 -070038 use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
39
Joel Galensonf21c0022020-12-11 14:37:52 -080040 static COMPAT_NAME: &str = "android.security.compat";
41
Stephen Crane221bbb52020-12-16 15:52:10 -080042 fn get_device() -> Option<Strong<dyn IKeyMintDevice>> {
Joel Galensonde386b42020-09-30 10:53:05 -070043 add_keymint_device_service();
Stephen Crane221bbb52020-12-16 15:52:10 -080044 let compat_service: Strong<dyn IKeystoreCompatService> =
Janis Danisevskis12913842021-02-01 13:49:25 -080045 binder::get_interface(COMPAT_NAME).ok()?;
46 compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).ok()
47 }
48
49 macro_rules! get_device_or_skip_test {
50 () => {
51 match get_device() {
52 Some(dev) => dev,
53 None => return,
54 }
55 };
Joel Galensonde386b42020-09-30 10:53:05 -070056 }
57
58 #[test]
59 fn test_get_hardware_info() {
Janis Danisevskis12913842021-02-01 13:49:25 -080060 let legacy = get_device_or_skip_test!();
Joel Galensond4dbfd52021-01-25 09:45:33 -080061 let hinfo = legacy.getHardwareInfo();
62 assert!(hinfo.is_ok());
Joel Galensonde386b42020-09-30 10:53:05 -070063 }
64
65 #[test]
Joel Galensonde386b42020-09-30 10:53:05 -070066 fn test_add_rng_entropy() {
Janis Danisevskis12913842021-02-01 13:49:25 -080067 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -070068 let result = legacy.addRngEntropy(&[42; 16]);
69 assert!(result.is_ok(), "{:?}", result);
70 }
71
72 // TODO: If I only need the key itself, don't return the other things.
Shawn Willdendbdac602021-01-12 22:35:16 -070073 fn generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult {
Shawn Willdenc2f3acf2021-02-03 07:07:17 -070074 let creation_result =
75 legacy.generateKey(&kps, None /* attest_key */).expect("Failed to generate key");
Shawn Willdendbdac602021-01-12 22:35:16 -070076 assert_ne!(creation_result.keyBlob.len(), 0);
77 creation_result
Joel Galensonde386b42020-09-30 10:53:05 -070078 }
79
Janis Danisevskis2c084012021-01-31 22:23:17 -080080 // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
81 // 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
82 const UNDEFINED_NOT_AFTER: i64 = 253402300799000i64;
83
Joel Galensonde386b42020-09-30 10:53:05 -070084 fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
85 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -080086 KeyParameter {
87 tag: Tag::ALGORITHM,
88 value: KeyParameterValue::Algorithm(Algorithm::RSA),
89 },
90 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) },
Joel Galensonde386b42020-09-30 10:53:05 -070091 KeyParameter {
92 tag: Tag::RSA_PUBLIC_EXPONENT,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080093 value: KeyParameterValue::LongInteger(65537),
Joel Galensonde386b42020-09-30 10:53:05 -070094 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -080095 KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) },
Joel Galensonde386b42020-09-30 10:53:05 -070096 KeyParameter {
97 tag: Tag::PADDING,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080098 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
Joel Galensonde386b42020-09-30 10:53:05 -070099 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800100 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
101 KeyParameter {
102 tag: Tag::PURPOSE,
103 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
104 },
Janis Danisevskis2c084012021-01-31 22:23:17 -0800105 KeyParameter {
106 tag: Tag::CERTIFICATE_NOT_BEFORE,
107 value: KeyParameterValue::DateTime(0),
108 },
109 KeyParameter {
110 tag: Tag::CERTIFICATE_NOT_AFTER,
111 value: KeyParameterValue::DateTime(UNDEFINED_NOT_AFTER),
112 },
Joel Galensonde386b42020-09-30 10:53:05 -0700113 ];
114 if encrypt {
115 kps.push(KeyParameter {
116 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800117 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700118 });
119 }
120 if attest {
121 kps.push(KeyParameter {
122 tag: Tag::ATTESTATION_CHALLENGE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800123 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700124 });
125 kps.push(KeyParameter {
126 tag: Tag::ATTESTATION_APPLICATION_ID,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800127 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700128 });
129 }
Shawn Willdendbdac602021-01-12 22:35:16 -0700130 let creation_result = generate_key(legacy, kps);
Joel Galensonde386b42020-09-30 10:53:05 -0700131 if attest {
132 // TODO: Will this always be greater than 1?
Shawn Willdendbdac602021-01-12 22:35:16 -0700133 assert!(creation_result.certificateChain.len() > 1);
Joel Galensonde386b42020-09-30 10:53:05 -0700134 } else {
Shawn Willdendbdac602021-01-12 22:35:16 -0700135 assert_eq!(creation_result.certificateChain.len(), 1);
Joel Galensonde386b42020-09-30 10:53:05 -0700136 }
Shawn Willdendbdac602021-01-12 22:35:16 -0700137 creation_result.keyBlob
Joel Galensonde386b42020-09-30 10:53:05 -0700138 }
139
140 #[test]
141 fn test_generate_key_no_encrypt() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800142 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700143 generate_rsa_key(legacy.as_ref(), false, false);
144 }
145
146 #[test]
147 fn test_generate_key_encrypt() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800148 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700149 generate_rsa_key(legacy.as_ref(), true, false);
150 }
151
152 #[test]
153 fn test_generate_key_attested() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800154 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700155 generate_rsa_key(legacy.as_ref(), false, true);
156 }
157
158 #[test]
159 fn test_import_key() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800160 let legacy = get_device_or_skip_test!();
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800161 let kps = [KeyParameter {
162 tag: Tag::ALGORITHM,
163 value: KeyParameterValue::Algorithm(Algorithm::AES),
164 }];
Joel Galensonde386b42020-09-30 10:53:05 -0700165 let kf = KeyFormat::RAW;
166 let kd = [0; 16];
Shawn Willdenc2f3acf2021-02-03 07:07:17 -0700167 let creation_result =
168 legacy.importKey(&kps, kf, &kd, None /* attest_key */).expect("Failed to import key");
Shawn Willdendbdac602021-01-12 22:35:16 -0700169 assert_ne!(creation_result.keyBlob.len(), 0);
170 assert_eq!(creation_result.certificateChain.len(), 0);
Joel Galensonde386b42020-09-30 10:53:05 -0700171 }
172
173 #[test]
174 fn test_import_wrapped_key() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800175 let legacy = get_device_or_skip_test!();
Shawn Willdendbdac602021-01-12 22:35:16 -0700176 let result = legacy.importWrappedKey(&[], &[], &[], &[], 0, 0);
Joel Galensond4dbfd52021-01-25 09:45:33 -0800177 // For this test we only care that there was no crash.
178 assert!(result.is_ok() || result.is_err());
Joel Galensonde386b42020-09-30 10:53:05 -0700179 }
180
181 #[test]
182 fn test_upgrade_key() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800183 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700184 let blob = generate_rsa_key(legacy.as_ref(), false, false);
185 let result = legacy.upgradeKey(&blob, &[]);
Joel Galensond4dbfd52021-01-25 09:45:33 -0800186 // For this test we only care that there was no crash.
187 assert!(result.is_ok() || result.is_err());
Joel Galensonde386b42020-09-30 10:53:05 -0700188 }
189
190 #[test]
191 fn test_delete_key() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800192 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700193 let blob = generate_rsa_key(legacy.as_ref(), false, false);
194 let result = legacy.deleteKey(&blob);
195 assert!(result.is_ok(), "{:?}", result);
196 }
197
198 #[test]
199 fn test_delete_all_keys() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800200 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700201 let result = legacy.deleteAllKeys();
202 assert!(result.is_ok(), "{:?}", result);
203 }
204
205 #[test]
206 fn test_destroy_attestation_ids() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800207 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700208 let result = legacy.destroyAttestationIds();
209 assert!(result.is_err());
210 assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
211 }
212
213 fn generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8> {
214 let kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800215 KeyParameter {
216 tag: Tag::ALGORITHM,
217 value: KeyParameterValue::Algorithm(Algorithm::AES),
218 },
219 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
220 KeyParameter {
221 tag: Tag::BLOCK_MODE,
222 value: KeyParameterValue::BlockMode(BlockMode::CBC),
223 },
224 KeyParameter {
225 tag: Tag::PADDING,
226 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
227 },
228 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
Joel Galensonde386b42020-09-30 10:53:05 -0700229 KeyParameter {
230 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800231 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700232 },
233 KeyParameter {
234 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800235 value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700236 },
237 ];
Shawn Willdendbdac602021-01-12 22:35:16 -0700238 let creation_result = generate_key(legacy, kps);
239 assert_eq!(creation_result.certificateChain.len(), 0);
240 creation_result.keyBlob
Joel Galensonde386b42020-09-30 10:53:05 -0700241 }
242
243 fn begin(
244 legacy: &dyn IKeyMintDevice,
245 blob: &[u8],
246 purpose: KeyPurpose,
247 extra_params: Option<Vec<KeyParameter>>,
248 ) -> BeginResult {
249 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800250 KeyParameter {
251 tag: Tag::BLOCK_MODE,
252 value: KeyParameterValue::BlockMode(BlockMode::CBC),
253 },
254 KeyParameter {
255 tag: Tag::PADDING,
256 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
257 },
Joel Galensonde386b42020-09-30 10:53:05 -0700258 ];
259 if let Some(mut extras) = extra_params {
260 kps.append(&mut extras);
261 }
David Drysdalef5c1ab02021-04-19 19:08:14 +0100262 let result = legacy.begin(purpose, &blob, &kps, None);
Joel Galensonde386b42020-09-30 10:53:05 -0700263 assert!(result.is_ok(), "{:?}", result);
264 result.unwrap()
265 }
266
267 #[test]
268 fn test_begin_abort() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800269 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700270 let blob = generate_aes_key(legacy.as_ref());
271 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
272 let operation = begin_result.operation.unwrap();
273 let result = operation.abort();
274 assert!(result.is_ok(), "{:?}", result);
275 let result = operation.abort();
276 assert!(result.is_err());
277 }
278
279 #[test]
280 fn test_begin_update_finish() {
Janis Danisevskis12913842021-02-01 13:49:25 -0800281 let legacy = get_device_or_skip_test!();
Joel Galensonde386b42020-09-30 10:53:05 -0700282 let blob = generate_aes_key(legacy.as_ref());
283
284 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
285 let operation = begin_result.operation.unwrap();
Shawn Willden44cc03d2021-02-19 10:53:49 -0700286
287 let update_aad_result = operation.updateAad(
288 &b"foobar".to_vec(),
289 None, /* authToken */
290 None, /* timestampToken */
291 );
292 assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
293
Joel Galensonde386b42020-09-30 10:53:05 -0700294 let message = [42; 128];
Shawn Willden44cc03d2021-02-19 10:53:49 -0700295 let result = operation.finish(
296 Some(&message),
297 None, /* signature */
298 None, /* authToken */
299 None, /* timestampToken */
300 None, /* confirmationToken */
301 );
Joel Galensonde386b42020-09-30 10:53:05 -0700302 assert!(result.is_ok(), "{:?}", result);
303 let ciphertext = result.unwrap();
304 assert!(!ciphertext.is_empty());
Joel Galensonde386b42020-09-30 10:53:05 -0700305
306 let begin_result =
307 begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
Shawn Willden44cc03d2021-02-19 10:53:49 -0700308
Joel Galensonde386b42020-09-30 10:53:05 -0700309 let operation = begin_result.operation.unwrap();
Shawn Willden44cc03d2021-02-19 10:53:49 -0700310
311 let update_aad_result = operation.updateAad(
312 &b"foobar".to_vec(),
313 None, /* authToken */
314 None, /* timestampToken */
315 );
316 assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
317
Joel Galensonde386b42020-09-30 10:53:05 -0700318 let result = operation.update(
Shawn Willden44cc03d2021-02-19 10:53:49 -0700319 &ciphertext,
320 None, /* authToken */
321 None, /* timestampToken */
Joel Galensonde386b42020-09-30 10:53:05 -0700322 );
323 assert!(result.is_ok(), "{:?}", result);
Shawn Willden44cc03d2021-02-19 10:53:49 -0700324 assert_eq!(result.unwrap(), message);
325 let result = operation.finish(
326 None, /* input */
327 None, /* signature */
328 None, /* authToken */
329 None, /* timestampToken */
330 None, /* confirmationToken */
331 );
Joel Galensonde386b42020-09-30 10:53:05 -0700332 assert!(result.is_ok(), "{:?}", result);
Joel Galensonde386b42020-09-30 10:53:05 -0700333 }
Joel Galensonf21c0022020-12-11 14:37:52 -0800334
335 #[test]
336 fn test_secure_clock() {
337 add_keymint_device_service();
Stephen Crane221bbb52020-12-16 15:52:10 -0800338 let compat_service: binder::Strong<dyn IKeystoreCompatService> =
Joel Galenson9978cd42021-02-23 09:11:10 -0800339 match binder::get_interface(COMPAT_NAME) {
340 Ok(cs) => cs,
341 _ => return,
342 };
343 let secure_clock = match compat_service.getSecureClock() {
344 Ok(sc) => sc,
345 _ => return,
346 };
Joel Galensonf21c0022020-12-11 14:37:52 -0800347
348 let challenge = 42;
349 let result = secure_clock.generateTimeStamp(challenge);
350 assert!(result.is_ok(), "{:?}", result);
351 let result = result.unwrap();
352 assert_eq!(result.challenge, challenge);
353 assert_eq!(result.mac.len(), 32);
354 }
355
356 #[test]
357 fn test_shared_secret() {
358 add_keymint_device_service();
Stephen Crane221bbb52020-12-16 15:52:10 -0800359 let compat_service: binder::Strong<dyn IKeystoreCompatService> =
Joel Galenson9978cd42021-02-23 09:11:10 -0800360 match binder::get_interface(COMPAT_NAME) {
361 Ok(cs) => cs,
362 _ => return,
363 };
364 let shared_secret = match compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT)
365 {
366 Ok(ss) => ss,
367 _ => return,
368 };
Joel Galensonf21c0022020-12-11 14:37:52 -0800369
370 let result = shared_secret.getSharedSecretParameters();
371 assert!(result.is_ok(), "{:?}", result);
372 let params = result.unwrap();
373
374 let result = shared_secret.computeSharedSecret(&[params]);
375 assert!(result.is_ok(), "{:?}", result);
376 assert_ne!(result.unwrap().len(), 0);
377 }
Joel Galensonde386b42020-09-30 10:53:05 -0700378}