Merge "Allow virt APEX to use diced and open_dice_cbor"
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index baa3b12..5cdfbe9 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -324,7 +324,7 @@
     0x41, 0xe3, 0xb9, 0xce, 0x27, 0x58, 0x4e, 0x91, 0xbc, 0xfd, 0xa5, 0x5d, 0x91, 0x85, 0xab, 0x11,
 ]);
 
-static EXPIRATION_BUFFER_MS: i64 = 20000;
+static EXPIRATION_BUFFER_MS: i64 = 12 * 60 * 60 * 1000;
 
 /// Indicates how the sensitive part of this key blob is encrypted.
 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 14b3601..70b78ba 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -465,12 +465,10 @@
     .context("In connect_remotely_provisioned_component.")?;
 
     let rem_prov_hal: Strong<dyn IRemotelyProvisionedComponent> =
-        map_binder_status_code(binder::get_interface(&service_name))
-            .context(concat!(
-                "In connect_remotely_provisioned_component: Trying to connect to",
-                " RemotelyProvisionedComponent service."
-            ))
-            .map_err(|e| e)?;
+        map_binder_status_code(binder::get_interface(&service_name)).context(concat!(
+            "In connect_remotely_provisioned_component: Trying to connect to",
+            " RemotelyProvisionedComponent service."
+        ))?;
     Ok(rem_prov_hal)
 }
 
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index 6d0630b..d513db0 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -574,6 +574,17 @@
     auto legacyUpgradeParams = convertKeyParametersToLegacy(in_inUpgradeParams);
     V4_0_ErrorCode errorCode;
 
+    if (prefixedKeyBlobIsSoftKeyMint(in_inKeyBlobToUpgrade)) {
+        auto status = softKeyMintDevice_->upgradeKey(
+            prefixedKeyBlobRemovePrefix(in_inKeyBlobToUpgrade), in_inUpgradeParams, _aidl_return);
+        if (!status.isOk()) {
+            LOG(ERROR) << __func__ << " transaction failed. " << status.getDescription();
+        } else {
+            *_aidl_return = keyBlobPrefix(*_aidl_return, true);
+        }
+        return status;
+    }
+
     auto result =
         mDevice->upgradeKey(prefixedKeyBlobRemovePrefix(in_inKeyBlobToUpgrade), legacyUpgradeParams,
                             [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& upgradedKeyBlob) {
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 22509c4..3cc116b 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -19,6 +19,7 @@
 //! defined by keystore2 and keystore2_key respectively.
 
 use crate::error::Error as KsError;
+use crate::error::ResponseCode;
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
 };
@@ -87,7 +88,9 @@
         /// Checked when the caller attempts to use a private or public key.
         #[selinux(name = use)]
         Use = KeyPermission::USE.0,
-        /// Checked when the caller attempts to use device ids for attestation.
+        /// Does nothing, and is not checked. For use of device identifiers,
+        /// the caller must hold the READ_PRIVILEGED_PHONE_STATE Android
+        /// permission.
         #[selinux(name = use_dev_id)]
         UseDevId = KeyPermission::USE_DEV_ID.0,
     }
@@ -388,7 +391,7 @@
             tctx
         }
         _ => {
-            return Err(KsError::sys())
+            return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
                 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
         }
     };
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index 6398f31..b1405c7 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -129,3 +129,42 @@
         Err(e) => Err(e),
     }
 }
+
+/// Generate EC signing key.
+pub fn generate_ec_key<S: IKeystoreSecurityLevel + ?Sized>(
+    sec_level: &S,
+    domain: Domain,
+    nspace: i64,
+    alias: Option<String>,
+    ec_curve: EcCurve,
+    digest: Digest,
+) -> binder::Result<KeyMetadata> {
+    let gen_params = AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::EC)
+        .purpose(KeyPurpose::SIGN)
+        .purpose(KeyPurpose::VERIFY)
+        .digest(digest)
+        .ec_curve(ec_curve);
+
+    let key_metadata = sec_level.generateKey(
+        &KeyDescriptor { domain, nspace, alias, blob: None },
+        None,
+        &gen_params,
+        0,
+        b"entropy",
+    )?;
+
+    // Must have a public key.
+    assert!(key_metadata.certificate.is_some());
+
+    // Should not have an attestation record.
+    assert!(key_metadata.certificateChain.is_none());
+
+    if domain == Domain::BLOB {
+        assert!(key_metadata.key.blob.is_some());
+    } else {
+        assert!(key_metadata.key.blob.is_none());
+    }
+    Ok(key_metadata)
+}
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 06268c5..671b4ae 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -17,11 +17,13 @@
 use serde::{Deserialize, Serialize};
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    Digest::Digest, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
+    Algorithm::Algorithm, Digest::Digest, EcCurve::EcCurve, ErrorCode::ErrorCode,
+    KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
     CreateOperationResponse::CreateOperationResponse, Domain::Domain,
