Merge "Adding a test to list aliases of large number of Keystore entries with long aliases."
diff --git a/keystore2/tests/keystore2_client_list_entries_tests.rs b/keystore2/tests/keystore2_client_list_entries_tests.rs
index 62e3dd0..3b656c3 100644
--- a/keystore2/tests/keystore2_client_list_entries_tests.rs
+++ b/keystore2/tests/keystore2_client_list_entries_tests.rs
@@ -14,6 +14,8 @@
 
 use nix::unistd::{getuid, Gid, Uid};
 use rustutils::users::AID_USER_OFFSET;
+use std::collections::HashSet;
+use std::fmt::Write;
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_system_keystore2::aidl::android::system::keystore2::{
@@ -21,6 +23,7 @@
     KeyPermission::KeyPermission, ResponseCode::ResponseCode,
 };
 
+use crate::keystore2_client_test_utils::delete_app_key;
 use keystore2_test_utils::{get_keystore_service, key_generations, key_generations::Error, run_as};
 
 /// Try to find a key with given key parameters using `listEntries` API.
@@ -183,3 +186,68 @@
     assert!(result.is_err());
     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
 }
+
+/// Import large number of Keystore entries with long aliases and try to list aliases
+/// of all the entries in the keystore.
+#[test]
+fn keystore2_list_entries_with_long_aliases_success() {
+    static CLIENT_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const USER_ID: u32 = 92;
+    const APPLICATION_ID: u32 = 10002;
+    static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static CLIENT_GID: u32 = CLIENT_UID;
+
+    unsafe {
+        run_as::run_as(CLIENT_CTX, Uid::from_raw(CLIENT_UID), Gid::from_raw(CLIENT_GID), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+            // Make sure there are no keystore entries exist before adding new entries.
+            let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+            if !key_descriptors.is_empty() {
+                key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
+                    delete_app_key(&keystore2, &alias).unwrap();
+                });
+            }
+
+            let mut imported_key_aliases = HashSet::new();
+
+            // Import 100 keys with aliases of length 6000.
+            for count in 1..101 {
+                let mut alias = String::new();
+                write!(alias, "{}_{}", "X".repeat(6000), count).unwrap();
+                imported_key_aliases.insert(alias.clone());
+
+                let result =
+                    key_generations::import_aes_key(&sec_level, Domain::APP, -1, Some(alias));
+                assert!(result.is_ok());
+            }
+
+            // b/222287335 Limiting Keystore `listEntries` API to return subset of the Keystore
+            // entries to avoid running out of binder buffer space.
+            // To verify that all the imported key aliases are present in Keystore,
+            //  - get the list of entries from Keystore
+            //  - check whether the retrieved key entries list is a subset of imported key aliases
+            //  - delete this subset of keystore entries from Keystore as well as from imported
+            //    list of key aliases
+            //  - continue above steps till it cleanup all the imported keystore entries.
+            while !imported_key_aliases.is_empty() {
+                let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+
+                // Check retrieved key entries list is a subset of imported keys list.
+                assert!(key_descriptors
+                    .iter()
+                    .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
+
+                // Delete the listed key entries from Keystore as well as from imported keys list.
+                key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
+                    delete_app_key(&keystore2, &alias).unwrap();
+                    assert!(imported_key_aliases.remove(&alias));
+                });
+            }
+
+            assert!(imported_key_aliases.is_empty());
+        })
+    };
+}