• 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 crate::keystore2_client_test_utils::{
16     perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
17 };
18 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
19     Algorithm::Algorithm, BlockMode::BlockMode, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose,
20     PaddingMode::PaddingMode,
21 };
22 use android_system_keystore2::aidl::android::system::keystore2::{
23     Domain::Domain, KeyDescriptor::KeyDescriptor,
24 };
25 use keystore2_test_utils::{authorizations, key_generations, key_generations::Error, SecLevel};
26 
27 /// Generate a AES key. Create encrypt and decrypt operations using the generated key.
create_aes_key_and_operation( sl: &SecLevel, key_size: i32, padding_mode: PaddingMode, block_mode: BlockMode, mac_len: Option<i32>, min_mac_len: Option<i32>, nonce: &mut Option<Vec<u8>>, ) -> Result<(), binder::Status>28 fn create_aes_key_and_operation(
29     sl: &SecLevel,
30     key_size: i32,
31     padding_mode: PaddingMode,
32     block_mode: BlockMode,
33     mac_len: Option<i32>,
34     min_mac_len: Option<i32>,
35     nonce: &mut Option<Vec<u8>>,
36 ) -> Result<(), binder::Status> {
37     let alias = format!("ks_aes_test_key_{}{}{}", key_size, block_mode.0, padding_mode.0);
38 
39     let key_metadata = key_generations::generate_sym_key(
40         sl,
41         Algorithm::AES,
42         key_size,
43         &alias,
44         &padding_mode,
45         &block_mode,
46         min_mac_len,
47     )?;
48 
49     let cipher_text = perform_sample_sym_key_encrypt_op(
50         &sl.binder,
51         padding_mode,
52         block_mode,
53         nonce,
54         mac_len,
55         &key_metadata.key,
56     )?;
57 
58     assert!(cipher_text.is_some());
59 
60     let plain_text = perform_sample_sym_key_decrypt_op(
61         &sl.binder,
62         &cipher_text.unwrap(),
63         padding_mode,
64         block_mode,
65         nonce,
66         mac_len,
67         &key_metadata.key,
68     )
69     .unwrap();
70     assert!(plain_text.is_some());
71     assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
72     Ok(())
73 }
74 
75 /// Generate AES keys with various block modes and paddings.
76 ///  - Block Modes: ECB, CBC
77 ///  - Padding Modes: NONE, PKCS7
78 ///
79 /// Test should generate keys and perform operation successfully.
80 #[test]
keystore2_aes_ecb_cbc_generate_key()81 fn keystore2_aes_ecb_cbc_generate_key() {
82     let key_sizes = [128, 256];
83     let block_modes = [BlockMode::ECB, BlockMode::CBC];
84     let padding_modes = [PaddingMode::PKCS7, PaddingMode::NONE];
85 
86     let sl = SecLevel::tee();
87     for key_size in key_sizes {
88         for block_mode in block_modes {
89             for padding_mode in padding_modes {
90                 assert_eq!(
91                     Ok(()),
92                     create_aes_key_and_operation(
93                         &sl,
94                         key_size,
95                         padding_mode,
96                         block_mode,
97                         None,
98                         None,
99                         &mut None,
100                     )
101                 );
102             }
103         }
104     }
105 }
106 
107 /// Generate AES keys with -
108 ///  - Block Modes: `CTR, GCM`
109 ///  - Padding Modes: `NONE`
110 ///
111 /// Test should generate keys and perform operation successfully.
112 #[test]
keystore2_aes_ctr_gcm_generate_key_success()113 fn keystore2_aes_ctr_gcm_generate_key_success() {
114     let key_sizes = [128, 256];
115     let key_params = [(BlockMode::CTR, None, None), (BlockMode::GCM, Some(128), Some(128))];
116     let sl = SecLevel::tee();
117 
118     for key_size in key_sizes {
119         for (block_mode, mac_len, min_mac_len) in key_params {
120             let result = key_generations::map_ks_error(create_aes_key_and_operation(
121                 &sl,
122                 key_size,
123                 PaddingMode::NONE,
124                 block_mode,
125                 mac_len,
126                 min_mac_len,
127                 &mut None,
128             ));
129 
130             assert_eq!(Ok(()), result);
131         } // End of block mode.
132     } // End of key size.
133 }
134 
135 /// Generate AES keys with -
136 ///  - Block Modes: `CTR, GCM`
137 ///  - Padding Modes: `PKCS7`
138 ///
139 /// Try to create an operation using generated keys, test should fail to create an operation
140 /// with an error code `INCOMPATIBLE_PADDING_MODE`.
141 #[test]
keystore2_aes_ctr_gcm_generate_key_fails_incompatible()142 fn keystore2_aes_ctr_gcm_generate_key_fails_incompatible() {
143     let key_sizes = [128, 256];
144     let key_params = [(BlockMode::CTR, None, None), (BlockMode::GCM, Some(128), Some(128))];
145     let sl = SecLevel::tee();
146 
147     for key_size in key_sizes {
148         for (block_mode, mac_len, min_mac_len) in key_params {
149             let result = key_generations::map_ks_error(create_aes_key_and_operation(
150                 &sl,
151                 key_size,
152                 PaddingMode::PKCS7,
153                 block_mode,
154                 mac_len,
155                 min_mac_len,
156                 &mut None,
157             ));
158 
159             assert!(result.is_err());
160             assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PADDING_MODE), result.unwrap_err());
161         } // End of block mode.
162     } // End of key size.
163 }
164 
165 /// Try to generate AES key with invalid key size. Test should fail to generate a key with
166 /// an error code `UNSUPPORTED_KEY_SIZE`.
167 #[test]
keystore2_aes_key_fails_unsupported_key_size()168 fn keystore2_aes_key_fails_unsupported_key_size() {
169     let sl = SecLevel::tee();
170     let alias = "aes_key_test_invalid_1";
171 
172     let result = key_generations::map_ks_error(key_generations::generate_sym_key(
173         &sl,
174         Algorithm::AES,
175         1024,
176         alias,
177         &PaddingMode::NONE,
178         &BlockMode::ECB,
179         None,
180     ));
181     assert!(result.is_err());
182     assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_KEY_SIZE), result.unwrap_err());
183 }
184 
185 /// Try to generate AES key with GCM block mode without providing `MIN_MAC_LENGTH`.
186 /// Test should fail to generate a key with an error code `MISSING_MIN_MAC_LENGTH`.
187 #[test]
keystore2_aes_gcm_key_fails_missing_min_mac_len()188 fn keystore2_aes_gcm_key_fails_missing_min_mac_len() {
189     let sl = SecLevel::tee();
190     let alias = "aes_key_test_invalid_1";
191 
192     let result = key_generations::map_ks_error(key_generations::generate_sym_key(
193         &sl,
194         Algorithm::AES,
195         128,
196         alias,
197         &PaddingMode::NONE,
198         &BlockMode::GCM,
199         None,
200     ));
201     assert!(result.is_err());
202     assert_eq!(Error::Km(ErrorCode::MISSING_MIN_MAC_LENGTH), result.unwrap_err());
203 }
204 
205 /// Try to create an operation using AES key with multiple block modes. Test should fail to create
206 /// an operation.
207 #[test]
keystore2_aes_key_op_fails_multi_block_modes()208 fn keystore2_aes_key_op_fails_multi_block_modes() {
209     let sl = SecLevel::tee();
210     let alias = "aes_key_test_invalid_1";
211 
212     let gen_params = authorizations::AuthSetBuilder::new()
213         .no_auth_required()
214         .algorithm(Algorithm::AES)
215         .purpose(KeyPurpose::ENCRYPT)
216         .purpose(KeyPurpose::DECRYPT)
217         .key_size(128)
218         .block_mode(BlockMode::ECB)
219         .block_mode(BlockMode::CBC)
220         .padding_mode(PaddingMode::NONE);
221 
222     let key_metadata = sl
223         .binder
224         .generateKey(
225             &KeyDescriptor {
226                 domain: Domain::APP,
227                 nspace: -1,
228                 alias: Some(alias.to_string()),
229                 blob: None,
230             },
231             None,
232             &gen_params,
233             0,
234             b"entropy",
235         )
236         .unwrap();
237 
238     let op_params = authorizations::AuthSetBuilder::new()
239         .purpose(KeyPurpose::ENCRYPT)
240         .block_mode(BlockMode::ECB)
241         .block_mode(BlockMode::CBC)
242         .padding_mode(PaddingMode::NONE);
243 
244     let result = key_generations::map_ks_error(sl.binder.createOperation(
245         &key_metadata.key,
246         &op_params,
247         false,
248     ));
249     assert!(result.is_err());
250     assert!(matches!(
251         result.unwrap_err(),
252         Error::Km(ErrorCode::INCOMPATIBLE_BLOCK_MODE)
253             | Error::Km(ErrorCode::UNSUPPORTED_BLOCK_MODE)
254             | Error::Km(ErrorCode::INVALID_ARGUMENT)
255     ));
256 }
257 
258 /// Try to create an operation using AES key with multiple padding modes. Test should fail to create
259 /// an operation.
260 #[test]
keystore2_aes_key_op_fails_multi_padding_modes()261 fn keystore2_aes_key_op_fails_multi_padding_modes() {
262     let sl = SecLevel::tee();
263     let alias = "aes_key_test_invalid_1";
264 
265     let gen_params = authorizations::AuthSetBuilder::new()
266         .no_auth_required()
267         .algorithm(Algorithm::AES)
268         .purpose(KeyPurpose::ENCRYPT)
269         .purpose(KeyPurpose::DECRYPT)
270         .key_size(128)
271         .block_mode(BlockMode::ECB)
272         .padding_mode(PaddingMode::PKCS7)
273         .padding_mode(PaddingMode::NONE);
274 
275     let key_metadata = sl
276         .binder
277         .generateKey(
278             &KeyDescriptor {
279                 domain: Domain::APP,
280                 nspace: -1,
281                 alias: Some(alias.to_string()),
282                 blob: None,
283             },
284             None,
285             &gen_params,
286             0,
287             b"entropy",
288         )
289         .unwrap();
290 
291     let op_params = authorizations::AuthSetBuilder::new()
292         .purpose(KeyPurpose::ENCRYPT)
293         .block_mode(BlockMode::ECB)
294         .padding_mode(PaddingMode::PKCS7)
295         .padding_mode(PaddingMode::NONE);
296 
297     let result = key_generations::map_ks_error(sl.binder.createOperation(
298         &key_metadata.key,
299         &op_params,
300         false,
301     ));
302     assert!(result.is_err());
303     assert!(matches!(
304         result.unwrap_err(),
305         Error::Km(ErrorCode::INCOMPATIBLE_PADDING_MODE)
306             | Error::Km(ErrorCode::UNSUPPORTED_PADDING_MODE)
307             | Error::Km(ErrorCode::INVALID_ARGUMENT)
308     ));
309 }
310 
311 /// Generate a AES-ECB key with unpadded mode. Try to create an operation using generated key
312 /// with PKCS7 padding mode. Test should fail to create an Operation with
313 /// `INCOMPATIBLE_PADDING_MODE` error code.
314 #[test]
keystore2_aes_key_op_fails_incompatible_padding()315 fn keystore2_aes_key_op_fails_incompatible_padding() {
316     let sl = SecLevel::tee();
317     let alias = "aes_key_test_invalid_1";
318 
319     let key_metadata = key_generations::generate_sym_key(
320         &sl,
321         Algorithm::AES,
322         128,
323         alias,
324         &PaddingMode::NONE,
325         &BlockMode::ECB,
326         None,
327     )
328     .unwrap();
329 
330     let result = key_generations::map_ks_error(perform_sample_sym_key_encrypt_op(
331         &sl.binder,
332         PaddingMode::PKCS7,
333         BlockMode::ECB,
334         &mut None,
335         None,
336         &key_metadata.key,
337     ));
338     assert!(result.is_err());
339     assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PADDING_MODE), result.unwrap_err());
340 }
341 
342 /// Generate a AES-ECB key with unpadded mode. Try to create an operation using generated key
343 /// with CBC block mode. Test should fail to create an Operation with
344 /// `INCOMPATIBLE_BLOCK_MODE` error code.
345 #[test]
keystore2_aes_key_op_fails_incompatible_blockmode()346 fn keystore2_aes_key_op_fails_incompatible_blockmode() {
347     let sl = SecLevel::tee();
348     let alias = "aes_key_test_invalid_1";
349 
350     let key_metadata = key_generations::generate_sym_key(
351         &sl,
352         Algorithm::AES,
353         128,
354         alias,
355         &PaddingMode::NONE,
356         &BlockMode::ECB,
357         None,
358     )
359     .unwrap();
360 
361     let result = key_generations::map_ks_error(perform_sample_sym_key_encrypt_op(
362         &sl.binder,
363         PaddingMode::NONE,
364         BlockMode::CBC,
365         &mut None,
366         None,
367         &key_metadata.key,
368     ));
369     assert!(result.is_err());
370     assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_BLOCK_MODE), result.unwrap_err());
371 }
372 
373 /// Generate a AES-GCM key with `MIN_MAC_LENGTH`. Try to create an operation using this
374 /// generated key without providing `MAC_LENGTH`. Test should fail to create an operation with
375 /// `MISSING_MAC_LENGTH` error code.
376 #[test]
keystore2_aes_gcm_op_fails_missing_mac_len()377 fn keystore2_aes_gcm_op_fails_missing_mac_len() {
378     let sl = SecLevel::tee();
379     let mac_len = None;
380     let min_mac_len = Some(128);
381 
382     let result = key_generations::map_ks_error(create_aes_key_and_operation(
383         &sl,
384         128,
385         PaddingMode::NONE,
386         BlockMode::GCM,
387         mac_len,
388         min_mac_len,
389         &mut None,
390     ));
391     assert!(result.is_err());
392 
393     let e = result.unwrap_err();
394     assert!(
395         e == Error::Km(ErrorCode::MISSING_MAC_LENGTH)
396             || e == Error::Km(ErrorCode::UNSUPPORTED_MAC_LENGTH)
397     );
398 }
399 
400 /// Generate a AES-GCM key with `MIN_MAC_LENGTH`. Try to create an operation using this
401 /// generated key and  provide `MAC_LENGTH` < key's `MIN_MAC_LENGTH`. Test should fail to create
402 /// an operation with `INVALID_MAC_LENGTH` error code.
403 #[test]
keystore2_aes_gcm_op_fails_invalid_mac_len()404 fn keystore2_aes_gcm_op_fails_invalid_mac_len() {
405     let sl = SecLevel::tee();
406     let mac_len = Some(96);
407     let min_mac_len = Some(104);
408 
409     let result = key_generations::map_ks_error(create_aes_key_and_operation(
410         &sl,
411         128,
412         PaddingMode::NONE,
413         BlockMode::GCM,
414         mac_len,
415         min_mac_len,
416         &mut None,
417     ));
418     assert!(result.is_err());
419     assert_eq!(Error::Km(ErrorCode::INVALID_MAC_LENGTH), result.unwrap_err());
420 }
421 
422 /// Generate a AES-GCM key with `MIN_MAC_LENGTH`. Try to create an operation using this
423 /// generated key and  provide `MAC_LENGTH` > 128. Test should fail to create an operation with
424 /// `UNSUPPORTED_MAC_LENGTH` error code.
425 #[test]
keystore2_aes_gcm_op_fails_unsupported_mac_len()426 fn keystore2_aes_gcm_op_fails_unsupported_mac_len() {
427     let sl = SecLevel::tee();
428 
429     let result = key_generations::map_ks_error(create_aes_key_and_operation(
430         &sl,
431         128,
432         PaddingMode::NONE,
433         BlockMode::GCM,
434         Some(256),
435         Some(128),
436         &mut None,
437     ));
438     assert!(result.is_err());
439     assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_MAC_LENGTH), result.unwrap_err());
440 }
441 
442 /// Generate a AES-CBC-PKCS7 key without `CALLER_NONCE` authorization. Try to set nonce while
443 /// creating an operation using this generated key. Test should fail to create an operation with
444 /// `CALLER_NONCE_PROHIBITED` error code.
445 #[test]
keystore2_aes_key_op_fails_nonce_prohibited()446 fn keystore2_aes_key_op_fails_nonce_prohibited() {
447     let sl = SecLevel::tee();
448     let alias = "aes_key_test_nonce_1";
449     let mut nonce = Some(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
450 
451     let key_metadata = key_generations::generate_sym_key(
452         &sl,
453         Algorithm::AES,
454         128,
455         alias,
456         &PaddingMode::PKCS7,
457         &BlockMode::CBC,
458         None,
459     )
460     .unwrap();
461 
462     let result = key_generations::map_ks_error(perform_sample_sym_key_encrypt_op(
463         &sl.binder,
464         PaddingMode::NONE,
465         BlockMode::CBC,
466         &mut nonce,
467         None,
468         &key_metadata.key,
469     ));
470     assert!(result.is_err());
471     assert_eq!(Error::Km(ErrorCode::CALLER_NONCE_PROHIBITED), result.unwrap_err());
472 }
473