blob: b6a6baff6cc00a258be1e3bc62b3b7913841731f [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,
35 KeyParameterArray::KeyParameterArray, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
36 SecurityLevel::SecurityLevel, Tag::Tag,
37 };
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![
90 KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::RSA.0, ..Default::default() },
91 KeyParameter { tag: Tag::KEY_SIZE, integer: 2048, ..Default::default() },
92 KeyParameter {
93 tag: Tag::RSA_PUBLIC_EXPONENT,
94 longInteger: 65537,
95 ..Default::default()
96 },
97 KeyParameter { tag: Tag::DIGEST, integer: Digest::SHA_2_256.0, ..Default::default() },
98 KeyParameter {
99 tag: Tag::PADDING,
100 integer: PaddingMode::RSA_PSS.0,
101 ..Default::default()
102 },
103 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, boolValue: true, ..Default::default() },
104 KeyParameter { tag: Tag::PURPOSE, integer: KeyPurpose::SIGN.0, ..Default::default() },
105 ];
106 if encrypt {
107 kps.push(KeyParameter {
108 tag: Tag::PURPOSE,
109 integer: KeyPurpose::ENCRYPT.0,
110 ..Default::default()
111 });
112 }
113 if attest {
114 kps.push(KeyParameter {
115 tag: Tag::ATTESTATION_CHALLENGE,
116 blob: vec![42; 8],
117 ..Default::default()
118 });
119 kps.push(KeyParameter {
120 tag: Tag::ATTESTATION_APPLICATION_ID,
121 blob: vec![42; 8],
122 ..Default::default()
123 });
124 }
125 let (blob, _, cert_chain) = generate_key(legacy, kps);
126 if attest {
127 // TODO: Will this always be greater than 1?
128 assert!(cert_chain.len() > 1);
129 } else {
130 assert_eq!(cert_chain.len(), 1);
131 }
132 blob.data
133 }
134
135 #[test]
136 fn test_generate_key_no_encrypt() {
137 let legacy = get_device();
138 generate_rsa_key(legacy.as_ref(), false, false);
139 }
140
141 #[test]
142 fn test_generate_key_encrypt() {
143 let legacy = get_device();
144 generate_rsa_key(legacy.as_ref(), true, false);
145 }
146
147 #[test]
148 fn test_generate_key_attested() {
149 let legacy = get_device();
150 generate_rsa_key(legacy.as_ref(), false, true);
151 }
152
153 #[test]
154 fn test_import_key() {
155 let legacy = get_device();
156 let kps =
157 [KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::AES.0, ..Default::default() }];
158 let kf = KeyFormat::RAW;
159 let kd = [0; 16];
160 let mut blob = ByteArray { data: vec![] };
161 let mut characteristics = KeyCharacteristics::default();
162 let mut cert_chain = vec![];
163 let result =
164 legacy.importKey(&kps, kf, &kd, &mut blob, &mut characteristics, &mut cert_chain);
165 assert!(result.is_ok(), "{:?}", result);
166 assert_ne!(blob.data.len(), 0);
167 assert_eq!(cert_chain.len(), 0);
168 }
169
170 #[test]
171 fn test_import_wrapped_key() {
172 let legacy = get_device();
173 let mut blob = ByteArray { data: vec![] };
174 let mut characteristics = KeyCharacteristics::default();
175 let result =
176 legacy.importWrappedKey(&[], &[], &[], &[], 0, 0, &mut blob, &mut characteristics);
177 // TODO: This test seems to fail on cuttlefish. How should I test it?
178 assert!(result.is_err());
179 }
180
181 #[test]
182 fn test_upgrade_key() {
183 let legacy = get_device();
184 let blob = generate_rsa_key(legacy.as_ref(), false, false);
185 let result = legacy.upgradeKey(&blob, &[]);
186 // TODO: This test seems to fail on cuttlefish. How should I test it?
187 assert!(result.is_err());
188 }
189
190 #[test]
191 fn test_delete_key() {
192 let legacy = get_device();
193 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() {
200 let legacy = get_device();
201 let result = legacy.deleteAllKeys();
202 assert!(result.is_ok(), "{:?}", result);
203 }
204
205 #[test]
206 fn test_destroy_attestation_ids() {
207 let legacy = get_device();
208 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![
215 KeyParameter { tag: Tag::ALGORITHM, integer: Algorithm::AES.0, ..Default::default() },
216 KeyParameter { tag: Tag::KEY_SIZE, integer: 128, ..Default::default() },
217 KeyParameter { tag: Tag::BLOCK_MODE, integer: BlockMode::CBC.0, ..Default::default() },
218 KeyParameter { tag: Tag::PADDING, integer: PaddingMode::NONE.0, ..Default::default() },
219 KeyParameter { tag: Tag::NO_AUTH_REQUIRED, boolValue: true, ..Default::default() },
220 KeyParameter {
221 tag: Tag::PURPOSE,
222 integer: KeyPurpose::ENCRYPT.0,
223 ..Default::default()
224 },
225 KeyParameter {
226 tag: Tag::PURPOSE,
227 integer: KeyPurpose::DECRYPT.0,
228 ..Default::default()
229 },
230 ];
231 let (blob, _, cert_chain) = generate_key(legacy, kps);
232 assert_eq!(cert_chain.len(), 0);
233 blob.data
234 }
235
236 fn begin(
237 legacy: &dyn IKeyMintDevice,
238 blob: &[u8],
239 purpose: KeyPurpose,
240 extra_params: Option<Vec<KeyParameter>>,
241 ) -> BeginResult {
242 let mut kps = vec![
243 KeyParameter { tag: Tag::BLOCK_MODE, integer: BlockMode::CBC.0, ..Default::default() },
244 KeyParameter { tag: Tag::PADDING, integer: PaddingMode::NONE.0, ..Default::default() },
245 ];
246 if let Some(mut extras) = extra_params {
247 kps.append(&mut extras);
248 }
249 let result = legacy.begin(purpose, &blob, &kps, &HardwareAuthToken::default());
250 assert!(result.is_ok(), "{:?}", result);
251 result.unwrap()
252 }
253
254 #[test]
255 fn test_begin_abort() {
256 let legacy = get_device();
257 let blob = generate_aes_key(legacy.as_ref());
258 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
259 let operation = begin_result.operation.unwrap();
260 let result = operation.abort();
261 assert!(result.is_ok(), "{:?}", result);
262 let result = operation.abort();
263 assert!(result.is_err());
264 }
265
266 #[test]
267 fn test_begin_update_finish() {
268 let legacy = get_device();
269 let blob = generate_aes_key(legacy.as_ref());
270
271 let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
272 let operation = begin_result.operation.unwrap();
273 let params = KeyParameterArray {
274 params: vec![KeyParameter {
275 tag: Tag::ASSOCIATED_DATA,
276 blob: b"foobar".to_vec(),
277 ..Default::default()
278 }],
279 };
280 let message = [42; 128];
281 let mut out_params = None;
282 let result =
283 operation.finish(Some(&params), Some(&message), None, None, None, &mut out_params);
284 assert!(result.is_ok(), "{:?}", result);
285 let ciphertext = result.unwrap();
286 assert!(!ciphertext.is_empty());
287 assert!(out_params.is_some());
288
289 let begin_result =
290 begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
291 let operation = begin_result.operation.unwrap();
292 let mut out_params = None;
293 let mut output = None;
294 let result = operation.update(
295 Some(&params),
296 Some(&ciphertext),
297 None,
298 None,
299 &mut out_params,
300 &mut output,
301 );
302 assert!(result.is_ok(), "{:?}", result);
303 assert_eq!(result.unwrap(), message.len() as i32);
304 assert!(output.is_some());
305 assert_eq!(output.unwrap().data, message.to_vec());
306 let result = operation.finish(Some(&params), None, None, None, None, &mut out_params);
307 assert!(result.is_ok(), "{:?}", result);
308 assert!(out_params.is_some());
309 }
310}