Merge changes Ic7857267,I2bf53018 into main
* changes:
Adding tests to check unique id attestation.
Changes are made in keystore-client-tests to verify CREATION_DATETIME, ATTESTATION_CHALLENGE and ATTESTATION_APPLICATION_ID.
diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs
index b73aab5..ebe2665 100644
--- a/keystore2/test_utils/authorizations.rs
+++ b/keystore2/test_utils/authorizations.rs
@@ -305,6 +305,24 @@
});
self
}
+
+ /// Set creation date-time.
+ pub fn creation_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::CREATION_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
+
+ /// Set include unique id.
+ pub fn include_unique_id(mut self) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::INCLUDE_UNIQUE_ID,
+ value: KeyParameterValue::BoolValue(true),
+ });
+ self
+ }
}
impl Deref for AuthSetBuilder {
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index ccf27bc..0ffc32a 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -26,7 +26,7 @@
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
KeyOrigin::KeyOrigin, KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue,
- KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, Tag::Tag,
+ KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
};
use android_system_keystore2::aidl::android::system::keystore2::{
AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization,
@@ -38,7 +38,10 @@
use crate::authorizations::AuthSetBuilder;
use android_system_keystore2::binder::{ExceptionCode, Result as BinderResult};
-use crate::ffi_test_utils::{get_os_patchlevel, get_os_version, get_vendor_patchlevel};
+use crate::ffi_test_utils::{
+ get_os_patchlevel, get_os_version, get_value_from_attest_record, get_vendor_patchlevel,
+ validate_certchain,
+};
/// Shell namespace.
pub const SELINUX_SHELL_NAMESPACE: i64 = 1;
@@ -388,6 +391,12 @@
})
}
+/// Indicate whether the default device is KeyMint (rather than Keymaster).
+pub fn has_default_keymint() -> bool {
+ binder::is_declared("android.hardware.security.keymint.IKeyMintDevice/default")
+ .expect("Could not check for declared keymint interface")
+}
+
/// Verify that given key param is listed in given authorizations list.
pub fn check_key_param(authorizations: &[Authorization], key_param: &KeyParameter) -> bool {
authorizations.iter().any(|auth| &auth.keyParameter == key_param)
@@ -468,6 +477,13 @@
)
}
));
+
+ if has_default_keymint() {
+ assert!(authorizations
+ .iter()
+ .map(|auth| &auth.keyParameter)
+ .any(|key_param| key_param.tag == Tag::CREATION_DATETIME));
+ }
}
/// Get the key `Authorization` for the given auth `Tag`.
@@ -1400,6 +1416,32 @@
assert!(key_metadata.certificate.is_some());
if gen_params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) {
assert!(key_metadata.certificateChain.is_some());
+ let mut cert_chain: Vec<u8> = Vec::new();
+ cert_chain.extend(key_metadata.certificate.as_ref().unwrap());
+ cert_chain.extend(key_metadata.certificateChain.as_ref().unwrap());
+ validate_certchain(&cert_chain).expect("Error while validating cert chain");
+ }
+
+ if let Some(challenge_param) =
+ gen_params.iter().find(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE)
+ {
+ if let KeyParameterValue::Blob(val) = &challenge_param.value {
+ let att_challenge = get_value_from_attest_record(
+ key_metadata.certificate.as_ref().unwrap(),
+ challenge_param.tag,
+ key_metadata.keySecurityLevel,
+ )
+ .expect("Attestation challenge verification failed.");
+ assert_eq!(&att_challenge, val);
+ }
+
+ let att_app_id = get_value_from_attest_record(
+ key_metadata.certificate.as_ref().unwrap(),
+ Tag::ATTESTATION_APPLICATION_ID,
+ SecurityLevel::KEYSTORE,
+ )
+ .expect("Attestation application id verification failed.");
+ assert!(!att_app_id.is_empty());
}
}
check_key_authorizations(&key_metadata.authorizations, gen_params, KeyOrigin::GENERATED);
diff --git a/keystore2/tests/keystore2_client_authorizations_tests.rs b/keystore2/tests/keystore2_client_authorizations_tests.rs
index fe48acd..4fce1d9 100644
--- a/keystore2/tests/keystore2_client_authorizations_tests.rs
+++ b/keystore2/tests/keystore2_client_authorizations_tests.rs
@@ -21,8 +21,8 @@
};
use android_system_keystore2::aidl::android::system::keystore2::{
- IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyMetadata::KeyMetadata,
- ResponseCode::ResponseCode,
+ Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+ KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
};
use keystore2_test_utils::{
@@ -36,6 +36,32 @@
use keystore2_test_utils::ffi_test_utils::get_value_from_attest_record;
+fn gen_key_including_unique_id(
+ sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+ alias: &str,
+) -> Vec<u8> {
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .include_unique_id();
+
+ let key_metadata = key_generations::generate_key(sec_level, &gen_params, alias).unwrap();
+
+ let unique_id = get_value_from_attest_record(
+ key_metadata.certificate.as_ref().unwrap(),
+ Tag::UNIQUE_ID,
+ key_metadata.keySecurityLevel,
+ )
+ .expect("Unique id not found.");
+ assert!(!unique_id.is_empty());
+ unique_id
+}
+
fn generate_key_and_perform_sign_verify_op_max_times(
sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
gen_params: &authorizations::AuthSetBuilder,
@@ -590,3 +616,60 @@
false,
);
}
+
+/// Try to generate a key with `Tag::CREATION_DATETIME` set to valid value. Test should fail
+/// to generate a key with `INVALID_ARGUMENT` error as Keystore2 backend doesn't allow user to
+/// specify `CREATION_DATETIME`.
+#[test]
+fn keystore2_gen_key_auth_creation_date_time_test_fail_with_invalid_arg_error() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let duration_since_epoch = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
+ let creation_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::EC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256)
+ .ec_curve(EcCurve::P_256)
+ .attestation_challenge(b"foo".to_vec())
+ .creation_date_time(creation_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::map_ks_error(sec_level.generateKey(
+ &KeyDescriptor {
+ domain: Domain::APP,
+ nspace: -1,
+ alias: Some(alias.to_string()),
+ blob: None,
+ },
+ None,
+ &gen_params,
+ 0,
+ b"entropy",
+ ));
+
+ assert!(result.is_err());
+ assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
+}
+
+/// Generate a key with `Tag::INCLUDE_UNIQUE_ID` set. Test should verify that `Tag::UNIQUE_ID` is
+/// included in attest record and it remains the same for new keys generated.
+#[test]
+fn keystore2_gen_key_auth_include_unique_id_success() {
+ let keystore2 = get_keystore_service();
+ let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+ let alias_first = "ks_test_auth_tags_test_1";
+ let unique_id_first = gen_key_including_unique_id(&sec_level, alias_first);
+
+ let alias_second = "ks_test_auth_tags_test_2";
+ let unique_id_second = gen_key_including_unique_id(&sec_level, alias_second);
+
+ assert_eq!(unique_id_first, unique_id_second);
+
+ delete_app_key(&keystore2, alias_first).unwrap();
+ delete_app_key(&keystore2, alias_second).unwrap();
+}
diff --git a/keystore2/tests/keystore2_client_import_keys_tests.rs b/keystore2/tests/keystore2_client_import_keys_tests.rs
index 3d108fe..31d57a2 100644
--- a/keystore2/tests/keystore2_client_import_keys_tests.rs
+++ b/keystore2/tests/keystore2_client_import_keys_tests.rs
@@ -37,9 +37,9 @@
};
use crate::keystore2_client_test_utils::{
- encrypt_secure_key, encrypt_transport_key, has_default_keymint,
- perform_sample_asym_sign_verify_op, perform_sample_hmac_sign_verify_op,
- perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
+ encrypt_secure_key, encrypt_transport_key, perform_sample_asym_sign_verify_op,
+ perform_sample_hmac_sign_verify_op, perform_sample_sym_key_decrypt_op,
+ perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
};
pub fn import_rsa_sign_key_and_perform_sample_operation(
@@ -288,7 +288,7 @@
key_generations::RSA_2048_KEY,
));
- if has_default_keymint() {
+ if key_generations::has_default_keymint() {
assert!(result.is_err());
assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
} else {
diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs
index f7e7985..e76c64b 100644
--- a/keystore2/tests/keystore2_client_test_utils.rs
+++ b/keystore2/tests/keystore2_client_test_utils.rs
@@ -104,12 +104,6 @@
};
}
-/// Indicate whether the default device is KeyMint (rather than Keymaster).
-pub fn has_default_keymint() -> bool {
- binder::is_declared("android.hardware.security.keymint.IKeyMintDevice/default")
- .expect("Could not check for declared keymint interface")
-}
-
/// Generate EC key and grant it to the list of users with given access vector.
/// Returns the list of granted keys `nspace` values in the order of given grantee uids.
pub fn generate_ec_key_and_grant_to_users(