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