xref: /aosp_15_r20/system/security/keystore2/tests/keystore2_client_list_entries_tests.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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::{delete_all_entries, delete_app_key, verify_aliases};
16 use android_system_keystore2::aidl::android::system::keystore2::{
17     Domain::Domain, IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor,
18     KeyPermission::KeyPermission, ResponseCode::ResponseCode,
19 };
20 use keystore2_test_utils::{
21     get_keystore_service, key_generations, key_generations::Error, run_as, SecLevel,
22 };
23 use nix::unistd::getuid;
24 use rustutils::users::AID_USER_OFFSET;
25 use std::collections::HashSet;
26 use std::fmt::Write;
27 
28 /// Try to find a key with given key parameters using `listEntries` API.
key_alias_exists( keystore2: &binder::Strong<dyn IKeystoreService>, domain: Domain, nspace: i64, alias: String, ) -> bool29 fn key_alias_exists(
30     keystore2: &binder::Strong<dyn IKeystoreService>,
31     domain: Domain,
32     nspace: i64,
33     alias: String,
34 ) -> bool {
35     let key_descriptors = keystore2.listEntries(domain, nspace).unwrap();
36     let alias_count = key_descriptors
37         .into_iter()
38         .map(|key| key.alias.unwrap())
39         .filter(|key_alias| *key_alias == alias)
40         .count();
41 
42     alias_count != 0
43 }
44 
45 /// List key entries with domain as SELINUX and APP.
46 /// 1. Generate a key with domain as SELINUX and find this key entry in list of keys retrieved from
47 ///    `listEntries` with domain SELINUX. Test should be able find this key entry successfully.
48 /// 2. Grant above generated Key to a user.
49 /// 3. In a user context, generate a new key with domain as APP. Try to list the key entries with
50 ///    domain APP. Test should find only one key entry that should be the key generated in user
51 ///    context. GRANT keys shouldn't be part of this list.
52 #[test]
keystore2_list_entries_success()53 fn keystore2_list_entries_success() {
54     const USER_ID: u32 = 91;
55     const APPLICATION_ID: u32 = 10006;
56     static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
57     static GRANTEE_GID: u32 = GRANTEE_UID;
58 
59     let gen_key_fn = || {
60         let sl = SecLevel::tee();
61 
62         let alias = format!("list_entries_grant_key1_{}", getuid());
63 
64         // Make sure there is no key exist with this `alias` in `SELINUX` domain and
65         // `SELINUX_SHELL_NAMESPACE` namespace.
66         if key_alias_exists(
67             &sl.keystore2,
68             Domain::SELINUX,
69             key_generations::SELINUX_SHELL_NAMESPACE,
70             alias.to_string(),
71         ) {
72             sl.keystore2
73                 .deleteKey(&KeyDescriptor {
74                     domain: Domain::SELINUX,
75                     nspace: key_generations::SELINUX_SHELL_NAMESPACE,
76                     alias: Some(alias.to_string()),
77                     blob: None,
78                 })
79                 .unwrap();
80         }
81 
82         // Generate a key with above defined `alias`.
83         let key_metadata = key_generations::generate_ec_p256_signing_key(
84             &sl,
85             Domain::SELINUX,
86             key_generations::SELINUX_SHELL_NAMESPACE,
87             Some(alias.to_string()),
88             None,
89         )
90         .unwrap();
91 
92         // Verify that above generated key entry is listed with domain SELINUX and
93         // namespace SELINUX_SHELL_NAMESPACE
94         assert!(key_alias_exists(
95             &sl.keystore2,
96             Domain::SELINUX,
97             key_generations::SELINUX_SHELL_NAMESPACE,
98             alias,
99         ));
100 
101         // Grant a key with GET_INFO permission.
102         let access_vector = KeyPermission::GET_INFO.0;
103         sl.keystore2
104             .grant(&key_metadata.key, GRANTEE_UID.try_into().unwrap(), access_vector)
105             .unwrap();
106     };
107 
108     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
109     // `--test-threads=1`), and nothing yet done with binder.
110     unsafe { run_as::run_as_root(gen_key_fn) };
111 
112     // In user context validate list of key entries associated with it.
113     let list_keys_fn = move || {
114         let sl = SecLevel::tee();
115         let alias = format!("list_entries_success_key{}", getuid());
116 
117         let key_metadata = key_generations::generate_ec_p256_signing_key(
118             &sl,
119             Domain::APP,
120             -1,
121             Some(alias.to_string()),
122             None,
123         )
124         .unwrap();
125 
126         // Make sure there is only one existing key entry and that should be the same key
127         // generated in this user context. Granted key shouldn't be included in this list.
128         let key_descriptors = sl.keystore2.listEntries(Domain::APP, -1).unwrap();
129         assert_eq!(1, key_descriptors.len());
130 
131         let key = key_descriptors.first().unwrap();
132         assert_eq!(key.alias, Some(alias));
133         assert_eq!(key.nspace, GRANTEE_UID.try_into().unwrap());
134         assert_eq!(key.domain, Domain::APP);
135 
136         sl.keystore2.deleteKey(&key_metadata.key).unwrap();
137 
138         let key_descriptors = sl.keystore2.listEntries(Domain::APP, -1).unwrap();
139         assert_eq!(0, key_descriptors.len());
140     };
141 
142     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
143     // `--test-threads=1`), and nothing yet done with binder.
144     unsafe { run_as::run_as_app(GRANTEE_UID, GRANTEE_GID, list_keys_fn) };
145 }
146 
147 /// Try to list the key entries with domain SELINUX from user context where user doesn't possesses
148 /// `GET_INFO` permission for specified namespace. Test should fail to list key entries with error
149 /// response code `PERMISSION_DENIED`.
150 #[test]
keystore2_list_entries_fails_perm_denied()151 fn keystore2_list_entries_fails_perm_denied() {
152     let auid = 91 * AID_USER_OFFSET + 10001;
153     let agid = 91 * AID_USER_OFFSET + 10001;
154     let list_keys_fn = move || {
155         let keystore2 = get_keystore_service();
156 
157         let result = key_generations::map_ks_error(
158             keystore2.listEntries(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE),
159         );
160         assert!(result.is_err());
161         assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
162     };
163 
164     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
165     // `--test-threads=1`), and nothing yet done with binder.
166     unsafe { run_as::run_as_app(auid, agid, list_keys_fn) };
167 }
168 
169 /// Try to list key entries with domain BLOB. Test should fail with error repose code
170 /// `INVALID_ARGUMENT`.
171 #[test]
keystore2_list_entries_fails_invalid_arg()172 fn keystore2_list_entries_fails_invalid_arg() {
173     let keystore2 = get_keystore_service();
174 
175     let result = key_generations::map_ks_error(
176         keystore2.listEntries(Domain::BLOB, key_generations::SELINUX_SHELL_NAMESPACE),
177     );
178     assert!(result.is_err());
179     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
180 }
181 
182 /// Import large number of Keystore entries with long aliases and try to list aliases
183 /// of all the entries in the keystore.
184 #[test]
keystore2_list_entries_with_long_aliases_success()185 fn keystore2_list_entries_with_long_aliases_success() {
186     const USER_ID: u32 = 92;
187     const APPLICATION_ID: u32 = 10002;
188     static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
189     static CLIENT_GID: u32 = CLIENT_UID;
190 
191     let import_keys_fn = || {
192         let sl = SecLevel::tee();
193 
194         // Make sure there are no keystore entries exist before adding new entries.
195         let key_descriptors = sl.keystore2.listEntries(Domain::APP, -1).unwrap();
196         if !key_descriptors.is_empty() {
197             key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
198                 delete_app_key(&sl.keystore2, &alias).unwrap();
199             });
200         }
201 
202         let mut imported_key_aliases = HashSet::new();
203 
204         // Import 100 keys with aliases of length 6000.
205         for count in 1..101 {
206             let mut alias = String::new();
207             write!(alias, "{}_{}", "X".repeat(6000), count).unwrap();
208             imported_key_aliases.insert(alias.clone());
209 
210             let result = key_generations::import_aes_key(&sl, Domain::APP, -1, Some(alias));
211             assert!(result.is_ok());
212         }
213 
214         // b/222287335 Limiting Keystore `listEntries` API to return subset of the Keystore
215         // entries to avoid running out of binder buffer space.
216         // To verify that all the imported key aliases are present in Keystore,
217         //  - get the list of entries from Keystore
218         //  - check whether the retrieved key entries list is a subset of imported key aliases
219         //  - delete this subset of keystore entries from Keystore as well as from imported
220         //    list of key aliases
221         //  - continue above steps till it cleanup all the imported keystore entries.
222         while !imported_key_aliases.is_empty() {
223             let key_descriptors = sl.keystore2.listEntries(Domain::APP, -1).unwrap();
224 
225             // Check retrieved key entries list is a subset of imported keys list.
226             assert!(key_descriptors
227                 .iter()
228                 .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
229 
230             // Delete the listed key entries from Keystore as well as from imported keys list.
231             key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
232                 delete_app_key(&sl.keystore2, &alias).unwrap();
233                 assert!(imported_key_aliases.remove(&alias));
234             });
235         }
236 
237         assert!(imported_key_aliases.is_empty());
238     };
239 
240     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
241     // `--test-threads=1`), and nothing yet done with binder.
242     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, import_keys_fn) };
243 }
244 
245 /// Import large number of Keystore entries with long aliases such that the
246 /// aliases list would exceed the binder transaction size limit.
247 /// Try to list aliases of all the entries in the keystore using `listEntriesBatched` API.
248 #[test]
keystore2_list_entries_batched_with_long_aliases_success()249 fn keystore2_list_entries_batched_with_long_aliases_success() {
250     const USER_ID: u32 = 92;
251     const APPLICATION_ID: u32 = 10002;
252     static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
253     static CLIENT_GID: u32 = CLIENT_UID;
254 
255     let import_keys_fn = || {
256         let sl = SecLevel::tee();
257 
258         // Make sure there are no keystore entries exist before adding new entries.
259         delete_all_entries(&sl.keystore2);
260 
261         // Import 100 keys with aliases of length 6000.
262         let mut imported_key_aliases =
263             key_generations::import_aes_keys(&sl, "X".repeat(6000), 1..101).unwrap();
264         assert_eq!(
265             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
266             100,
267             "Error while importing keys"
268         );
269 
270         let mut start_past_alias = None;
271         let mut alias;
272         while !imported_key_aliases.is_empty() {
273             let key_descriptors =
274                 sl.keystore2.listEntriesBatched(Domain::APP, -1, start_past_alias).unwrap();
275 
276             // Check retrieved key entries list is a subset of imported keys list.
277             assert!(key_descriptors
278                 .iter()
279                 .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
280 
281             alias = key_descriptors.last().unwrap().alias.clone().unwrap();
282             start_past_alias = Some(alias.as_ref());
283             // Delete the listed key entries from imported keys list.
284             key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
285                 assert!(imported_key_aliases.remove(&alias));
286             });
287         }
288 
289         assert!(imported_key_aliases.is_empty());
290         delete_all_entries(&sl.keystore2);
291         assert_eq!(
292             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
293             0,
294             "Error while doing cleanup"
295         );
296     };
297 
298     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
299     // `--test-threads=1`), and nothing yet done with binder.
300     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, import_keys_fn) };
301 }
302 
303 /// Import keys from multiple processes with same user context and try to list the keystore entries
304 /// using `listEntriesBatched` API.
305 ///  - Create two processes sharing user-id.
306 ///  - From process-1, import 3 keys and try to list the keys using `listEntriesBatched`
307 ///    without `startingPastAlias`, it should list all the 3 entries.
308 ///  - From process-2, import another 5 keys and try to list the keys using `listEntriesBatched`
309 ///    with the alias of the last key listed in process-1 as `startingPastAlias`. It should list
310 ///    all the entries whose alias is greater than the provided `startingPastAlias`.
311 ///  - From process-2 try to list all entries accessible to it by using `listEntriesBatched` with
312 ///    `startingPastAlias` as None. It should list all the keys imported in process-1 and process-2.
313 #[test]
keystore2_list_entries_batched_with_multi_procs_success()314 fn keystore2_list_entries_batched_with_multi_procs_success() {
315     const USER_ID: u32 = 92;
316     const APPLICATION_ID: u32 = 10002;
317     static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
318     static CLIENT_GID: u32 = CLIENT_UID;
319     static ALIAS_PREFIX: &str = "key_test_batch_list";
320 
321     let import_keys_fn = || {
322         let sl = SecLevel::tee();
323 
324         // Make sure there are no keystore entries exist before adding new entries.
325         delete_all_entries(&sl.keystore2);
326 
327         // Import 3 keys with below aliases -
328         // [key_test_batch_list_1, key_test_batch_list_2, key_test_batch_list_3]
329         let imported_key_aliases =
330             key_generations::import_aes_keys(&sl, ALIAS_PREFIX.to_string(), 1..4).unwrap();
331         assert_eq!(
332             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
333             3,
334             "Error while importing keys"
335         );
336 
337         // List all entries in keystore for this user-id.
338         let key_descriptors = sl.keystore2.listEntriesBatched(Domain::APP, -1, None).unwrap();
339         assert_eq!(key_descriptors.len(), 3);
340 
341         // Makes sure all listed aliases are matching with imported keys aliases.
342         assert!(key_descriptors
343             .iter()
344             .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
345     };
346 
347     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
348     // `--test-threads=1`), and nothing yet done with binder.
349     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, import_keys_fn) };
350 
351     let import_more_fn = || {
352         let sl = SecLevel::tee();
353 
354         // Import another 5 keys with below aliases -
355         // [ key_test_batch_list_4, key_test_batch_list_5, key_test_batch_list_6,
356         //   key_test_batch_list_7, key_test_batch_list_8 ]
357         let mut imported_key_aliases =
358             key_generations::import_aes_keys(&sl, ALIAS_PREFIX.to_string(), 4..9).unwrap();
359 
360         // Above context already 3 keys are imported, in this context 5 keys are imported,
361         // total 8 keystore entries are expected to be present in Keystore for this user-id.
362         assert_eq!(
363             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
364             8,
365             "Error while importing keys"
366         );
367 
368         // List keystore entries with `start_past_alias` as "key_test_batch_list_3".
369         // `listEntriesBatched` should list all the keystore entries with
370         // alias > "key_test_batch_list_3".
371         let key_descriptors = sl
372             .keystore2
373             .listEntriesBatched(Domain::APP, -1, Some("key_test_batch_list_3"))
374             .unwrap();
375         assert_eq!(key_descriptors.len(), 5);
376 
377         // Make sure above listed aliases are matching with imported keys aliases.
378         assert!(key_descriptors
379             .iter()
380             .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
381 
382         // List all keystore entries with `start_past_alias` as `None`.
383         // `listEntriesBatched` should list all the keystore entries.
384         let key_descriptors = sl.keystore2.listEntriesBatched(Domain::APP, -1, None).unwrap();
385         assert_eq!(key_descriptors.len(), 8);
386 
387         // Include previously imported keys aliases as well
388         imported_key_aliases.insert(ALIAS_PREFIX.to_owned() + "_1");
389         imported_key_aliases.insert(ALIAS_PREFIX.to_owned() + "_2");
390         imported_key_aliases.insert(ALIAS_PREFIX.to_owned() + "_3");
391 
392         // Make sure all the above listed aliases are matching with imported keys aliases.
393         assert!(key_descriptors
394             .iter()
395             .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
396 
397         delete_all_entries(&sl.keystore2);
398         assert_eq!(
399             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
400             0,
401             "Error while doing cleanup"
402         );
403     };
404 
405     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
406     // `--test-threads=1`), and nothing yet done with binder.
407     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, import_more_fn) };
408 }
409 
410 #[test]
keystore2_list_entries_batched_with_empty_keystore_success()411 fn keystore2_list_entries_batched_with_empty_keystore_success() {
412     const USER_ID: u32 = 92;
413     const APPLICATION_ID: u32 = 10002;
414     static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
415     static CLIENT_GID: u32 = CLIENT_UID;
416 
417     let list_keys_fn = || {
418         let keystore2 = get_keystore_service();
419 
420         // Make sure there are no keystore entries exist before adding new entries.
421         delete_all_entries(&keystore2);
422 
423         // List all entries in keystore for this user-id, pass startingPastAlias = None
424         let key_descriptors = keystore2.listEntriesBatched(Domain::APP, -1, None).unwrap();
425         assert_eq!(key_descriptors.len(), 0);
426 
427         // List all entries in keystore for this user-id, pass startingPastAlias = <random value>
428         let key_descriptors =
429             keystore2.listEntriesBatched(Domain::APP, -1, Some("startingPastAlias")).unwrap();
430         assert_eq!(key_descriptors.len(), 0);
431     };
432 
433     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
434     // `--test-threads=1`), and nothing yet done with binder.
435     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, list_keys_fn) };
436 }
437 
438 /// Import a key with SELINUX as domain, list aliases using `listEntriesBatched`.
439 /// Test should successfully list the imported key.
440 #[test]
keystore2_list_entries_batched_with_selinux_domain_success()441 fn keystore2_list_entries_batched_with_selinux_domain_success() {
442     let sl = SecLevel::tee();
443 
444     let alias = "test_selinux_key_list_alias_batched";
445     let _result = sl.keystore2.deleteKey(&KeyDescriptor {
446         domain: Domain::SELINUX,
447         nspace: key_generations::SELINUX_SHELL_NAMESPACE,
448         alias: Some(alias.to_string()),
449         blob: None,
450     });
451 
452     let initial_count = sl
453         .keystore2
454         .getNumberOfEntries(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE)
455         .unwrap();
456 
457     key_generations::import_aes_key(
458         &sl,
459         Domain::SELINUX,
460         key_generations::SELINUX_SHELL_NAMESPACE,
461         Some(alias.to_string()),
462     )
463     .unwrap();
464 
465     assert_eq!(
466         sl.keystore2
467             .getNumberOfEntries(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE)
468             .unwrap(),
469         initial_count + 1,
470         "Error while getting number of keystore entries accessible."
471     );
472 
473     let key_descriptors = sl
474         .keystore2
475         .listEntriesBatched(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE, None)
476         .unwrap();
477     assert_eq!(key_descriptors.len(), (initial_count + 1) as usize);
478 
479     let count =
480         key_descriptors.into_iter().map(|key| key.alias.unwrap()).filter(|a| a == alias).count();
481     assert_eq!(count, 1);
482 
483     sl.keystore2
484         .deleteKey(&KeyDescriptor {
485             domain: Domain::SELINUX,
486             nspace: key_generations::SELINUX_SHELL_NAMESPACE,
487             alias: Some(alias.to_string()),
488             blob: None,
489         })
490         .unwrap();
491 }
492 
493 #[test]
keystore2_list_entries_batched_validate_count_and_order_success()494 fn keystore2_list_entries_batched_validate_count_and_order_success() {
495     const USER_ID: u32 = 92;
496     const APPLICATION_ID: u32 = 10002;
497     static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
498     static CLIENT_GID: u32 = CLIENT_UID;
499     static ALIAS_PREFIX: &str = "key_test_batch_list";
500 
501     let list_keys_fn = || {
502         let sl = SecLevel::tee();
503 
504         // Make sure there are no keystore entries exist before adding new entries.
505         delete_all_entries(&sl.keystore2);
506 
507         // Import keys with below mentioned aliases -
508         // [
509         //   key_test_batch_list_1,
510         //   key_test_batch_list_2,
511         //   key_test_batch_list_3,
512         //   key_test_batch_list_4,
513         //   key_test_batch_list_5,
514         //   key_test_batch_list_10,
515         //   key_test_batch_list_11,
516         //   key_test_batch_list_12,
517         //   key_test_batch_list_21,
518         //   key_test_batch_list_22,
519         // ]
520         let _imported_key_aliases =
521             key_generations::import_aes_keys(&sl, ALIAS_PREFIX.to_string(), 1..6).unwrap();
522         assert_eq!(
523             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
524             5,
525             "Error while importing keys"
526         );
527         let _imported_key_aliases =
528             key_generations::import_aes_keys(&sl, ALIAS_PREFIX.to_string(), 10..13).unwrap();
529         assert_eq!(
530             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
531             8,
532             "Error while importing keys"
533         );
534         let _imported_key_aliases =
535             key_generations::import_aes_keys(&sl, ALIAS_PREFIX.to_string(), 21..23).unwrap();
536         assert_eq!(
537             sl.keystore2.getNumberOfEntries(Domain::APP, -1).unwrap(),
538             10,
539             "Error while importing keys"
540         );
541 
542         // List the aliases using given `startingPastAlias` and verify the listed
543         // aliases with the expected list of aliases.
544         verify_aliases(&sl.keystore2, Some(format!("{}{}", ALIAS_PREFIX, "_5").as_str()), vec![]);
545 
546         verify_aliases(
547             &sl.keystore2,
548             Some(format!("{}{}", ALIAS_PREFIX, "_4").as_str()),
549             vec![ALIAS_PREFIX.to_owned() + "_5"],
550         );
551 
552         verify_aliases(
553             &sl.keystore2,
554             Some(format!("{}{}", ALIAS_PREFIX, "_3").as_str()),
555             vec![ALIAS_PREFIX.to_owned() + "_4", ALIAS_PREFIX.to_owned() + "_5"],
556         );
557 
558         verify_aliases(
559             &sl.keystore2,
560             Some(format!("{}{}", ALIAS_PREFIX, "_2").as_str()),
561             vec![
562                 ALIAS_PREFIX.to_owned() + "_21",
563                 ALIAS_PREFIX.to_owned() + "_22",
564                 ALIAS_PREFIX.to_owned() + "_3",
565                 ALIAS_PREFIX.to_owned() + "_4",
566                 ALIAS_PREFIX.to_owned() + "_5",
567             ],
568         );
569 
570         verify_aliases(
571             &sl.keystore2,
572             Some(format!("{}{}", ALIAS_PREFIX, "_1").as_str()),
573             vec![
574                 ALIAS_PREFIX.to_owned() + "_10",
575                 ALIAS_PREFIX.to_owned() + "_11",
576                 ALIAS_PREFIX.to_owned() + "_12",
577                 ALIAS_PREFIX.to_owned() + "_2",
578                 ALIAS_PREFIX.to_owned() + "_21",
579                 ALIAS_PREFIX.to_owned() + "_22",
580                 ALIAS_PREFIX.to_owned() + "_3",
581                 ALIAS_PREFIX.to_owned() + "_4",
582                 ALIAS_PREFIX.to_owned() + "_5",
583             ],
584         );
585 
586         verify_aliases(
587             &sl.keystore2,
588             Some(ALIAS_PREFIX),
589             vec![
590                 ALIAS_PREFIX.to_owned() + "_1",
591                 ALIAS_PREFIX.to_owned() + "_10",
592                 ALIAS_PREFIX.to_owned() + "_11",
593                 ALIAS_PREFIX.to_owned() + "_12",
594                 ALIAS_PREFIX.to_owned() + "_2",
595                 ALIAS_PREFIX.to_owned() + "_21",
596                 ALIAS_PREFIX.to_owned() + "_22",
597                 ALIAS_PREFIX.to_owned() + "_3",
598                 ALIAS_PREFIX.to_owned() + "_4",
599                 ALIAS_PREFIX.to_owned() + "_5",
600             ],
601         );
602 
603         verify_aliases(
604             &sl.keystore2,
605             None,
606             vec![
607                 ALIAS_PREFIX.to_owned() + "_1",
608                 ALIAS_PREFIX.to_owned() + "_10",
609                 ALIAS_PREFIX.to_owned() + "_11",
610                 ALIAS_PREFIX.to_owned() + "_12",
611                 ALIAS_PREFIX.to_owned() + "_2",
612                 ALIAS_PREFIX.to_owned() + "_21",
613                 ALIAS_PREFIX.to_owned() + "_22",
614                 ALIAS_PREFIX.to_owned() + "_3",
615                 ALIAS_PREFIX.to_owned() + "_4",
616                 ALIAS_PREFIX.to_owned() + "_5",
617             ],
618         );
619     };
620 
621     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
622     // `--test-threads=1`), and nothing yet done with binder.
623     unsafe { run_as::run_as_app(CLIENT_UID, CLIENT_GID, list_keys_fn) };
624 }
625 
626 /// Try to list the key entries with domain SELINUX from user context where user doesn't possesses
627 /// `GET_INFO` permission for specified namespace. Test should fail to list key entries with error
628 /// response code `PERMISSION_DENIED`.
629 #[test]
keystore2_list_entries_batched_fails_perm_denied()630 fn keystore2_list_entries_batched_fails_perm_denied() {
631     let auid = 91 * AID_USER_OFFSET + 10001;
632     let agid = 91 * AID_USER_OFFSET + 10001;
633     let list_keys_fn = move || {
634         let keystore2 = get_keystore_service();
635 
636         let result = key_generations::map_ks_error(keystore2.listEntriesBatched(
637             Domain::SELINUX,
638             key_generations::SELINUX_SHELL_NAMESPACE,
639             None,
640         ));
641         assert!(result.is_err());
642         assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
643     };
644 
645     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
646     // `--test-threads=1`), and nothing yet done with binder.
647     unsafe { run_as::run_as_app(auid, agid, list_keys_fn) };
648 }
649 
650 /// Try to list key entries with domain BLOB. Test should fail with error response code
651 /// `INVALID_ARGUMENT`.
652 #[test]
keystore2_list_entries_batched_fails_invalid_arg()653 fn keystore2_list_entries_batched_fails_invalid_arg() {
654     let keystore2 = get_keystore_service();
655 
656     let result = key_generations::map_ks_error(keystore2.listEntriesBatched(
657         Domain::BLOB,
658         key_generations::SELINUX_SHELL_NAMESPACE,
659         None,
660     ));
661     assert!(result.is_err());
662     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
663 }
664 
665 /// Try to get the number of key entries with domain SELINUX from user context where user doesn't
666 /// possesses `GET_INFO` permission for specified namespace. Test should fail to list key entries
667 /// with error response code `PERMISSION_DENIED`.
668 #[test]
keystore2_get_number_of_entries_fails_perm_denied()669 fn keystore2_get_number_of_entries_fails_perm_denied() {
670     let auid = 91 * AID_USER_OFFSET + 10001;
671     let agid = 91 * AID_USER_OFFSET + 10001;
672     let get_num_fn = move || {
673         let keystore2 = get_keystore_service();
674 
675         let result = key_generations::map_ks_error(
676             keystore2.getNumberOfEntries(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE),
677         );
678         assert!(result.is_err());
679         assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
680     };
681 
682     // Safety: only one thread at this point (enforced by `AndroidTest.xml` setting
683     // `--test-threads=1`), and nothing yet done with binder.
684     unsafe { run_as::run_as_app(auid, agid, get_num_fn) };
685 }
686 
687 /// Try to get number of key entries with domain BLOB. Test should fail with error response code
688 /// `INVALID_ARGUMENT`.
689 #[test]
keystore2_get_number_of_entries_fails_invalid_arg()690 fn keystore2_get_number_of_entries_fails_invalid_arg() {
691     let keystore2 = get_keystore_service();
692 
693     let result = key_generations::map_ks_error(
694         keystore2.getNumberOfEntries(Domain::BLOB, key_generations::SELINUX_SHELL_NAMESPACE),
695     );
696     assert!(result.is_err());
697     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
698 }
699