blob: 36f1303d50f3177ad06d3fe5b34dfcc0af08bfde [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::{
31 Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, ByteArray::ByteArray,
32 Certificate::Certificate, Digest::Digest, ErrorCode::ErrorCode,
33 HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
34 KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080035 KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue,
36 KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Joel Galensonde386b42020-09-30 10:53:05 -070037 };
38 use android_hardware_security_keymint::binder;
39 use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
40
41 fn get_device() -> Box<dyn IKeyMintDevice> {
42 add_keymint_device_service();
43 let compat_service: Box<dyn IKeystoreCompatService> =
44 binder::get_interface("android.security.compat").unwrap();
45 compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap()
46 }
47
48 #[test]
49 fn test_get_hardware_info() {
50 let legacy = get_device();
51 let hinfo = legacy.getHardwareInfo().unwrap();
52 assert_eq!(hinfo.versionNumber, 0);
53 assert_ne!(hinfo.securityLevel, SecurityLevel::SOFTWARE);
54 assert_eq!(hinfo.keyMintName, "RemoteKeymaster");
55 assert_eq!(hinfo.keyMintAuthorName, "Google");
56 }
57
58 #[test]
59 fn test_verify_authorization() {
60 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::HardwareAuthToken::HardwareAuthToken;
61 let legacy = get_device();
62 let result = legacy.verifyAuthorization(0, &HardwareAuthToken::default());
63 assert!(result.is_err());
64 assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
65 }
66
67 #[test]
68 fn test_add_rng_entropy() {
69 let legacy = get_device();
70 let result = legacy.addRngEntropy(&[42; 16]);
71 assert!(result.is_ok(), "{:?}", result);
72 }
73
74 // TODO: If I only need the key itself, don't return the other things.
75 fn generate_key(
76 legacy: &dyn IKeyMintDevice,
77 kps: Vec<KeyParameter>,
78 ) -> (ByteArray, KeyCharacteristics, Vec<Certificate>) {
79 let mut blob = ByteArray { data: vec![] };
80 let mut characteristics = KeyCharacteristics::default();
81 let mut cert_chain = vec![];
82 let result = legacy.generateKey(&kps, &mut blob, &mut characteristics, &mut cert_chain);
83 assert!(result.is_ok(), "{:?}", result);
84 assert_ne!(blob.data.len(), 0);
85 (blob, characteristics, cert_chain)
86 }
87
88 fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
89 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -080090 KeyParameter {
91 tag: Tag::ALGORITHM,
92 value: KeyParameterValue::Algorithm(Algorithm::RSA),
93 },
94 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) },
Joel Galensonde386b42020-09-30 10:53:05 -070095 KeyParameter {
96 tag: Tag::RSA_PUBLIC_EXPONENT,
Janis Danisevskisb60c0042020-12-17 00:11:21 -080097 value: KeyParameterValue::LongInteger(65537),
Joel Galensonde386b42020-09-30 10:53:05 -070098 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -080099 KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) },
Joel Galensonde386b42020-09-30 10:53:05 -0700100 KeyParameter {
101 tag: Tag::PADDING,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800102 value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
Joel Galensonde386b42020-09-30 10:53:05 -0700103 },
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800104 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
105 KeyParameter {
106 tag: Tag::PURPOSE,
107 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
108 },
Joel Galensonde386b42020-09-30 10:53:05 -0700109 ];
110 if encrypt {
111 kps.push(KeyParameter {
112 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800113 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700114 });
115 }
116 if attest {
117 kps.push(KeyParameter {
118 tag: Tag::ATTESTATION_CHALLENGE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800119 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700120 });
121 kps.push(KeyParameter {
122 tag: Tag::ATTESTATION_APPLICATION_ID,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800123 value: KeyParameterValue::Blob(vec![42; 8]),
Joel Galensonde386b42020-09-30 10:53:05 -0700124 });
125 }
126 let (blob, _, cert_chain) = generate_key(legacy, kps);
127 if attest {
128 // TODO: Will this always be greater than 1?
129 assert!(cert_chain.len() > 1);
130 } else {
131 assert_eq!(cert_chain.len(), 1);
132 }
133 blob.data
134 }
135
136 #[test]
137 fn test_generate_key_no_encrypt() {
138 let legacy = get_device();
139 generate_rsa_key(legacy.as_ref(), false, false);
140 }
141
142 #[test]
143 fn test_generate_key_encrypt() {
144 let legacy = get_device();
145 generate_rsa_key(legacy.as_ref(), true, false);
146 }
147
148 #[test]
149 fn test_generate_key_attested() {
150 let legacy = get_device();
151 generate_rsa_key(legacy.as_ref(), false, true);
152 }
153
154 #[test]
155 fn test_import_key() {
156 let legacy = get_device();
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800157 let kps = [KeyParameter {
158 tag: Tag::ALGORITHM,
159 value: KeyParameterValue::Algorithm(Algorithm::AES),
160 }];
Joel Galensonde386b42020-09-30 10:53:05 -0700161 let kf = KeyFormat::RAW;
162 let kd = [0; 16];
163 let mut blob = ByteArray { data: vec![] };
164 let mut characteristics = KeyCharacteristics::default();
165 let mut cert_chain = vec![];
166 let result =
167 legacy.importKey(&kps, kf, &kd, &mut blob, &mut characteristics, &mut cert_chain);
168 assert!(result.is_ok(), "{:?}", result);
169 assert_ne!(blob.data.len(), 0);
170 assert_eq!(cert_chain.len(), 0);
171 }
172
173 #[test]
174 fn test_import_wrapped_key() {
175 let legacy = get_device();
176 let mut blob = ByteArray { data: vec![] };
177 let mut characteristics = KeyCharacteristics::default();
178 let result =
179 legacy.importWrappedKey(&[], &[], &[], &[], 0, 0, &mut blob, &mut characteristics);
180 // TODO: This test seems to fail on cuttlefish. How should I test it?
181 assert!(result.is_err());
182 }
183
184 #[test]
185 fn test_upgrade_key() {
186 let legacy = get_device();
187 let blob = generate_rsa_key(legacy.as_ref(), false, false);
188 let result = legacy.upgradeKey(&blob, &[]);
189 // TODO: This test seems to fail on cuttlefish. How should I test it?
190 assert!(result.is_err());
191 }
192
193 #[test]
194 fn test_delete_key() {
195 let legacy = get_device();
196 let blob = generate_rsa_key(legacy.as_ref(), false, false);
197 let result = legacy.deleteKey(&blob);
198 assert!(result.is_ok(), "{:?}", result);
199 }
200
201 #[test]
202 fn test_delete_all_keys() {
203 let legacy = get_device();
204 let result = legacy.deleteAllKeys();
205 assert!(result.is_ok(), "{:?}", result);
206 }
207
208 #[test]
209 fn test_destroy_attestation_ids() {
210 let legacy = get_device();
211 let result = legacy.destroyAttestationIds();
212 assert!(result.is_err());
213 assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
214 }
215
216 fn generate_aes_key(legacy: &dyn IKeyMintDevice) -> Vec<u8> {
217 let kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800218 KeyParameter {
219 tag: Tag::ALGORITHM,
220 value: KeyParameterValue::Algorithm(Algorithm::AES),
221 },
222 KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
223 KeyParameter {
224 tag: Tag::BLOCK_MODE,
225 value: KeyParameterValue::BlockMode(BlockMode::CBC),
226 },
227 KeyParameter {
228 tag: Tag::PADDING,
229 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
230 },
231 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) },
Joel Galensonde386b42020-09-30 10:53:05 -0700232 KeyParameter {
233 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800234 value: KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700235 },
236 KeyParameter {
237 tag: Tag::PURPOSE,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800238 value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
Joel Galensonde386b42020-09-30 10:53:05 -0700239 },
240 ];
241 let (blob, _, cert_chain) = generate_key(legacy, kps);
242 assert_eq!(cert_chain.len(), 0);
243 blob.data
244 }
245
246 fn begin(
247 legacy: &dyn IKeyMintDevice,
248 blob: &[u8],
249 purpose: KeyPurpose,
250 extra_params: Option<Vec<KeyParameter>>,
251 ) -> BeginResult {
252 let mut kps = vec![
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800253 KeyParameter {
254 tag: Tag::BLOCK_MODE,
255 value: KeyParameterValue::BlockMode(BlockMode::CBC),
256 },
257 KeyParameter {
258 tag: Tag::PADDING,
259 value: KeyParameterValue::PaddingMode(PaddingMode::NONE),
260 },
Joel Galensonde386b42020-09-30 10:53:05 -0700261 ];
262 if let Some(mut extras) = extra_params {
263 kps.append(&mut extras);
264 }
265 let result = legacy.begin(purpose, &blob, &kps, &HardwareAuthToken::default());
266 assert!(result.is_ok(), "{:?}", result);
267 result.unwrap()
268 }
269
270 #[test]
271 fn test_begin_abort() {
272 let legacy = get_device();
273 let blob = generate_aes_key(legacy.as_ref());
274 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
275 let operation = begin_result.operation.unwrap();
276 let result = operation.abort();
277 assert!(result.is_ok(), "{:?}", result);
278 let result = operation.abort();
279 assert!(result.is_err());
280 }
281
282 #[test]
283 fn test_begin_update_finish() {
284 let legacy = get_device();
285 let blob = generate_aes_key(legacy.as_ref());
286
287 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
288 let operation = begin_result.operation.unwrap();
289 let params = KeyParameterArray {
290 params: vec![KeyParameter {
291 tag: Tag::ASSOCIATED_DATA,
Janis Danisevskisb60c0042020-12-17 00:11:21 -0800292 value: KeyParameterValue::Blob(b"foobar".to_vec()),
Joel Galensonde386b42020-09-30 10:53:05 -0700293 }],
294 };
295 let message = [42; 128];
296 let mut out_params = None;
297 let result =
298 operation.finish(Some(&params), Some(&message), None, None, None, &mut out_params);
299 assert!(result.is_ok(), "{:?}", result);
300 let ciphertext = result.unwrap();
301 assert!(!ciphertext.is_empty());
302 assert!(out_params.is_some());
303
304 let begin_result =
305 begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
306 let operation = begin_result.operation.unwrap();
307 let mut out_params = None;
308 let mut output = None;
309 let result = operation.update(
310 Some(&params),
311 Some(&ciphertext),
312 None,
313 None,
314 &mut out_params,
315 &mut output,
316 );
317 assert!(result.is_ok(), "{:?}", result);
318 assert_eq!(result.unwrap(), message.len() as i32);
319 assert!(output.is_some());
320 assert_eq!(output.unwrap().data, message.to_vec());
321 let result = operation.finish(Some(&params), None, None, None, None, &mut out_params);
322 assert!(result.is_ok(), "{:?}", result);
323 assert!(out_params.is_some());
324 }
325}