• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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