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