• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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