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, Digest::Digest, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose,
17 SecurityLevel::SecurityLevel,
18 };
19 use android_system_keystore2::aidl::android::system::keystore2::{
20 Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
21 };
22
23 use keystore2_test_utils::{
24 authorizations, get_keystore_service, key_generations, key_generations::Error,
25 };
26
27 use crate::keystore2_client_test_utils::perform_sample_sign_operation;
28
29 /// Generate HMAC key with given parameters and perform a sample operation using generated key.
create_hmac_key_and_operation( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, alias: &str, key_size: i32, mac_len: i32, min_mac_len: i32, digest: Digest, ) -> Result<(), binder::Status>30 fn create_hmac_key_and_operation(
31 sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
32 alias: &str,
33 key_size: i32,
34 mac_len: i32,
35 min_mac_len: i32,
36 digest: Digest,
37 ) -> Result<(), binder::Status> {
38 let key_metadata =
39 key_generations::generate_hmac_key(sec_level, alias, key_size, min_mac_len, digest)?;
40
41 let op_response = sec_level.createOperation(
42 &key_metadata.key,
43 &authorizations::AuthSetBuilder::new()
44 .purpose(KeyPurpose::SIGN)
45 .digest(digest)
46 .mac_length(mac_len),
47 false,
48 )?;
49
50 assert!(op_response.iOperation.is_some());
51 assert_eq!(
52 Ok(()),
53 key_generations::map_ks_error(perform_sample_sign_operation(
54 &op_response.iOperation.unwrap()
55 ))
56 );
57
58 Ok(())
59 }
60
61 /// Generate HMAC keys with various digest modes [SHA1, SHA_2_224, SHA_2_256, SHA_2_384,
62 /// SHA_2_512]. Create an operation using generated keys. Test should create operations
63 /// successfully.
64 #[test]
keystore2_hmac_key_op_success()65 fn keystore2_hmac_key_op_success() {
66 let digests =
67 [Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512];
68 let min_mac_len = 128;
69 let mac_len = 128;
70 let key_size = 128;
71
72 let keystore2 = get_keystore_service();
73 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
74
75 for digest in digests {
76 let alias = format!("ks_hmac_test_key_{}", digest.0);
77
78 assert_eq!(
79 Ok(()),
80 create_hmac_key_and_operation(
81 &sec_level,
82 &alias,
83 key_size,
84 mac_len,
85 min_mac_len,
86 digest,
87 )
88 );
89 }
90 }
91
92 /// Generate HMAC keys with various key lengths. For invalid key sizes, key generation
93 /// should fail with an error code `UNSUPPORTED_KEY_SIZE`.
94 #[test]
keystore2_hmac_gen_keys_fails_expect_unsupported_key_size()95 fn keystore2_hmac_gen_keys_fails_expect_unsupported_key_size() {
96 let min_mac_len = 256;
97 let digest = Digest::SHA_2_256;
98
99 let keystore2 = get_keystore_service();
100 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
101
102 for key_size in 0..513 {
103 let alias = format!("ks_hmac_test_key_{}", key_size);
104 let result = key_generations::map_ks_error(key_generations::generate_hmac_key(
105 &sec_level,
106 &alias,
107 key_size,
108 min_mac_len,
109 digest,
110 ));
111
112 match result {
113 Ok(_) => {
114 assert!((key_size >= 64 && key_size % 8 == 0));
115 }
116 Err(e) => {
117 assert_eq!(e, Error::Km(ErrorCode::UNSUPPORTED_KEY_SIZE));
118 assert!((key_size < 64 || key_size % 8 != 0), "Unsupported KeySize: {}", key_size);
119 }
120 }
121 }
122 }
123
124 /// Generate HMAC keys with various min-mac-lengths. For invalid min-mac-length, key generation
125 /// should fail with an error code `UNSUPPORTED_MIN_MAC_LENGTH`.
126 #[test]
keystore2_hmac_gen_keys_fails_expect_unsupported_min_mac_length()127 fn keystore2_hmac_gen_keys_fails_expect_unsupported_min_mac_length() {
128 let digest = Digest::SHA_2_256;
129 let key_size = 128;
130
131 let keystore2 = get_keystore_service();
132 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
133
134 for min_mac_len in 0..257 {
135 let alias = format!("ks_hmac_test_key_mml_{}", min_mac_len);
136 match key_generations::map_ks_error(key_generations::generate_hmac_key(
137 &sec_level,
138 &alias,
139 key_size,
140 min_mac_len,
141 digest,
142 )) {
143 Ok(_) => {
144 assert!((min_mac_len >= 64 && min_mac_len % 8 == 0));
145 }
146 Err(e) => {
147 assert_eq!(e, Error::Km(ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH));
148 assert!(
149 (min_mac_len < 64 || min_mac_len % 8 != 0),
150 "Unsupported MinMacLength: {}",
151 min_mac_len
152 );
153 }
154 }
155 }
156 }
157
158 /// Try to generate HMAC key with multiple digests in key authorizations list.
159 /// Test fails to generate a key with multiple digests with an error code `UNSUPPORTED_DIGEST`.
160 #[test]
keystore2_hmac_gen_key_multi_digests_fails_expect_unsupported_digest()161 fn keystore2_hmac_gen_key_multi_digests_fails_expect_unsupported_digest() {
162 let keystore2 = get_keystore_service();
163 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
164
165 let alias = "ks_hmac_test_key_multi_dig";
166 let gen_params = authorizations::AuthSetBuilder::new()
167 .no_auth_required()
168 .algorithm(Algorithm::HMAC)
169 .purpose(KeyPurpose::SIGN)
170 .purpose(KeyPurpose::VERIFY)
171 .key_size(128)
172 .min_mac_length(128)
173 .digest(Digest::SHA1)
174 .digest(Digest::SHA_2_256);
175
176 let result = key_generations::map_ks_error(sec_level.generateKey(
177 &KeyDescriptor {
178 domain: Domain::APP,
179 nspace: -1,
180 alias: Some(alias.to_string()),
181 blob: None,
182 },
183 None,
184 &gen_params,
185 0,
186 b"entropy",
187 ));
188 assert!(result.is_err());
189 assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_DIGEST), result.unwrap_err());
190 }
191
192 /// Try to generate HMAC key without providing digest mode. HMAC key generation with
193 /// no digest should fail with an error code `UNSUPPORTED_DIGEST`.
194 #[test]
keystore2_hmac_gen_key_no_digests_fails_expect_unsupported_digest()195 fn keystore2_hmac_gen_key_no_digests_fails_expect_unsupported_digest() {
196 let keystore2 = get_keystore_service();
197 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
198
199 let alias = "ks_hmac_test_key_no_dig";
200 let gen_params = authorizations::AuthSetBuilder::new()
201 .no_auth_required()
202 .algorithm(Algorithm::HMAC)
203 .purpose(KeyPurpose::SIGN)
204 .purpose(KeyPurpose::VERIFY)
205 .key_size(128)
206 .min_mac_length(128);
207
208 let result = key_generations::map_ks_error(sec_level.generateKey(
209 &KeyDescriptor {
210 domain: Domain::APP,
211 nspace: -1,
212 alias: Some(alias.to_string()),
213 blob: None,
214 },
215 None,
216 &gen_params,
217 0,
218 b"entropy",
219 ));
220 assert!(result.is_err());
221 assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_DIGEST), result.unwrap_err());
222 }
223
224 /// Try to generate a HMAC key with NONE digest mode, it should fail with `UNSUPPORTED_DIGEST`
225 /// error code.
226 #[test]
keystore2_hmac_gen_key_with_none_digest_fails_expect_unsupported_digest()227 fn keystore2_hmac_gen_key_with_none_digest_fails_expect_unsupported_digest() {
228 let min_mac_len = 128;
229 let key_size = 128;
230 let keystore2 = get_keystore_service();
231 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
232
233 let alias = "ks_hmac_test_key_fail";
234 let result = key_generations::map_ks_error(key_generations::generate_hmac_key(
235 &sec_level,
236 alias,
237 key_size,
238 min_mac_len,
239 Digest::NONE,
240 ));
241 assert!(result.is_err());
242 assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_DIGEST), result.unwrap_err());
243 }
244
245 /// Generate HMAC key with min-mac-len of 128 bits for the digest modes Digest::SHA1 and
246 /// Digest::SHA_2_224. Try to create an operation with generated key and mac-length greater than
247 /// digest length. Test should fail to create an operation with an error code
248 /// `UNSUPPORTED_MAC_LENGTH`.
249 #[test]
keystore2_hmac_key_op_with_mac_len_greater_than_digest_len_fail()250 fn keystore2_hmac_key_op_with_mac_len_greater_than_digest_len_fail() {
251 let digests = [Digest::SHA1, Digest::SHA_2_224];
252 let min_mac_len = 128;
253 let mac_len = 256;
254 let key_size = 128;
255
256 let keystore2 = get_keystore_service();
257 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
258
259 for digest in digests {
260 let alias = format!("ks_hmac_test_key_{}", digest.0);
261
262 let result = key_generations::map_ks_error(create_hmac_key_and_operation(
263 &sec_level,
264 &alias,
265 key_size,
266 mac_len,
267 min_mac_len,
268 digest,
269 ));
270
271 assert!(result.is_err());
272 assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_MAC_LENGTH), result.unwrap_err());
273 }
274 }
275
276 /// Generate HMAC key with min-mac-len of 128 bits for the digest modes Digest::SHA1 and
277 /// Digest::SHA_2_224. Try to create an operation with generated key and mac-length less than
278 /// min-mac-length. Test should fail to create an operation with an error code
279 /// `INVALID_MAC_LENGTH`.
280 #[test]
keystore2_hmac_key_op_with_mac_len_less_than_min_mac_len_fail()281 fn keystore2_hmac_key_op_with_mac_len_less_than_min_mac_len_fail() {
282 let digests = [Digest::SHA1, Digest::SHA_2_224];
283 let min_mac_len = 128;
284 let mac_len = 64;
285 let key_size = 128;
286
287 let keystore2 = get_keystore_service();
288 let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
289
290 for digest in digests {
291 let alias = format!("ks_hmac_test_key_{}", digest.0);
292
293 let result = key_generations::map_ks_error(create_hmac_key_and_operation(
294 &sec_level,
295 &alias,
296 key_size,
297 mac_len,
298 min_mac_len,
299 digest,
300 ));
301
302 assert!(result.is_err());
303 assert_eq!(Error::Km(ErrorCode::INVALID_MAC_LENGTH), result.unwrap_err());
304 }
305 }
306