Changes to strictly validate multiple `KeyPurpose` parameters
with KeyMint-V2 onward and to skip real key attestation using
emulated curve-25519 key on device with KeyMint V1 or Keymaster.
Bug: 353162976
Test: atest keystore2_client_tests
Change-Id: I95172afbf5cc351774447ba7bf430ceec9162a6b
diff --git a/keystore2/test_utils/lib.rs b/keystore2/test_utils/lib.rs
index 8b766dd..825657f 100644
--- a/keystore2/test_utils/lib.rs
+++ b/keystore2/test_utils/lib.rs
@@ -24,7 +24,7 @@
IKeystoreSecurityLevel::IKeystoreSecurityLevel,
};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
- ErrorCode::ErrorCode, SecurityLevel::SecurityLevel,
+ ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
};
use android_security_authorization::aidl::android::security::authorization::IKeystoreAuthorization::IKeystoreAuthorization;
@@ -176,4 +176,21 @@
pub fn is_keymaster(&self) -> bool {
!self.is_keymint()
}
+
+ /// Get KeyMint version.
+ /// Returns 0 if the underlying device is Keymaster not KeyMint.
+ pub fn get_keymint_version(&self) -> i32 {
+ let instance = match self.level {
+ SecurityLevel::TRUSTED_ENVIRONMENT => "default",
+ SecurityLevel::STRONGBOX => "strongbox",
+ l => panic!("unexpected level {l:?}"),
+ };
+ let name = format!("android.hardware.security.keymint.IKeyMintDevice/{instance}");
+ if binder::is_declared(&name).expect("Could not check for declared keymint interface") {
+ let km: binder::Strong<dyn IKeyMintDevice> = binder::get_interface(&name).unwrap();
+ km.getInterfaceVersion().unwrap()
+ } else {
+ 0
+ }
+ }
}
diff --git a/keystore2/tests/keystore2_client_attest_key_tests.rs b/keystore2/tests/keystore2_client_attest_key_tests.rs
index b51896a..a303ee8 100644
--- a/keystore2/tests/keystore2_client_attest_key_tests.rs
+++ b/keystore2/tests/keystore2_client_attest_key_tests.rs
@@ -177,6 +177,13 @@
skip_test_if_no_app_attest_key_feature!();
let sl = SecLevel::tee();
+ if sl.get_keymint_version() < 2 {
+ // Curve 25519 was included in version 2 of the KeyMint interface.
+ // For device with KeyMint-V1 or Keymaster in backend, emulated Ed25519 key can't attest
+ // to a "real" RSA key.
+ return;
+ }
+
let att_challenge: &[u8] = b"foo";
// Create EcCurve::CURVE_25519 attestation key.
@@ -226,6 +233,13 @@
fn keystore2_generate_rsa_attest_key_with_multi_purpose_fail() {
skip_test_if_no_app_attest_key_feature!();
let sl = SecLevel::tee();
+ if sl.get_keymint_version() < 2 {
+ // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+ // with other key purposes. However, this was not checked at the time
+ // so we can only be strict about checking this for implementations of KeyMint
+ // version 2 and above.
+ return;
+ }
let digest = Digest::SHA_2_256;
let padding = PaddingMode::RSA_PKCS1_1_5_SIGN;
@@ -267,6 +281,13 @@
fn keystore2_ec_attest_key_with_multi_purpose_fail() {
skip_test_if_no_app_attest_key_feature!();
let sl = SecLevel::tee();
+ if sl.get_keymint_version() < 2 {
+ // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+ // with other key purposes. However, this was not checked at the time
+ // so we can only be strict about checking this for implementations of KeyMint
+ // version 2 and above.
+ return;
+ }
let attest_key_alias = format!("ks_ec_attest_multipurpose_key_{}", getuid());
diff --git a/keystore2/tests/keystore2_client_import_keys_tests.rs b/keystore2/tests/keystore2_client_import_keys_tests.rs
index b06303e..f3a267b 100644
--- a/keystore2/tests/keystore2_client_import_keys_tests.rs
+++ b/keystore2/tests/keystore2_client_import_keys_tests.rs
@@ -247,8 +247,8 @@
}
/// Try to import a key with multiple purposes. Test should fail to import a key with
-/// `INCOMPATIBLE_PURPOSE` error code. If the backend is `keymaster` then `importKey` shall be
-/// successful.
+/// `INCOMPATIBLE_PURPOSE` error code. If the backend is `keymaster` or KeyMint-version-1 then
+/// `importKey` shall be successful.
#[test]
fn keystore2_rsa_import_key_with_multipurpose_fails_incompt_purpose_error() {
let sl = SecLevel::tee();
@@ -276,8 +276,14 @@
));
if sl.is_keymint() {
- assert!(result.is_err());
- assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
+ if sl.get_keymint_version() >= 2 {
+ // The KeyMint v1 spec required that KeyPurpose::ATTEST_KEY not be combined
+ // with other key purposes. However, this was not checked at the time
+ // so we can only be strict about checking this for implementations of KeyMint
+ // version 2 and above.
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
+ }
} else {
assert!(result.is_ok());
}
diff --git a/keystore2/tests/keystore2_client_key_agreement_tests.rs b/keystore2/tests/keystore2_client_key_agreement_tests.rs
index 19f6210..6744b60 100644
--- a/keystore2/tests/keystore2_client_key_agreement_tests.rs
+++ b/keystore2/tests/keystore2_client_key_agreement_tests.rs
@@ -112,7 +112,7 @@
test_ec_key_agree!(test_ec_p384_key_agreement, EcCurve::P_384);
test_ec_key_agree!(test_ec_p521_key_agreement, EcCurve::P_521);
-/// Generate two EC keys with curve `CURVE_25519` from KeyMint and OpeanSSL.
+/// Generate two EC keys with curve `CURVE_25519` from KeyMint and OpenSSL.
/// Perform local ECDH between them and verify that the derived secrets are the same.
#[test]
fn keystore2_ec_25519_agree_key_success() {