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