Merge "Update source for Rust 1.63.0"
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index d634e0c..8d2e5ad 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -266,7 +266,7 @@
                 ..Default::default()
             },
             Domain::SELINUX => KeyDescriptor{domain, nspace: namespace, ..Default::default()},
-            _ => return Err(Error::perm()).context(
+            _ => return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
                 "In list_entries: List entries is only supported for Domain::APP and Domain::SELINUX."
             ),
         };
@@ -278,8 +278,8 @@
         // selected.
         if let Err(e) = check_key_permission(KeyPerm::GetInfo, &k, &None) {
             if let Some(selinux::Error::PermissionDenied) =
-                e.root_cause().downcast_ref::<selinux::Error>() {
-
+                e.root_cause().downcast_ref::<selinux::Error>()
+            {
                 check_keystore_permission(KeystorePerm::List)
                     .context("In list_entries: While checking keystore permission.")?;
                 if namespace != -1 {
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index 047df28..c25d928 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -254,9 +254,10 @@
     Ok(key_metadata)
 }
 
-/// Generate AES key.
-pub fn generate_aes_key(
+/// Generate AES/3DES key.
+pub fn generate_sym_key(
     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    algorithm: Algorithm,
     size: i32,
     alias: &str,
     padding_mode: &PaddingMode,
@@ -265,7 +266,7 @@
 ) -> binder::Result<KeyMetadata> {
     let mut gen_params = AuthSetBuilder::new()
         .no_auth_required()
-        .algorithm(Algorithm::AES)
+        .algorithm(algorithm)
         .purpose(KeyPurpose::ENCRYPT)
         .purpose(KeyPurpose::DECRYPT)
         .key_size(size)
diff --git a/keystore2/tests/keystore2_client_3des_key_tests.rs b/keystore2/tests/keystore2_client_3des_key_tests.rs
new file mode 100644
index 0000000..eda24db
--- /dev/null
+++ b/keystore2/tests/keystore2_client_3des_key_tests.rs
@@ -0,0 +1,218 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    Algorithm::Algorithm, BlockMode::BlockMode, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose,
+    PaddingMode::PaddingMode, SecurityLevel::SecurityLevel,
+};
+
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+};
+
+use keystore2_test_utils::{
+    authorizations, get_keystore_service, key_generations, key_generations::Error,
+};
+
+use crate::keystore2_client_test_utils::{
+    perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
+};
+
+/// Generate a 3DES key. Create encryption and decryption operations using the generated key.
+fn create_3des_key_and_operation(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    padding_mode: PaddingMode,
+    block_mode: BlockMode,
+    nonce: &mut Option<Vec<u8>>,
+) -> Result<(), binder::Status> {
+    let alias = format!("ks_3des_test_key_{}{}", block_mode.0, padding_mode.0);
+
+    let key_metadata = key_generations::generate_sym_key(
+        sec_level,
+        Algorithm::TRIPLE_DES,
+        168,
+        &alias,
+        &padding_mode,
+        &block_mode,
+        None,
+    )?;
+
+    // Encrypts `SAMPLE_PLAIN_TEXT` whose length is multiple of DES block size.
+    let cipher_text = perform_sample_sym_key_encrypt_op(
+        sec_level,
+        padding_mode,
+        block_mode,
+        nonce,
+        None,
+        &key_metadata.key,
+    )?;
+    assert!(cipher_text.is_some());
+
+    let plain_text = perform_sample_sym_key_decrypt_op(
+        sec_level,
+        &cipher_text.unwrap(),
+        padding_mode,
+        block_mode,
+        nonce,
+        None,
+        &key_metadata.key,
+    )
+    .unwrap();
+    assert!(plain_text.is_some());
+    assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+    Ok(())
+}
+
+/// Generate 3DES keys with various block modes and paddings.
+///  - Block Modes: ECB, CBC
+///  - Padding Modes: NONE, PKCS7
+/// Test should generate keys and perform operation successfully.
+#[test]
+fn keystore2_3des_ecb_cbc_generate_key_success() {
+    let keystore2 = get_keystore_service();
+    let block_modes = [BlockMode::ECB, BlockMode::CBC];
+    let padding_modes = [PaddingMode::PKCS7, PaddingMode::NONE];
+
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    for block_mode in block_modes {
+        for padding_mode in padding_modes {
+            assert_eq!(
+                Ok(()),
+                create_3des_key_and_operation(&sec_level, padding_mode, block_mode, &mut None)
+            );
+        }
+    }
+}
+
+/// Try to generate 3DES key with invalid key size. Test should fail to generate a key with
+/// an error code `UNSUPPORTED_KEY_SIZE`.
+#[test]
+fn keystore2_3des_key_fails_unsupported_key_size() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "3des_key_test_invalid_1";
+    let invalid_key_size = 128;
+
+    let result = key_generations::map_ks_error(key_generations::generate_sym_key(
+        &sec_level,
+        Algorithm::TRIPLE_DES,
+        invalid_key_size,
+        alias,
+        &PaddingMode::PKCS7,
+        &BlockMode::CBC,
+        None,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_KEY_SIZE), result.unwrap_err());
+}
+
+/// Generate a 3DES key without providing padding mode and try to use the generated key to create
+/// an operation. Test should fail to create an operation with an error code
+/// `UNSUPPORTED_PADDING_MODE`.
+#[test]
+fn keystore2_3des_key_fails_missing_padding() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "3des_key_test_missing_padding";
+
+    let gen_params = authorizations::AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::TRIPLE_DES)
+        .purpose(KeyPurpose::ENCRYPT)
+        .purpose(KeyPurpose::DECRYPT)
+        .key_size(168)
+        .block_mode(BlockMode::ECB);
+
+    let key_metadata = sec_level
+        .generateKey(
+            &KeyDescriptor {
+                domain: Domain::APP,
+                nspace: -1,
+                alias: Some(alias.to_string()),
+                blob: None,
+            },
+            None,
+            &gen_params,
+            0,
+            b"entropy",
+        )
+        .unwrap();
+
+    let op_params = authorizations::AuthSetBuilder::new()
+        .purpose(KeyPurpose::ENCRYPT)
+        .block_mode(BlockMode::ECB);
+
+    let result = key_generations::map_ks_error(sec_level.createOperation(
+        &key_metadata.key,
+        &op_params,
+        false,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_PADDING_MODE), result.unwrap_err());
+}
+
+/// Generate a 3DES key with padding mode NONE. Try to encrypt a text whose length isn't a
+/// multiple of the DES block size.
+#[test]
+fn keystore2_3des_key_encrypt_fails_invalid_input_length() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "3des_key_test_invalid_input_len";
+
+    let key_metadata = key_generations::generate_sym_key(
+        &sec_level,
+        Algorithm::TRIPLE_DES,
+        168,
+        alias,
+        &PaddingMode::NONE,
+        &BlockMode::ECB,
+        None,
+    )
+    .unwrap();
+
+    let op_params = authorizations::AuthSetBuilder::new()
+        .purpose(KeyPurpose::ENCRYPT)
+        .padding_mode(PaddingMode::NONE)
+        .block_mode(BlockMode::ECB);
+
+    let op_response = sec_level
+        .createOperation(&key_metadata.key, &op_params, false)
+        .expect("Error in creation of operation using rebound key.");
+    assert!(op_response.iOperation.is_some());
+
+    let op = op_response.iOperation.unwrap();
+    // 3DES expects input should be multiple of DES block size (64-bits) length. Try with invalid
+    // length of input.
+    let invalid_block_size_msg = b"my message 111";
+    let result = key_generations::map_ks_error(op.finish(Some(invalid_block_size_msg), None));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INVALID_INPUT_LENGTH), result.unwrap_err());
+}
+
+/// Try to generate 3DES key with BlockMode::CTR. Test should fail to create an operation with an
+/// error code `UNSUPPORTED_BLOCK_MODE`.
+#[test]
+fn keystore2_3des_key_fails_unsupported_block_mode() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let result = key_generations::map_ks_error(create_3des_key_and_operation(
+        &sec_level,
+        PaddingMode::NONE,
+        BlockMode::CTR,
+        &mut None,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_BLOCK_MODE), result.unwrap_err());
+}
diff --git a/keystore2/tests/keystore2_client_aes_key_tests.rs b/keystore2/tests/keystore2_client_aes_key_tests.rs
index 989d047..c56eef6 100644
--- a/keystore2/tests/keystore2_client_aes_key_tests.rs
+++ b/keystore2/tests/keystore2_client_aes_key_tests.rs
@@ -41,8 +41,9 @@
 ) -> Result<(), binder::Status> {
     let alias = format!("ks_aes_test_key_{}{}{}", key_size, block_mode.0, padding_mode.0);
 
-    let key_metadata = key_generations::generate_aes_key(
+    let key_metadata = key_generations::generate_sym_key(
         sec_level,
+        Algorithm::AES,
         key_size,
         &alias,
         &padding_mode,
@@ -176,8 +177,9 @@
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let alias = "aes_key_test_invalid_1";
 
-    let result = key_generations::map_ks_error(key_generations::generate_aes_key(
+    let result = key_generations::map_ks_error(key_generations::generate_sym_key(
         &sec_level,
+        Algorithm::AES,
         1024,
         alias,
         &PaddingMode::NONE,
@@ -196,8 +198,9 @@
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let alias = "aes_key_test_invalid_1";
 
-    let result = key_generations::map_ks_error(key_generations::generate_aes_key(
+    let result = key_generations::map_ks_error(key_generations::generate_sym_key(
         &sec_level,
+        Algorithm::AES,
         128,
         alias,
         &PaddingMode::NONE,
@@ -313,8 +316,9 @@
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let alias = "aes_key_test_invalid_1";
 
-    let key_metadata = key_generations::generate_aes_key(
+    let key_metadata = key_generations::generate_sym_key(
         &sec_level,
+        Algorithm::AES,
         128,
         alias,
         &PaddingMode::NONE,
@@ -344,8 +348,9 @@
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let alias = "aes_key_test_invalid_1";
 
-    let key_metadata = key_generations::generate_aes_key(
+    let key_metadata = key_generations::generate_sym_key(
         &sec_level,
+        Algorithm::AES,
         128,
         alias,
         &PaddingMode::NONE,
@@ -443,8 +448,9 @@
     let alias = "aes_key_test_nonce_1";
     let mut nonce = Some(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
 
-    let key_metadata = key_generations::generate_aes_key(
+    let key_metadata = key_generations::generate_sym_key(
         &sec_level,
+        Algorithm::AES,
         128,
         alias,
         &PaddingMode::PKCS7,
diff --git a/keystore2/tests/keystore2_client_list_entries_tests.rs b/keystore2/tests/keystore2_client_list_entries_tests.rs
new file mode 100644
index 0000000..d50ef5c
--- /dev/null
+++ b/keystore2/tests/keystore2_client_list_entries_tests.rs
@@ -0,0 +1,187 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use nix::unistd::{getuid, Gid, Uid};
+use rustutils::users::AID_USER_OFFSET;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor,
+    KeyPermission::KeyPermission, ResponseCode::ResponseCode,
+};
+
+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.
+fn is_key_alias_exist(
+    keystore2: &binder::Strong<dyn IKeystoreService>,
+    domain: Domain,
+    nspace: i64,
+    alias: String,
+) -> bool {
+    let key_descriptors = keystore2.listEntries(domain, nspace).unwrap();
+    let alias_count = key_descriptors
+        .into_iter()
+        .map(|key| key.alias.unwrap())
+        .filter(|key_alias| *key_alias == alias)
+        .count();
+
+    alias_count != 0
+}
+
+/// List key entries with domain as SELINUX and APP.
+/// 1. Generate a key with domain as SELINUX and find this key entry in list of keys retrieved from
+///    `listEntries` with domain SELINUX. Test should be able find this key entry successfully.
+/// 2. Grant above generated Key to a user.
+/// 3. In a user context, generate a new key with domain as APP. Try to list the key entries with
+///    domain APP. Test should find only one key entry that should be the key generated in user
+///    context. GRANT keys shouldn't be part of this list.
+#[test]
+fn keystore2_list_entries_success() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const USER_ID: u32 = 91;
+    const APPLICATION_ID: u32 = 10006;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+            let alias = format!("list_entries_grant_key1_{}", getuid());
+
+            // Make sure there is no key exist with this `alias` in `SELINUX` domain and
+            // `SELINUX_SHELL_NAMESPACE` namespace.
+            if is_key_alias_exist(
+                &keystore2,
+                Domain::SELINUX,
+                key_generations::SELINUX_SHELL_NAMESPACE,
+                alias.to_string(),
+            ) {
+                keystore2
+                    .deleteKey(&KeyDescriptor {
+                        domain: Domain::SELINUX,
+                        nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+                        alias: Some(alias.to_string()),
+                        blob: None,
+                    })
+                    .unwrap();
+            }
+
+            // Generate a key with above defined `alias`.
+            let key_metadata = key_generations::generate_ec_p256_signing_key(
+                &sec_level,
+                Domain::SELINUX,
+                key_generations::SELINUX_SHELL_NAMESPACE,
+                Some(alias.to_string()),
+                None,
+                None,
+            )
+            .unwrap();
+
+            // Verify that above generated key entry is listed with domain SELINUX and
+            // namespace SELINUX_SHELL_NAMESPACE
+            assert!(is_key_alias_exist(
+                &keystore2,
+                Domain::SELINUX,
+                key_generations::SELINUX_SHELL_NAMESPACE,
+                alias,
+            ));
+
+            // Grant a key with GET_INFO permission.
+            let access_vector = KeyPermission::GET_INFO.0;
+            keystore2
+                .grant(&key_metadata.key, GRANTEE_UID.try_into().unwrap(), access_vector)
+                .unwrap();
+        })
+    };
+
+    // In user context validate list of key entries associated with it.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+                let sec_level =
+                    keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+                let alias = format!("list_entries_success_key{}", getuid());
+
+                let key_metadata = key_generations::generate_ec_p256_signing_key(
+                    &sec_level,
+                    Domain::APP,
+                    -1,
+                    Some(alias.to_string()),
+                    None,
+                    None,
+                )
+                .unwrap();
+
+                // Make sure there is only one key entry exist and that should be the same key
+                // generated in this user context. Granted key shouldn't be included in this list.
+                let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+                assert_eq!(1, key_descriptors.len());
+
+                let key = key_descriptors.get(0).unwrap();
+                assert_eq!(key.alias, Some(alias));
+                assert_eq!(key.nspace, GRANTEE_UID.try_into().unwrap());
+                assert_eq!(key.domain, Domain::APP);
+
+                keystore2.deleteKey(&key_metadata.key).unwrap();
+
+                let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+                assert_eq!(0, key_descriptors.len());
+            },
+        )
+    };
+}
+
+/// Try to list the key entries with domain SELINUX from user context where user doesn't possesses
+/// `GET_INFO` permission for specified namespace. Test should fail to list key entries with error
+/// response code `PERMISSION_DENIED`.
+#[test]
+fn keystore2_list_entries_fails_perm_denied() {
+    let auid = 91 * AID_USER_OFFSET + 10001;
+    let agid = 91 * AID_USER_OFFSET + 10001;
+    static TARGET_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    unsafe {
+        run_as::run_as(TARGET_CTX, Uid::from_raw(auid), Gid::from_raw(agid), move || {
+            let keystore2 = get_keystore_service();
+
+            let result = key_generations::map_ks_error(
+                keystore2.listEntries(Domain::SELINUX, key_generations::SELINUX_SHELL_NAMESPACE),
+            );
+            assert!(result.is_err());
+            assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+        })
+    };
+}
+
+/// Try to list key entries with domain BLOB. Test should fail with error repose code
+/// `INVALID_ARGUMENT`.
+#[test]
+fn keystore2_list_entries_fails_invalid_arg() {
+    let keystore2 = get_keystore_service();
+
+    let result = key_generations::map_ks_error(
+        keystore2.listEntries(Domain::BLOB, key_generations::SELINUX_SHELL_NAMESPACE),
+    );
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
+}
diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs
index 075912d..006f2f9 100644
--- a/keystore2/tests/keystore2_client_test_utils.rs
+++ b/keystore2/tests/keystore2_client_test_utils.rs
@@ -145,6 +145,7 @@
 }
 
 /// This performs sample encryption operation with given symmetric key (AES/3DES).
+/// It encrypts `SAMPLE_PLAIN_TEXT` of length 128-bits.
 pub fn perform_sample_sym_key_encrypt_op(
     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
     padding_mode: PaddingMode,
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 3fb3e15..734faf6 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -12,10 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+pub mod keystore2_client_3des_key_tests;
 pub mod keystore2_client_aes_key_tests;
 pub mod keystore2_client_ec_key_tests;
 pub mod keystore2_client_grant_key_tests;
 pub mod keystore2_client_key_id_domain_tests;
+pub mod keystore2_client_list_entries_tests;
 pub mod keystore2_client_operation_tests;
 pub mod keystore2_client_rsa_key_tests;
 pub mod keystore2_client_test_utils;