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