-    IKeystoreOperation::IKeystoreOperation, ResponseCode::ResponseCode,
+    IKeystoreOperation::IKeystoreOperation, KeyDescriptor::KeyDescriptor,
+    KeyPermission::KeyPermission, ResponseCode::ResponseCode,
 };
 
 use keystore2_test_utils::authorizations;
@@ -69,6 +71,28 @@
     )
 }
 
+/// Generate an EC signing key and grant it to the user with given access vector.
+fn generate_ec_key_and_grant_to_user(
+    grantee_uid: i32,
+    access_vector: i32,
+) -> binder::Result<KeyDescriptor> {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("{}{}", "ks_grant_test_key_1", getuid());
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::SELINUX,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias),
+        None,
+        None,
+    )
+    .unwrap();
+
+    keystore2.grant(&key_metadata.key, grantee_uid, access_vector)
+}
+
 /// Performs sample signing operation.
 fn perform_sample_sign_operation(
     op: &binder::Strong<dyn IKeystoreOperation>,
@@ -522,3 +546,739 @@
         });
     }
 }
+
+/// Try to grant a key with permission that does not map to any of the `KeyPermission` values.
+/// An error is expected with values that does not map to set of permissions listed in
+/// `KeyPermission`.
+#[test]
+fn keystore2_grant_key_with_invalid_perm_expecting_syserror() {
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    let grantee_uid = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    let invalid_access_vector = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0 << 19;
+
+    let result = key_generations::map_ks_error(generate_ec_key_and_grant_to_user(
+        grantee_uid.try_into().unwrap(),
+        invalid_access_vector,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::SYSTEM_ERROR), result.unwrap_err());
+}
+
+/// Try to grant a key with empty access vector `KeyPermission::NONE`, should be able to grant a
+/// key with empty access vector successfully. In grantee context try to use the granted key, it
+/// should fail to load the key with permission denied error.
+#[test]
+fn keystore2_grant_key_with_perm_none() {
+    static TARGET_SU_CTX: &str = "u:r:su:s0";
+
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    let grant_key_nspace = unsafe {
+        run_as::run_as(TARGET_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let empty_access_vector = KeyPermission::NONE.0;
+
+            let grant_key = key_generations::map_ks_error(generate_ec_key_and_grant_to_user(
+                GRANTEE_UID.try_into().unwrap(),
+                empty_access_vector,
+            ))
+            .unwrap();
+
+            assert_eq!(grant_key.domain, Domain::GRANT);
+
+            grant_key.nspace
+        })
+    };
+
+    // In grantee context try to load the key, it should fail to load the granted key as it is
+    // granted with empty access vector.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let result = key_generations::map_ks_error(keystore2.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+            },
+        )
+    };
+}
+
+/// Grant a key to the user (grantee) with `GET_INFO|USE` key permissions. Verify whether grantee
+/// can succeed in loading the granted key and try to perform simple operation using this granted
+/// key. Grantee should be able to load the key and use the key to perform crypto operation
+/// successfully. Try to delete the granted key in grantee context where it is expected to fail to
+/// delete it as `DELETE` permission is not granted.
+#[test]
+fn keystore2_grant_get_info_use_key_perm() {
+    static TARGET_SU_CTX: &str = "u:r:su:s0";
+
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    // Generate a key and grant it to a user with GET_INFO|USE key permissions.
+    let grant_key_nspace = unsafe {
+        run_as::run_as(TARGET_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let access_vector = KeyPermission::GET_INFO.0 | KeyPermission::USE.0;
+            let grant_key = key_generations::map_ks_error(generate_ec_key_and_grant_to_user(
+                GRANTEE_UID.try_into().unwrap(),
+                access_vector,
+            ))
+            .unwrap();
+
+            assert_eq!(grant_key.domain, Domain::GRANT);
+
+            grant_key.nspace
+        })
+    };
+
+    // In grantee context load the key and try to perform crypto operation.
+    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();
+
+                // Load the granted key.
+                let key_entry_response = keystore2
+                    .getKeyEntry(&KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: grant_key_nspace,
+                        alias: None,
+                        blob: None,
+                    })
+                    .unwrap();
+
+                // Perform sample crypto operation using granted key.
+                let op_response = sec_level
+                    .createOperation(
+                        &key_entry_response.metadata.key,
+                        &authorizations::AuthSetBuilder::new()
+                            .purpose(KeyPurpose::SIGN)
+                            .digest(Digest::SHA_2_256),
+                        false,
+                    )
+                    .unwrap();
+                assert!(op_response.iOperation.is_some());
+                assert_eq!(
+                    Ok(()),
+                    key_generations::map_ks_error(perform_sample_sign_operation(
+                        &op_response.iOperation.unwrap()
+                    ))
+                );
+
+                // Try to delete the key, it is expected to be fail with permission denied error.
+                let result = key_generations::map_ks_error(keystore2.deleteKey(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+            },
+        )
+    };
+}
+
+/// Try to generate a key with invalid Domain. `INVALID_ARGUMENT` error response is expected.
+#[test]
+fn keystore2_generate_key_invalid_domain() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_invalid_test_key_{}", getuid());
+
+    let result = key_generations::map_ks_error(key_generations::generate_ec_key(
+        &*sec_level,
+        Domain(99), // Invalid domain.
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
+}
+
+/// Try to generate a EC key without providing the curve.
+/// `UNSUPPORTED_EC_CURVE or UNSUPPORTED_KEY_SIZE` error response is expected.
+#[test]
+fn keystore2_generate_ec_key_missing_curve() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_ec_no_curve_test_key_{}", getuid());
+
+    // Don't provide EC curve.
+    let gen_params = authorizations::AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::EC)
+        .purpose(KeyPurpose::SIGN)
+        .purpose(KeyPurpose::VERIFY)
+        .digest(Digest::SHA_2_256);
+
+    let result = key_generations::map_ks_error(sec_level.generateKey(
+        &KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+            alias: Some(alias),
+            blob: None,
+        },
+        None,
+        &gen_params,
+        0,
+        b"entropy",
+    ));
+    assert!(result.is_err());
+    let err = result.unwrap_err();
+    assert!(matches!(
+        err,
+        Error::Km(ErrorCode::UNSUPPORTED_EC_CURVE) | Error::Km(ErrorCode::UNSUPPORTED_KEY_SIZE)
+    ));
+}
+
+/// Try to generate a EC key with curve `CURVE_25519` having `SIGN and AGREE_KEY` purposes.
+/// `INCOMPATIBLE_PURPOSE` error response is expected.
+#[test]
+fn keystore2_generate_ec_key_25519_multi_purpose() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_ec_no_curve_test_key_{}", getuid());
+
+    // Specify `SIGN and AGREE_KEY` purposes.
+    let gen_params = authorizations::AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::EC)
+        .ec_curve(EcCurve::CURVE_25519)
+        .purpose(KeyPurpose::SIGN)
+        .purpose(KeyPurpose::AGREE_KEY)
+        .digest(Digest::SHA_2_256);
+
+    let result = key_generations::map_ks_error(sec_level.generateKey(
+        &KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+            alias: Some(alias),
+            blob: None,
+        },
+        None,
+        &gen_params,
+        0,
+        b"entropy",
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
+}
+
+/// Generate EC keys with curves EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521 and
+/// various digest modes. Try to create operations using generated keys. Operations with digest
+/// modes `SHA1, SHA-2 224, SHA-2 256, SHA-2 384 and SHA-2 512` should be created  successfully.
+/// Creation of operations with digest modes NONE and MD5 should fail with an error code
+/// `UNSUPPORTED_DIGEST`.
+#[test]
+fn keystore2_ec_generate_key() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let digests = [
+        Digest::NONE,
+        Digest::MD5,
+        Digest::SHA1,
+        Digest::SHA_2_224,
+        Digest::SHA_2_256,
+        Digest::SHA_2_384,
+        Digest::SHA_2_512,
+    ];
+
+    let ec_curves = [EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521];
+
+    for ec_curve in ec_curves {
+        for digest in digests {
+            let alias = format!("ks_ec_test_key_gen_{}{}{}", getuid(), ec_curve.0, digest.0);
+            let key_metadata = key_generations::generate_ec_key(
+                &*sec_level,
+                Domain::APP,
+                -1,
+                Some(alias.to_string()),
+                ec_curve,
+                digest,
+            )
+            .unwrap();
+
+            match key_generations::map_ks_error(sec_level.createOperation(
+                &key_metadata.key,
+                &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(digest),
+                false,
+            )) {
+                Ok(op_response) => {
+                    assert!(op_response.iOperation.is_some());
+                    assert_eq!(
+                        Ok(()),
+                        key_generations::map_ks_error(perform_sample_sign_operation(
+                            &op_response.iOperation.unwrap()
+                        ))
+                    );
+                }
+                Err(e) => {
+                    assert_eq!(e, Error::Km(ErrorCode::UNSUPPORTED_DIGEST));
+                    assert!(digest == Digest::NONE || digest == Digest::MD5);
+                }
+            }
+        }
+    }
+}
+
+/// Generate EC key with curve `CURVE_25519` and digest mode NONE. Try to create an operation using
+/// generated key. `CURVE_25519` key should support `Digest::NONE` digest mode and test should be
+/// able to create an operation successfully.
+#[test]
+fn keystore2_ec_25519_generate_key_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let alias = format!("ks_ec_25519_none_test_key_gen_{}", getuid());
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias),
+        EcCurve::CURVE_25519,
+        Digest::NONE,
+    )
+    .unwrap();
+
+    let op_response = sec_level
+        .createOperation(
+            &key_metadata.key,
+            &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::NONE),
+            false,
+        )
+        .unwrap();
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+}
+
+/// Generate EC keys with curve `CURVE_25519` and digest modes `MD5, SHA1, SHA-2 224, SHA-2 256,
+/// SHA-2 384 and SHA-2 512`. Try to create operations using generated keys. `CURVE_25519` keys
+/// shouldn't support these digest modes. Test should fail to create operations with an error
+/// `UNSUPPORTED_DIGEST`.
+#[test]
+fn keystore2_ec_25519_generate_key_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let digests = [
+        Digest::MD5,
+        Digest::SHA1,
+        Digest::SHA_2_224,
+        Digest::SHA_2_256,
+        Digest::SHA_2_384,
+        Digest::SHA_2_512,
+    ];
+
+    for digest in digests {
+        let alias = format!("ks_ec_25519_test_key_gen_{}{}", getuid(), digest.0);
+        let key_metadata = key_generations::generate_ec_key(
+            &*sec_level,
+            Domain::APP,
+            -1,
+            Some(alias.to_string()),
+            EcCurve::CURVE_25519,
+            digest,
+        )
+        .unwrap();
+
+        let result = key_generations::map_ks_error(sec_level.createOperation(
+            &key_metadata.key,
+            &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(digest),
+            false,
+        ));
+        assert!(result.is_err());
+        assert_eq!(Error::Km(ErrorCode::UNSUPPORTED_DIGEST), result.unwrap_err());
+    }
+}
+
+/// Generate a EC key with `SHA_2_256` digest mode. Try to create an operation with digest mode
+/// other than `SHA_2_256`. Creation of an operation with generated key should fail with
+/// `INCOMPATIBLE_DIGEST` error as there is a mismatch of digest mode in key authorizations.
+#[test]
+fn keystore2_create_op_with_incompatible_key_digest() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let alias = "ks_ec_test_incomp_key_digest";
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .unwrap();
+
+    let digests =
+        [Digest::NONE, Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_384, Digest::SHA_2_512];
+
+    for digest in digests {
+        let result = key_generations::map_ks_error(sec_level.createOperation(
+            &key_metadata.key,
+            &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(digest),
+            false,
+        ));
+        assert!(result.is_err());
+        assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_DIGEST), result.unwrap_err());
+    }
+}
+
+/// Generate a key in client#1 and try to use it in other client#2.
+/// Client#2 should fail to load the key as the it doesn't own the client#1 generated key.
+#[test]
+fn keystore2_key_owner_validation() {
+    static TARGET_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID_1: u32 = 10601;
+
+    let uid1 = USER_ID * AID_USER_OFFSET + APPLICATION_ID_1;
+    let gid1 = USER_ID * AID_USER_OFFSET + APPLICATION_ID_1;
+    let alias = "ks_owner_check_test_key";
+
+    // Client#1: Generate a key and create an operation using generated key.
+    // Wait until the parent notifies to continue. Once the parent notifies, this operation
+    // is expected to be completed successfully.
+    let mut child_handle = execute_op_run_as_child(
+        TARGET_CTX,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        Uid::from_raw(uid1),
+        Gid::from_raw(gid1),
+        ForcedOp(false),
+    );
+
+    // Wait until (client#1) child process notifies us to continue, so that there will be a key
+    // generated by client#1.
+    child_handle.recv();
+
+    // Client#2: This child will try to load the key generated by client#1.
+    const APPLICATION_ID_2: u32 = 10602;
+    let uid2 = USER_ID * AID_USER_OFFSET + APPLICATION_ID_2;
+    let gid2 = USER_ID * AID_USER_OFFSET + APPLICATION_ID_2;
+    unsafe {
+        run_as::run_as(TARGET_CTX, Uid::from_raw(uid2), Gid::from_raw(gid2), move || {
+            let keystore2_inst = get_keystore_service();
+            let result =
+                key_generations::map_ks_error(keystore2_inst.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: -1,
+                    alias: Some(alias.to_string()),
+                    blob: None,
+                }));
+            assert!(result.is_err());
+            assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+        });
+    };
+
+    // Notify the child process (client#1) to resume and finish.
+    child_handle.send(&BarrierReached {});
+    assert!(
+        (child_handle.get_result() == TestOutcome::Ok),
+        "Client#1 failed to complete the operation."
+    );
+}
+
+/// Generate EC key with BLOB as domain. Generated key should be returned to caller as key blob.
+/// Verify that `blob` field in the `KeyDescriptor` is not empty and should have the key blob.
+/// Try to use this key for performing a sample operation and the operation should complete
+/// successfully.
+#[test]
+fn keystore2_generate_key_with_blob_domain() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::BLOB,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        None,
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .unwrap();
+
+    assert!(key_metadata.certificate.is_some());
+    assert!(key_metadata.certificateChain.is_none());
+
+    // Must have the key blob.
+    assert!(key_metadata.key.blob.is_some());
+
+    let op_response = key_generations::map_ks_error(sec_level.createOperation(
+        &key_metadata.key,
+        &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+        false,
+    ))
+    .unwrap();
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+
+    // Delete the generated key blob.
+    sec_level.deleteKey(&key_metadata.key).unwrap();
+}
+
+/// Try to generate a key with `Domain::KEY_ID`, test should fail with an error code
+/// `SYSTEM_ERROR`. `Domain::KEY_ID` is not allowed to use for generating a key. Key id is returned
+/// by Keystore2 after a key has been mapped from an alias.
+#[test]
+fn keystore2_generate_key_with_key_id_domain_expect_sys_error() {
+    let alias = "ks_gen_key_id_test_key";
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let result = key_generations::map_ks_error(key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::KEY_ID,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias.to_string()),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::SYSTEM_ERROR), result.unwrap_err());
+}
+
+/// Generate a key and try to load the generated key using KEY_ID as domain. Create an
+/// operation using key which is loaded with domain as KEY_ID. Test should create an operation
+/// successfully.
+#[test]
+fn keystore2_find_key_with_key_id_as_domain() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "ks_key_id_test_key";
+
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .expect("Failed to generate a EC key.");
+
+    // Try to load the above generated key with KEY_ID as domain.
+    let key_entry_response = keystore2
+        .getKeyEntry(&KeyDescriptor {
+            domain: Domain::KEY_ID,
+            nspace: key_metadata.key.nspace,
+            alias: Some(alias.to_string()),
+            blob: None,
+        })
+        .expect("Error in getKeyEntry to load a key with domain KEY_ID.");
+
+    // Verify above found key is same the one generated.
+    assert_eq!(key_metadata.key, key_entry_response.metadata.key);
+    assert_eq!(key_metadata.certificate, key_entry_response.metadata.certificate);
+    assert_eq!(key_metadata.certificateChain, key_entry_response.metadata.certificateChain);
+    assert_eq!(key_metadata.key.nspace, key_entry_response.metadata.key.nspace);
+
+    // Try to create an operation using above loaded key, operation should be created
+    // successfully.
+    let op_response = sec_level
+        .createOperation(
+            &key_entry_response.metadata.key,
+            &authorizations::AuthSetBuilder::new()
+                .purpose(KeyPurpose::SIGN)
+                .digest(Digest::SHA_2_256),
+            false,
+        )
+        .expect("Error in creation of operation.");
+
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+}
+
+/// Generate a key with an alias. Generate another key and bind it to the same alias.
+/// Try to create an operation using previously generated key. Creation of an operation should
+/// fail because previously generated key material is no longer accessible. Test should successfully
+/// create an operation using the rebound key.
+#[test]
+fn keystore2_key_id_alias_rebind_verify_by_alias() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_key_id_test_alias_rebind_1_{}", getuid());
+
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .expect("Failed to generate a EC key.");
+
+    // Generate a key with same alias as above generated key, so that alias will be rebound
+    // to this key.
+    let new_key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .expect("Failed to generate a rebound EC key.");
+
+    assert_ne!(key_metadata.key, new_key_metadata.key);
+    assert_ne!(key_metadata.certificate, new_key_metadata.certificate);
+    assert_ne!(key_metadata.key.nspace, new_key_metadata.key.nspace);
+
+    // Try to create an operation using previously generated key_metadata.
+    // It should fail as previously generated key material is no longer remains valid.
+    let result = key_generations::map_ks_error(sec_level.createOperation(
+        &key_metadata.key,
+        &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+        false,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+
+    // Try to create an operation using rebound key, operation should be created
+    // successfully.
+    let op_response = sec_level
+        .createOperation(
+            &new_key_metadata.key,
+            &authorizations::AuthSetBuilder::new()
+                .purpose(KeyPurpose::SIGN)
+                .digest(Digest::SHA_2_256),
+            false,
+        )
+        .expect("Error in creation of operation using rebound key.");
+
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+}
+
+/// Generate a key with an alias. Load the generated key with `Domain::KEY_ID`. Generate another
+/// key and bind it to the same alias. Try to create an operation using the key loaded with domain
+/// `KEY_ID`. Creation of an operation should fail because originally loaded key no longer exists.
+/// Test should successfully create an operation using the rebound key.
+#[test]
+fn keystore2_key_id_alias_rebind_verify_by_key_id() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_key_id_test_alias_rebind_2_{}", getuid());
+
+    let key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .expect("Failed to generate a EC key.");
+
+    // Load the above generated key with KEY_ID as domain.
+    let key_entry_response = keystore2
+        .getKeyEntry(&KeyDescriptor {
+            domain: Domain::KEY_ID,
+            nspace: key_metadata.key.nspace,
+            alias: Some(alias.to_string()),
+            blob: None,
+        })
+        .expect("Error in getKeyEntry to load a key with domain KEY_ID.");
+
+    // Verify above found key is same the one generated.
+    assert_eq!(key_metadata.key, key_entry_response.metadata.key);
+    assert_eq!(key_metadata.certificate, key_entry_response.metadata.certificate);
+    assert_eq!(key_metadata.certificateChain, key_entry_response.metadata.certificateChain);
+    assert_eq!(key_metadata.key.nspace, key_entry_response.metadata.key.nspace);
+
+    // Generate another key with same alias as above generated key, so that alias will be rebound
+    // to this key.
+    let new_key_metadata = key_generations::generate_ec_key(
+        &*sec_level,
+        Domain::APP,
+        -1,
+        Some(alias),
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+    )
+    .expect("Failed to generate a rebound EC key.");
+
+    // Verify that an alias is rebound to a new key.
+    assert_eq!(key_metadata.key.alias, new_key_metadata.key.alias);
+    assert_ne!(key_metadata.key, new_key_metadata.key);
+    assert_ne!(key_metadata.certificate, new_key_metadata.certificate);
+    assert_ne!(key_metadata.key.nspace, new_key_metadata.key.nspace);
+
+    // Try to create an operation using previously loaded key_entry_response.
+    // It should fail as previously generated key material is no longer valid.
+    let result = key_generations::map_ks_error(sec_level.createOperation(
+        &key_entry_response.metadata.key,
+        &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+        false,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+
+    // Try to create an operation using rebound key, operation should be created
+    // successfully.
+    let op_response = sec_level
+        .createOperation(
+            &new_key_metadata.key,
+            &authorizations::AuthSetBuilder::new()
+                .purpose(KeyPurpose::SIGN)
+                .digest(Digest::SHA_2_256),
+            false,
+        )
+        .expect("Error in creation of operation using rebound key.");
+
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+}
diff --git a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
index 48275ae..32ecd03 100644
--- a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
+++ b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
@@ -85,7 +85,7 @@
         .expect("failed to execute pidof keystore2");
 
     let id = String::from_utf8(output.stdout).unwrap();
-    let id: String = id.chars().filter(|c| c.is_digit(10)).collect();
+    let id: String = id.chars().filter(|c| c.is_ascii_digit()).collect();
 
     let _status = std::process::Command::new("kill").arg("-9").arg(id).status().unwrap();