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 3DES key. Create encryption and decryption operations using the generated key.
create_3des_key_and_operation( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, padding_mode: PaddingMode, block_mode: BlockMode, nonce: &mut Option<Vec<u8>>, ) -> Result<(), binder::Status>33 fn create_3des_key_and_operation(
34     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
35     padding_mode: PaddingMode,
36     block_mode: BlockMode,
37     nonce: &mut Option<Vec<u8>>,
38 ) -> Result<(), binder::Status> {
39     let alias = format!("ks_3des_test_key_{}{}", block_mode.0, padding_mode.0);
40 
41     let key_metadata = key_generations::generate_sym_key(
42         sec_level,
43         Algorithm::TRIPLE_DES,
44         168,
45         &alias,
46         &padding_mode,
47         &block_mode,
48         None,
49     )?;
50 
51     // Encrypts `SAMPLE_PLAIN_TEXT` whose length is multiple of DES block size.
52     let cipher_text = perform_sample_sym_key_encrypt_op(
53         sec_level,
54         padding_mode,
55         block_mode,
56         nonce,
57         None,
58         &key_metadata.key,
59     )?;
60     assert!(cipher_text.is_some());
61 
62     let plain_text = perform_sample_sym_key_decrypt_op(
63         sec_level,
64         &cipher_text.unwrap(),
65         padding_mode,
66         block_mode,
67         nonce,
68         None,
69         &key_metadata.key,
70     )
71     .unwrap();
72     assert!(plain_text.is_some());
73     assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
74     Ok(())
75 }
76 
77 /// Generate 3DES keys with various block modes and paddings.
78 ///  - Block Modes: ECB, CBC
79 ///  - Padding Modes: NONE, PKCS7
80 /// Test should generate keys and perform operation successfully.
81 #[test]
keystore2_3des_ecb_cbc_generate_key_success()82 fn keystore2_3des_ecb_cbc_generate_key_success() {
83     let keystore2 = get_keystore_service();
84     let block_modes = [BlockMode::ECB, BlockMode::CBC];
85     let padding_modes = [PaddingMode::PKCS7, PaddingMode::NONE];
86 
87     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
88     for block_mode in block_modes {
89         for padding_mode in padding_modes {
90             assert_eq!(
91                 Ok(()),
92                 create_3des_key_and_operation(&sec_level, padding_mode, block_mode, &mut None)
93             );
94         }
95     }
96 }
97 
98 /// Try to generate 3DES key with invalid key size. Test should fail to generate a key with
99 /// an error code `UNSUPPORTED_KEY_SIZE`.
100 #[test]
keystore2_3des_key_fails_unsupported_key_size()101 fn keystore2_3des_key_fails_unsupported_key_size() {
102     let keystore2 = get_keystore_service();
103     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
104     let alias = "3des_key_test_invalid_1";
105     let invalid_key_size = 128;
106 
107     let result = key_generations::map_ks_error(key_generations::generate_sym_key(
108         &sec_level,
109         Algorithm::TRIPLE_DES,
110         invalid_key_size,
111         alias,
112         &PaddingMode::PKCS7,
113         &BlockMode::CBC,
114         None,
115     ));
116     assert!(result.is_err());
117     assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_KEY_SIZE), result.unwrap_err());
118 }
119 
120 /// Generate a 3DES key without providing padding mode and try to use the generated key to create
121 /// an operation. Test should fail to create an operation with an error code
122 /// `UNSUPPORTED_PADDING_MODE`.
123 #[test]
keystore2_3des_key_fails_missing_padding()124 fn keystore2_3des_key_fails_missing_padding() {
125     let keystore2 = get_keystore_service();
126     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
127     let alias = "3des_key_test_missing_padding";
128 
129     let gen_params = authorizations::AuthSetBuilder::new()
130         .no_auth_required()
131         .algorithm(Algorithm::TRIPLE_DES)
132         .purpose(KeyPurpose::ENCRYPT)
133         .purpose(KeyPurpose::DECRYPT)
134         .key_size(168)
135         .block_mode(BlockMode::ECB);
136 
137     let key_metadata = sec_level
138         .generateKey(
139             &KeyDescriptor {
140                 domain: Domain::APP,
141                 nspace: -1,
142                 alias: Some(alias.to_string()),
143                 blob: None,
144             },
145             None,
146             &gen_params,
147             0,
148             b"entropy",
149         )
150         .unwrap();
151 
152     let op_params = authorizations::AuthSetBuilder::new()
153         .purpose(KeyPurpose::ENCRYPT)
154         .block_mode(BlockMode::ECB);
155 
156     let result = key_generations::map_ks_error(sec_level.createOperation(
157         &key_metadata.key,
158         &op_params,
159         false,
160     ));
161     assert!(result.is_err());
162     assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_PADDING_MODE), result.unwrap_err());
163 }
164 
165 /// Generate a 3DES key with padding mode NONE. Try to encrypt a text whose length isn't a
166 /// multiple of the DES block size.
167 #[test]
keystore2_3des_key_encrypt_fails_invalid_input_length()168 fn keystore2_3des_key_encrypt_fails_invalid_input_length() {
169     let keystore2 = get_keystore_service();
170     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
171     let alias = "3des_key_test_invalid_input_len";
172 
173     let key_metadata = key_generations::generate_sym_key(
174         &sec_level,
175         Algorithm::TRIPLE_DES,
176         168,
177         alias,
178         &PaddingMode::NONE,
179         &BlockMode::ECB,
180         None,
181     )
182     .unwrap();
183 
184     let op_params = authorizations::AuthSetBuilder::new()
185         .purpose(KeyPurpose::ENCRYPT)
186         .padding_mode(PaddingMode::NONE)
187         .block_mode(BlockMode::ECB);
188 
189     let op_response = sec_level
190         .createOperation(&key_metadata.key, &op_params, false)
191         .expect("Error in creation of operation using rebound key.");
192     assert!(op_response.iOperation.is_some());
193 
194     let op = op_response.iOperation.unwrap();
195     // 3DES expects input should be multiple of DES block size (64-bits) length. Try with invalid
196     // length of input.
197     let invalid_block_size_msg = b"my message 111";
198     let result = key_generations::map_ks_error(op.finish(Some(invalid_block_size_msg), None));
199     assert!(result.is_err());
200     assert_eq!(Error::Km(ErrorCode::INVALID_INPUT_LENGTH), result.unwrap_err());
201 }
202 
203 /// Try to generate 3DES key with BlockMode::CTR. Test should fail to create an operation with an
204 /// error code `UNSUPPORTED_BLOCK_MODE`.
205 #[test]
keystore2_3des_key_fails_unsupported_block_mode()206 fn keystore2_3des_key_fails_unsupported_block_mode() {
207     let keystore2 = get_keystore_service();
208     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
209 
210     let result = key_generations::map_ks_error(create_3des_key_and_operation(
211         &sec_level,
212         PaddingMode::NONE,
213         BlockMode::CTR,
214         &mut None,
215     ));
216     assert!(result.is_err());
217     assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_BLOCK_MODE), result.unwrap_err());
218 }
219