1 // Copyright 2022, 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 use nix::unistd::getuid;
16
17 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
18 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
19 ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
20 SecurityLevel::SecurityLevel,
21 };
22 use android_system_keystore2::aidl::android::system::keystore2::{
23 Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
24 };
25
26 use keystore2_test_utils::{
27 authorizations, get_keystore_service, key_generations, key_generations::Error,
28 };
29
30 use crate::ffi_test_utils::validate_certchain;
31
32 use crate::{
33 keystore2_client_test_utils::app_attest_key_feature_exists,
34 skip_test_if_no_app_attest_key_feature,
35 };
36
37 /// Generate RSA and EC attestation keys and use them for signing RSA-signing keys.
38 /// Test should be able to generate attestation keys and use them successfully.
39 #[test]
keystore2_attest_rsa_signing_key_success()40 fn keystore2_attest_rsa_signing_key_success() {
41 skip_test_if_no_app_attest_key_feature!();
42
43 let keystore2 = get_keystore_service();
44 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
45 let att_challenge: &[u8] = b"foo";
46
47 for algo in [Algorithm::RSA, Algorithm::EC] {
48 // Create attestation key.
49 let attestation_key_metadata =
50 key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
51
52 let mut cert_chain: Vec<u8> = Vec::new();
53 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
54 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
55 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
56
57 // Create RSA signing key and use attestation key to sign it.
58 let sign_key_alias = format!("ks_attest_rsa_signing_key_{}", getuid());
59 let sign_key_metadata = key_generations::generate_rsa_key(
60 &sec_level,
61 Domain::APP,
62 -1,
63 Some(sign_key_alias),
64 &key_generations::KeyParams {
65 key_size: 2048,
66 purpose: vec![KeyPurpose::SIGN, KeyPurpose::VERIFY],
67 padding: Some(PaddingMode::RSA_PKCS1_1_5_SIGN),
68 digest: Some(Digest::SHA_2_256),
69 mgf_digest: None,
70 block_mode: None,
71 att_challenge: Some(att_challenge.to_vec()),
72 },
73 Some(&attestation_key_metadata.key),
74 )
75 .unwrap();
76
77 let mut cert_chain: Vec<u8> = Vec::new();
78 cert_chain.extend(sign_key_metadata.certificate.as_ref().unwrap());
79 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
80 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
81 validate_certchain(&cert_chain).expect("Error while validating cert chain");
82 }
83 }
84
85 /// Generate RSA and EC attestation keys and use them for signing RSA encrypt/decrypt keys.
86 /// Test should be able to generate attestation keys and use them successfully.
87 #[test]
keystore2_attest_rsa_encrypt_key_success()88 fn keystore2_attest_rsa_encrypt_key_success() {
89 skip_test_if_no_app_attest_key_feature!();
90
91 let keystore2 = get_keystore_service();
92 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
93 let att_challenge: &[u8] = b"foo";
94
95 for algo in [Algorithm::RSA, Algorithm::EC] {
96 // Create attestation key.
97 let attestation_key_metadata =
98 key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
99
100 let mut cert_chain: Vec<u8> = Vec::new();
101 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
102 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
103 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
104
105 // Create RSA encrypt/decrypt key and use attestation key to sign it.
106 let decrypt_key_alias = format!("ks_attest_rsa_encrypt_key_{}", getuid());
107 let decrypt_key_metadata = key_generations::generate_rsa_key(
108 &sec_level,
109 Domain::APP,
110 -1,
111 Some(decrypt_key_alias),
112 &key_generations::KeyParams {
113 key_size: 2048,
114 purpose: vec![KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT],
115 padding: Some(PaddingMode::RSA_PKCS1_1_5_ENCRYPT),
116 digest: Some(Digest::SHA_2_256),
117 mgf_digest: None,
118 block_mode: None,
119 att_challenge: Some(att_challenge.to_vec()),
120 },
121 Some(&attestation_key_metadata.key),
122 )
123 .unwrap();
124
125 let mut cert_chain: Vec<u8> = Vec::new();
126 cert_chain.extend(decrypt_key_metadata.certificate.as_ref().unwrap());
127 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
128 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
129
130 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
131 }
132 }
133
134 /// Generate RSA and EC attestation keys and use them for signing EC keys.
135 /// Test should be able to generate attestation keys and use them successfully.
136 #[test]
keystore2_attest_ec_key_success()137 fn keystore2_attest_ec_key_success() {
138 skip_test_if_no_app_attest_key_feature!();
139
140 let keystore2 = get_keystore_service();
141 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
142 let att_challenge: &[u8] = b"foo";
143
144 for algo in [Algorithm::RSA, Algorithm::EC] {
145 // Create attestation key.
146 let attestation_key_metadata =
147 key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
148
149 let mut cert_chain: Vec<u8> = Vec::new();
150 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
151 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
152 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
153
154 // Create EC key and use attestation key to sign it.
155 let ec_key_alias = format!("ks_ec_attested_test_key_{}", getuid());
156 let ec_key_metadata = key_generations::generate_ec_256_attested_key(
157 &sec_level,
158 Some(ec_key_alias),
159 att_challenge,
160 &attestation_key_metadata.key,
161 )
162 .unwrap();
163
164 let mut cert_chain: Vec<u8> = Vec::new();
165 cert_chain.extend(ec_key_metadata.certificate.as_ref().unwrap());
166 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
167 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
168
169 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
170 }
171 }
172
173 /// Generate EC-CURVE_25519 attestation key and use it for signing RSA-signing keys.
174 /// Test should be able to generate RSA signing key with EC-CURVE_25519 as attestation key
175 /// successfully.
176 #[test]
keystore2_attest_rsa_signing_key_with_ec_25519_key_success()177 fn keystore2_attest_rsa_signing_key_with_ec_25519_key_success() {
178 skip_test_if_no_app_attest_key_feature!();
179
180 let keystore2 = get_keystore_service();
181 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
182 let att_challenge: &[u8] = b"foo";
183
184 // Create EcCurve::CURVE_25519 attestation key.
185 let attestation_key_metadata = key_generations::generate_ec_attestation_key(
186 &sec_level,
187 att_challenge,
188 Digest::NONE,
189 EcCurve::CURVE_25519,
190 )
191 .unwrap();
192
193 let mut cert_chain: Vec<u8> = Vec::new();
194 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
195 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
196 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
197
198 // Create RSA signing key and use attestation key to sign it.
199 let sign_key_alias = format!("ksrsa_attested_sign_test_key_{}", getuid());
200 let sign_key_metadata = key_generations::generate_rsa_key(
201 &sec_level,
202 Domain::APP,
203 -1,
204 Some(sign_key_alias),
205 &key_generations::KeyParams {
206 key_size: 2048,
207 purpose: vec![KeyPurpose::SIGN, KeyPurpose::VERIFY],
208 padding: Some(PaddingMode::RSA_PKCS1_1_5_SIGN),
209 digest: Some(Digest::SHA_2_256),
210 mgf_digest: None,
211 block_mode: None,
212 att_challenge: Some(att_challenge.to_vec()),
213 },
214 Some(&attestation_key_metadata.key),
215 )
216 .unwrap();
217
218 let mut cert_chain: Vec<u8> = Vec::new();
219 cert_chain.extend(sign_key_metadata.certificate.as_ref().unwrap());
220 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
221 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
222 validate_certchain(&cert_chain).expect("Error while validating cert chain");
223 }
224
225 /// Try to generate RSA attestation key with multiple purposes. Test should fail with error code
226 /// `INCOMPATIBLE_PURPOSE` to generate an attestation key.
227 #[test]
keystore2_generate_rsa_attest_key_with_multi_purpose_fail()228 fn keystore2_generate_rsa_attest_key_with_multi_purpose_fail() {
229 skip_test_if_no_app_attest_key_feature!();
230
231 let keystore2 = get_keystore_service();
232 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
233
234 let digest = Digest::SHA_2_256;
235 let padding = PaddingMode::RSA_PKCS1_1_5_SIGN;
236 let key_size = 2048;
237
238 let attest_key_alias =
239 format!("ksrsa_attest_multipurpose_key_{}{}{}", getuid(), key_size, digest.0);
240
241 let attest_gen_params = authorizations::AuthSetBuilder::new()
242 .no_auth_required()
243 .algorithm(Algorithm::RSA)
244 .purpose(KeyPurpose::ATTEST_KEY)
245 .purpose(KeyPurpose::SIGN)
246 .purpose(KeyPurpose::VERIFY)
247 .digest(digest)
248 .key_size(key_size)
249 .rsa_public_exponent(65537)
250 .padding_mode(padding);
251
252 let result = key_generations::map_ks_error(sec_level.generateKey(
253 &KeyDescriptor {
254 domain: Domain::APP,
255 nspace: -1,
256 alias: Some(attest_key_alias),
257 blob: None,
258 },
259 None,
260 &attest_gen_params,
261 0,
262 b"entropy",
263 ));
264 assert!(result.is_err());
265 assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
266 }
267
268 /// Try to generate EC attestation key with multiple purposes. Test should fail with error code
269 /// `INCOMPATIBLE_PURPOSE` to generate an attestation key.
270 #[test]
keystore2_ec_attest_key_with_multi_purpose_fail()271 fn keystore2_ec_attest_key_with_multi_purpose_fail() {
272 skip_test_if_no_app_attest_key_feature!();
273
274 let keystore2 = get_keystore_service();
275 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
276
277 let attest_key_alias = format!("ks_ec_attest_multipurpose_key_{}", getuid());
278
279 let attest_gen_params = authorizations::AuthSetBuilder::new()
280 .no_auth_required()
281 .algorithm(Algorithm::EC)
282 .purpose(KeyPurpose::ATTEST_KEY)
283 .purpose(KeyPurpose::SIGN)
284 .purpose(KeyPurpose::VERIFY)
285 .digest(Digest::SHA_2_256)
286 .ec_curve(EcCurve::P_256);
287
288 let result = key_generations::map_ks_error(sec_level.generateKey(
289 &KeyDescriptor {
290 domain: Domain::APP,
291 nspace: -1,
292 alias: Some(attest_key_alias),
293 blob: None,
294 },
295 None,
296 &attest_gen_params,
297 0,
298 b"entropy",
299 ));
300 assert!(result.is_err());
301 assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
302 }
303
304 /// Generate RSA attestation key and try to use it for signing RSA key without providing
305 /// attestation challenge. Test should fail to generate a key with error code
306 /// `ATTESTATION_CHALLENGE_MISSING`.
307 #[test]
keystore2_attest_key_fails_missing_challenge()308 fn keystore2_attest_key_fails_missing_challenge() {
309 skip_test_if_no_app_attest_key_feature!();
310
311 let keystore2 = get_keystore_service();
312 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
313 let att_challenge: &[u8] = b"foo";
314
315 // Create RSA attestation key.
316 let attestation_key_metadata =
317 key_generations::generate_attestation_key(&sec_level, Algorithm::RSA, att_challenge)
318 .unwrap();
319
320 let mut cert_chain: Vec<u8> = Vec::new();
321 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
322 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
323 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
324
325 // Try to attest RSA signing key without providing attestation challenge.
326 let sign_key_alias = format!("ksrsa_attested_test_key_missing_challenge{}", getuid());
327 let result = key_generations::map_ks_error(key_generations::generate_rsa_key(
328 &sec_level,
329 Domain::APP,
330 -1,
331 Some(sign_key_alias),
332 &key_generations::KeyParams {
333 key_size: 2048,
334 purpose: vec![KeyPurpose::SIGN, KeyPurpose::VERIFY],
335 padding: Some(PaddingMode::RSA_PKCS1_1_5_SIGN),
336 digest: Some(Digest::SHA_2_256),
337 mgf_digest: None,
338 block_mode: None,
339 att_challenge: None,
340 },
341 Some(&attestation_key_metadata.key),
342 ));
343 assert!(result.is_err());
344 assert_eq!(Error::Km(ErrorCode::ATTESTATION_CHALLENGE_MISSING), result.unwrap_err());
345 }
346
347 /// Generate an asymmetric key which doesn't possess ATTEST_KEY purpose. Try to use this key as
348 /// attestation key while generating RSA key. Test should fail to generate a key with error
349 /// code `INCOMPATIBLE_PURPOSE`.
350 #[test]
keystore2_attest_rsa_key_with_non_attest_key_fails_incompat_purpose_error()351 fn keystore2_attest_rsa_key_with_non_attest_key_fails_incompat_purpose_error() {
352 skip_test_if_no_app_attest_key_feature!();
353
354 let keystore2 = get_keystore_service();
355 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
356 let att_challenge: &[u8] = b"foo";
357
358 let alias = format!("non_attest_key_{}", getuid());
359 let non_attest_key_metadata = key_generations::generate_ec_p256_signing_key(
360 &sec_level,
361 Domain::APP,
362 -1,
363 Some(alias),
364 None,
365 )
366 .unwrap();
367
368 // Try to generate RSA signing key with non-attestation key to sign it.
369 let sign_key_alias = format!("ksrsa_attested_sign_test_key_non_attest_{}", getuid());
370 let result = key_generations::map_ks_error(key_generations::generate_rsa_key(
371 &sec_level,
372 Domain::APP,
373 -1,
374 Some(sign_key_alias),
375 &key_generations::KeyParams {
376 key_size: 2048,
377 purpose: vec![KeyPurpose::SIGN, KeyPurpose::VERIFY],
378 padding: Some(PaddingMode::RSA_PKCS1_1_5_SIGN),
379 digest: Some(Digest::SHA_2_256),
380 mgf_digest: None,
381 block_mode: None,
382 att_challenge: Some(att_challenge.to_vec()),
383 },
384 Some(&non_attest_key_metadata.key),
385 ));
386 assert!(result.is_err());
387 assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
388 }
389
390 /// Generate a symmetric key. Try to use this symmetric key as attestation key while generating RSA
391 /// key. Test should fail to generate a key with response code `INVALID_ARGUMENT`.
392 #[test]
keystore2_attest_rsa_key_with_symmetric_key_fails_sys_error()393 fn keystore2_attest_rsa_key_with_symmetric_key_fails_sys_error() {
394 skip_test_if_no_app_attest_key_feature!();
395
396 let keystore2 = get_keystore_service();
397 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
398 let att_challenge: &[u8] = b"foo";
399
400 let alias = "aes_attest_key";
401 let sym_key_metadata = key_generations::generate_sym_key(
402 &sec_level,
403 Algorithm::AES,
404 128,
405 alias,
406 &PaddingMode::NONE,
407 &BlockMode::ECB,
408 None,
409 )
410 .unwrap();
411
412 // Try to generate RSA signing key with symmetric key as attestation key.
413 let sign_key_alias = format!("ksrsa_attested_sign_test_key_sym_attest_{}", getuid());
414 let result = key_generations::map_ks_error(key_generations::generate_rsa_key(
415 &sec_level,
416 Domain::APP,
417 -1,
418 Some(sign_key_alias),
419 &key_generations::KeyParams {
420 key_size: 2048,
421 purpose: vec![KeyPurpose::SIGN, KeyPurpose::VERIFY],
422 padding: Some(PaddingMode::RSA_PKCS1_1_5_SIGN),
423 digest: Some(Digest::SHA_2_256),
424 mgf_digest: None,
425 block_mode: None,
426 att_challenge: Some(att_challenge.to_vec()),
427 },
428 Some(&sym_key_metadata.key),
429 ));
430 assert!(result.is_err());
431 assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
432 }
433
434 /// Generate RSA attestation key and try to use it as attestation key while generating symmetric
435 /// key. Test should generate symmetric key successfully. Verify that generated symmetric key
436 /// should not have attestation record or certificate.
437 #[test]
keystore2_attest_symmetric_key_fail_sys_error()438 fn keystore2_attest_symmetric_key_fail_sys_error() {
439 skip_test_if_no_app_attest_key_feature!();
440
441 let keystore2 = get_keystore_service();
442 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
443 let att_challenge: &[u8] = b"foo";
444
445 // Create attestation key.
446 let attestation_key_metadata =
447 key_generations::generate_attestation_key(&sec_level, Algorithm::RSA, att_challenge)
448 .unwrap();
449
450 let mut cert_chain: Vec<u8> = Vec::new();
451 cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
452 cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
453 validate_certchain(&cert_chain).expect("Error while validating cert chain.");
454
455 // Generate symmetric key with above generated key as attestation key.
456 let gen_params = authorizations::AuthSetBuilder::new()
457 .no_auth_required()
458 .algorithm(Algorithm::AES)
459 .purpose(KeyPurpose::ENCRYPT)
460 .purpose(KeyPurpose::DECRYPT)
461 .key_size(128)
462 .padding_mode(PaddingMode::NONE)
463 .block_mode(BlockMode::ECB)
464 .attestation_challenge(att_challenge.to_vec());
465
466 let alias = format!("ks_test_sym_key_attest_{}", getuid());
467 let aes_key_metadata = sec_level
468 .generateKey(
469 &KeyDescriptor { domain: Domain::APP, nspace: -1, alias: Some(alias), blob: None },
470 Some(&attestation_key_metadata.key),
471 &gen_params,
472 0,
473 b"entropy",
474 )
475 .unwrap();
476
477 // Should not have public certificate.
478 assert!(aes_key_metadata.certificate.is_none());
479
480 // Should not have an attestation record.
481 assert!(aes_key_metadata.certificateChain.is_none());
482 }
483