blob: aed0e7ef2840f996dd38c731cc7b93cdaac003b0 [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
15// TODO: Once this is stable, remove this and document everything public.
16#![allow(missing_docs)]
17
18extern "C" {
19 fn addKeyMintDeviceService() -> i32;
20}
21
22pub fn add_keymint_device_service() -> i32 {
23 unsafe { addKeyMintDeviceService() }
24}
25
26#[cfg(test)]
27mod tests {
28
29 use super::*;
30 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Shawn Willdendbdac602021-01-12 22:35:16 -070031 Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
32 ErrorCode::ErrorCode, HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
33 KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080034 KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue,
35 KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Joel Galensonde386b42020-09-30 10:53:05 -070036 };
37 use android_hardware_security_keymint::binder;
38 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
Joel Galensonde386b42020-09-30 10:53:05 -070042 fn get_device() -> Box<dyn IKeyMintDevice> {
43 add_keymint_device_service();
44 let compat_service: Box<dyn IKeystoreCompatService> =
Joel Galensonf21c0022020-12-11 14:37:52 -080045 binder::get_interface(COMPAT_NAME).unwrap();
Joel Galensonde386b42020-09-30 10:53:05 -070046 compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap()
47 }
48
49 #[test]
50 fn test_get_hardware_info() {
51 let legacy = get_device();
52 let hinfo = legacy.getHardwareInfo().unwrap();
53 assert_eq!(hinfo.versionNumber, 0);
54 assert_ne!(hinfo.securityLevel, SecurityLevel::SOFTWARE);
55 assert_eq!(hinfo.keyMintName, "RemoteKeymaster");
56 assert_eq!(hinfo.keyMintAuthorName, "Google");
57 }
58
59 #[test]
Joel Galensonde386b42020-09-30 10:53:05 -070060 fn test_add_rng_entropy() {
61 let legacy = get_device();
62 let result = legacy.addRngEntropy(&[42; 16]);
63 assert!(result.is_ok(), "{:?}", result);
64 }
65
66 // TODO: If I only need the key itself, don't return the other things.
Shawn Willdendbdac602021-01-12 22:35:16 -070067 fn generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult {
68 let creation_result = legacy.generateKey(&kps).expect("Failed to generate key");
69 assert_ne!(creation_result.keyBlob.len(), 0);
70 creation_result
Joel Galensonde386b42020-09-30 10:53:05 -070071 }
72
73 fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
74 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -080075 KeyParameter {
76 tag: Tag::ALGORITHM,
77 value: KeyParameterValue::Algorithm(Algorithm::RSA),
78 },
79 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) },
Joel Galensonde386b42020-09-30 10:53:05 -070080 KeyParameter {
81 tag: Tag::RSA_PUBLIC_EXPONENT,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080082 value: KeyParameterValue::LongInteger(65537),
Joel Galensonde386b42020-09-30 10:53:05 -070083 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -080084 KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) },
Joel Galensonde386b42020-09-30 10:53:05 -070085 KeyParameter {
86 tag: Tag::PADDING,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080087 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
Joel Galensonde386b42020-09-30 10:53:05 -070088 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -080089 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
90 KeyParameter {
91 tag: Tag::PURPOSE,
92 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
93 },
Joel Galensonde386b42020-09-30 10:53:05 -070094 ];
95 if encrypt {
96 kps.push(KeyParameter {
97 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080098 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -070099 });
100 }
101 if attest {
102 kps.push(KeyParameter {
103 tag: Tag::ATTESTATION_CHALLENGE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800104 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700105 });
106 kps.push(KeyParameter {
107 tag: Tag::ATTESTATION_APPLICATION_ID,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800108 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700109 });
110 }
Shawn Willdendbdac602021-01-12 22:35:16 -0700111 let creation_result = generate_key(legacy, kps);
Joel Galensonde386b42020-09-30 10:53:05 -0700112 if attest {
113 // TODO: Will this always be greater than 1?
Shawn Willdendbdac602021-01-12 22:35:16 -0700114 assert!(creation_result.certificateChain.len() > 1);
Joel Galensonde386b42020-09-30 10:53:05 -0700115 } else {
Shawn Willdendbdac602021-01-12 22:35:16 -0700116 assert_eq!(creation_result.certificateChain.len(), 1);
Joel Galensonde386b42020-09-30 10:53:05 -0700117 }
Shawn Willdendbdac602021-01-12 22:35:16 -0700118 creation_result.keyBlob
Joel Galensonde386b42020-09-30 10:53:05 -0700119 }
120
121 #[test]
122 fn test_generate_key_no_encrypt() {
123 let legacy = get_device();
124 generate_rsa_key(legacy.as_ref(), false, false);
125 }
126
127 #[test]
128 fn test_generate_key_encrypt() {
129 let legacy = get_device();
130 generate_rsa_key(legacy.as_ref(), true, false);
131 }
132
133 #[test]
134 fn test_generate_key_attested() {
135 let legacy = get_device();
136 generate_rsa_key(legacy.as_ref(), false, true);
137 }
138
139 #[test]
140 fn test_import_key() {
141 let legacy = get_device();
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800142 let kps = [KeyParameter {
143 tag: Tag::ALGORITHM,
144 value: KeyParameterValue::Algorithm(Algorithm::AES),
145 }];
Joel Galensonde386b42020-09-30 10:53:05 -0700146 let kf = KeyFormat::RAW;
147 let kd = [0; 16];
Shawn Willdendbdac602021-01-12 22:35:16 -0700148 let creation_result = legacy.importKey(&kps, kf, &kd).expect("Failed to import key");
149 assert_ne!(creation_result.keyBlob.len(), 0);
150 assert_eq!(creation_result.certificateChain.len(), 0);
Joel Galensonde386b42020-09-30 10:53:05 -0700151 }
152
153 #[test]
154 fn test_import_wrapped_key() {
155 let legacy = get_device();
Shawn Willdendbdac602021-01-12 22:35:16 -0700156 let result = legacy.importWrappedKey(&[], &[], &[], &[], 0, 0);
Joel Galensonde386b42020-09-30 10:53:05 -0700157 // TODO: This test seems to fail on cuttlefish. How should I test it?
158 assert!(result.is_err());
159 }
160
161 #[test]
162 fn test_upgrade_key() {
163 let legacy = get_device();
164 let blob = generate_rsa_key(legacy.as_ref(), false, false);
165 let result = legacy.upgradeKey(&blob, &[]);
166 // TODO: This test seems to fail on cuttlefish. How should I test it?
167 assert!(result.is_err());
168 }
169
170 #[test]
171 fn test_delete_key() {
172 let legacy = get_device();
173 let blob = generate_rsa_key(legacy.as_ref(), false, false);
174 let result = legacy.deleteKey(&blob);
175 assert!(result.is_ok(), "{:?}", result);
176 }
177
178 #[test]
179 fn test_delete_all_keys() {
180 let legacy = get_device();
181 let result = legacy.deleteAllKeys();
182 assert!(result.is_ok(), "{:?}", result);
183 }
184
185 #[test]
186 fn test_destroy_attestation_ids() {
187 let legacy = get_device();
188 let result = legacy.destroyAttestationIds();
189 assert!(result.is_err());
190 assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
191 }
192
193 fn generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8> {
194 let kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800195 KeyParameter {
196 tag: Tag::ALGORITHM,
197 value: KeyParameterValue::Algorithm(Algorithm::AES),
198 },
199 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
200 KeyParameter {
201 tag: Tag::BLOCK_MODE,
202 value: KeyParameterValue::BlockMode(BlockMode::CBC),
203 },
204 KeyParameter {
205 tag: Tag::PADDING,
206 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
207 },
208 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
Joel Galensonde386b42020-09-30 10:53:05 -0700209 KeyParameter {
210 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800211 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700212 },
213 KeyParameter {
214 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800215 value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700216 },
217 ];
Shawn Willdendbdac602021-01-12 22:35:16 -0700218 let creation_result = generate_key(legacy, kps);
219 assert_eq!(creation_result.certificateChain.len(), 0);
220 creation_result.keyBlob
Joel Galensonde386b42020-09-30 10:53:05 -0700221 }
222
223 fn begin(
224 legacy: &dyn IKeyMintDevice,
225 blob: &[u8],
226 purpose: KeyPurpose,
227 extra_params: Option<Vec<KeyParameter>>,
228 ) -> BeginResult {
229 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800230 KeyParameter {
231 tag: Tag::BLOCK_MODE,
232 value: KeyParameterValue::BlockMode(BlockMode::CBC),
233 },
234 KeyParameter {
235 tag: Tag::PADDING,
236 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
237 },
Joel Galensonde386b42020-09-30 10:53:05 -0700238 ];
239 if let Some(mut extras) = extra_params {
240 kps.append(&mut extras);
241 }
242 let result = legacy.begin(purpose, &blob, &kps, &HardwareAuthToken::default());
243 assert!(result.is_ok(), "{:?}", result);
244 result.unwrap()
245 }
246
247 #[test]
248 fn test_begin_abort() {
249 let legacy = get_device();
250 let blob = generate_aes_key(legacy.as_ref());
251 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
252 let operation = begin_result.operation.unwrap();
253 let result = operation.abort();
254 assert!(result.is_ok(), "{:?}", result);
255 let result = operation.abort();
256 assert!(result.is_err());
257 }
258
259 #[test]
260 fn test_begin_update_finish() {
261 let legacy = get_device();
262 let blob = generate_aes_key(legacy.as_ref());
263
264 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
265 let operation = begin_result.operation.unwrap();
266 let params = KeyParameterArray {
267 params: vec![KeyParameter {
268 tag: Tag::ASSOCIATED_DATA,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800269 value: KeyParameterValue::Blob(b"foobar".to_vec()),
Joel Galensonde386b42020-09-30 10:53:05 -0700270 }],
271 };
272 let message = [42; 128];
273 let mut out_params = None;
274 let result =
275 operation.finish(Some(&params), Some(&message), None, None, None, &mut out_params);
276 assert!(result.is_ok(), "{:?}", result);
277 let ciphertext = result.unwrap();
278 assert!(!ciphertext.is_empty());
279 assert!(out_params.is_some());
280
281 let begin_result =
282 begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
283 let operation = begin_result.operation.unwrap();
284 let mut out_params = None;
285 let mut output = None;
286 let result = operation.update(
287 Some(&params),
288 Some(&ciphertext),
289 None,
290 None,
291 &mut out_params,
292 &mut output,
293 );
294 assert!(result.is_ok(), "{:?}", result);
295 assert_eq!(result.unwrap(), message.len() as i32);
296 assert!(output.is_some());
297 assert_eq!(output.unwrap().data, message.to_vec());
298 let result = operation.finish(Some(&params), None, None, None, None, &mut out_params);
299 assert!(result.is_ok(), "{:?}", result);
300 assert!(out_params.is_some());
301 }
Joel Galensonf21c0022020-12-11 14:37:52 -0800302
303 #[test]
304 fn test_secure_clock() {
305 add_keymint_device_service();
306 let compat_service: Box<dyn IKeystoreCompatService> =
307 binder::get_interface(COMPAT_NAME).unwrap();
308 let secure_clock = compat_service.getSecureClock().unwrap();
309
310 let challenge = 42;
311 let result = secure_clock.generateTimeStamp(challenge);
312 assert!(result.is_ok(), "{:?}", result);
313 let result = result.unwrap();
314 assert_eq!(result.challenge, challenge);
315 assert_eq!(result.mac.len(), 32);
316 }
317
318 #[test]
319 fn test_shared_secret() {
320 add_keymint_device_service();
321 let compat_service: Box<dyn IKeystoreCompatService> =
322 binder::get_interface(COMPAT_NAME).unwrap();
323 let shared_secret =
324 compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
325
326 let result = shared_secret.getSharedSecretParameters();
327 assert!(result.is_ok(), "{:?}", result);
328 let params = result.unwrap();
329
330 let result = shared_secret.computeSharedSecret(&[params]);
331 assert!(result.is_ok(), "{:?}", result);
332 assert_ne!(result.unwrap().len(), 0);
333 }
Joel Galensonde386b42020-09-30 10:53:05 -0700334}