Adding tests using tags ACTIVE_DATETIME, ORIGINATION_EXPIRE_DATETIME,
USAGE_EXPIRE_DATETIME.
1. Tests will generate a key with current date and time set to
active-datetime and verify the key characteristics. Test will use
this key to create a sign operation successfully.
2. Test will generate a key with future date set to active-datetime and
verify the key characteristics. Test will fail with error code
`KEY_NOT_YET_VALID` while creating an operation using generated key.
3. Tests will generate a key with future date and time set to
origination-expire-datetime and verify the key characteristics. Test
will use this key to create a sign operation successfully.
4. Test will generate a key with current date and time set to
origination-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while creating an operation
using generated key.
5. Tests will generate a key with future date and time set to
usage-expire-datetime and verify the key characteristics. Test
will use this key to successfully verify the signature created using
this key.
6. Tests will generate a key with current date and time set to
usage-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while verifying the signature
created using this key.
7. Test will generate a AES key with future date and time set to
usage-expire-datetime and verify the key characteristics. Test
will perform encrypt and decrypt operations using this generated key
successfully.
8. Test will generate a AES key with current date and time set to
usage-expire-datetime and verify the key characteristics. Test
will fail with error code `KEY_EXPIRED` while creating Decrypt
operation using generated key.
Bug: 279721870
Test: atest keystore2_client_tests
Change-Id: I8a0865a6256a6da133e95d0ee8250ba67359a2a2
diff --git a/keystore2/test_utils/Android.bp b/keystore2/test_utils/Android.bp
index 9f3a4e9..a3c40cb 100644
--- a/keystore2/test_utils/Android.bp
+++ b/keystore2/test_utils/Android.bp
@@ -35,6 +35,7 @@
"liblog_rust",
"libnix",
"librand",
+ "librustutils",
"libserde",
"libserde_cbor",
"libthiserror",
@@ -82,7 +83,6 @@
shared_libs: [
"libbase",
"libcrypto",
- "libcppbor_external",
"libkeymaster_portable",
"libkeystore-engine",
"libkeymint_support",
diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs
index 514cbd3..aa75982 100644
--- a/keystore2/test_utils/authorizations.rs
+++ b/keystore2/test_utils/authorizations.rs
@@ -242,6 +242,33 @@
});
self
}
+
+ /// Set active date-time.
+ pub fn active_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::ACTIVE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
+
+ /// Set origination expire date-time.
+ pub fn origination_expire_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::ORIGINATION_EXPIRE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
+
+ /// Set usage expire date-time.
+ pub fn usage_expire_date_time(mut self, date: i64) -> Self {
+ self.0.push(KeyParameter {
+ tag: Tag::USAGE_EXPIRE_DATETIME,
+ value: KeyParameterValue::DateTime(date),
+ });
+ self
+ }
}
impl Deref for AuthSetBuilder {
diff --git a/keystore2/test_utils/ffi_test_utils.cpp b/keystore2/test_utils/ffi_test_utils.cpp
index 1853c07..0740804 100644
--- a/keystore2/test_utils/ffi_test_utils.cpp
+++ b/keystore2/test_utils/ffi_test_utils.cpp
@@ -8,6 +8,7 @@
#include <keymaster/km_openssl/openssl_err.h>
#include <keymaster/km_openssl/openssl_utils.h>
#include <keymint_support/attestation_record.h>
+#include <keymint_support/keymint_utils.h>
#include <openssl/mem.h>
using keymaster::ASN1_OBJECT_Ptr;
@@ -696,3 +697,15 @@
std::move(val.begin(), val.end(), std::back_inserter(cxx_result.data));
return cxx_result;
}
+
+uint32_t getOsVersion() {
+ return aidl::android::hardware::security::keymint::getOsVersion();
+}
+
+uint32_t getOsPatchlevel() {
+ return aidl::android::hardware::security::keymint::getOsPatchlevel();
+}
+
+uint32_t getVendorPatchlevel() {
+ return aidl::android::hardware::security::keymint::getVendorPatchlevel();
+}
diff --git a/keystore2/test_utils/ffi_test_utils.hpp b/keystore2/test_utils/ffi_test_utils.hpp
index 3ed7edc..69f558a 100644
--- a/keystore2/test_utils/ffi_test_utils.hpp
+++ b/keystore2/test_utils/ffi_test_utils.hpp
@@ -11,3 +11,6 @@
CxxResult buildAsn1DerEncodedWrappedKeyDescription();
bool performCryptoOpUsingKeystoreEngine(int64_t grant_id);
CxxResult getValueFromAttestRecord(rust::Vec<rust::u8> cert_buf, int32_t tag);
+uint32_t getOsVersion();
+uint32_t getOsPatchlevel();
+uint32_t getVendorPatchlevel();
diff --git a/keystore2/test_utils/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs
index 95e3160..04d82f1 100644
--- a/keystore2/test_utils/ffi_test_utils.rs
+++ b/keystore2/test_utils/ffi_test_utils.rs
@@ -36,6 +36,9 @@
fn buildAsn1DerEncodedWrappedKeyDescription() -> CxxResult;
fn performCryptoOpUsingKeystoreEngine(grant_id: i64) -> bool;
fn getValueFromAttestRecord(cert_buf: Vec<u8>, tag: i32) -> CxxResult;
+ fn getOsVersion() -> u32;
+ fn getOsPatchlevel() -> u32;
+ fn getVendorPatchlevel() -> u32;
}
}
@@ -102,3 +105,18 @@
}
Err(Error::AttestRecordGetValueFailed)
}
+
+/// Get OS Version
+pub fn get_os_version() -> u32 {
+ ffi::getOsVersion()
+}
+
+/// Get OS Patch Level
+pub fn get_os_patchlevel() -> u32 {
+ ffi::getOsPatchlevel()
+}
+
+/// Get vendor Patch Level
+pub fn get_vendor_patchlevel() -> u32 {
+ ffi::getVendorPatchlevel()
+}
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index 0f9ecbe..24ce6e1 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -15,11 +15,13 @@
//! This module implements test utils to generate various types of keys.
use anyhow::Result;
-
use core::ops::Range;
+use nix::unistd::getuid;
use std::collections::HashSet;
use std::fmt::Write;
+use binder::ThreadState;
+
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
@@ -27,7 +29,8 @@
KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, Tag::Tag,
};
use android_system_keystore2::aidl::android::system::keystore2::{
- AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization, Domain::Domain,
+ AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization,
+ CreateOperationResponse::CreateOperationResponse, Domain::Domain,
IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
};
@@ -35,6 +38,8 @@
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};
+
/// Shell namespace.
pub const SELINUX_SHELL_NAMESPACE: i64 = 1;
/// Vold namespace.
@@ -388,7 +393,12 @@
authorizations.iter().any(|auth| &auth.keyParameter == key_param)
}
-fn check_key_authorizations(authorizations: &[Authorization], expected_params: &[KeyParameter]) {
+/// Verify the given key authorizations with the expected authorizations.
+pub fn check_key_authorizations(
+ authorizations: &[Authorization],
+ expected_params: &[KeyParameter],
+ expected_key_origin: KeyOrigin,
+) {
// Make sure key authorizations contains only `ALLOWED_TAGS_IN_KEY_AUTHS`
authorizations.iter().all(|auth| {
assert!(
@@ -410,6 +420,54 @@
}
true
});
+
+ check_common_auths(authorizations, expected_key_origin);
+}
+
+/// Verify common key authorizations.
+fn check_common_auths(authorizations: &[Authorization], expected_key_origin: KeyOrigin) {
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::OS_VERSION,
+ value: KeyParameterValue::Integer(get_os_version().try_into().unwrap())
+ }
+ ));
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::OS_PATCHLEVEL,
+ value: KeyParameterValue::Integer(get_os_patchlevel().try_into().unwrap())
+ }
+ ));
+
+ // Access denied for finding vendor-patch-level ("ro.vendor.build.security_patch") property
+ // in a test running with `untrusted_app` context. Keeping this check to verify
+ // vendor-patch-level in tests running with `su` context.
+ if getuid().is_root() {
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::VENDOR_PATCHLEVEL,
+ value: KeyParameterValue::Integer(get_vendor_patchlevel().try_into().unwrap())
+ }
+ ));
+ }
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter { tag: Tag::ORIGIN, value: KeyParameterValue::Origin(expected_key_origin) }
+ ));
+ assert!(check_key_param(
+ authorizations,
+ &KeyParameter {
+ tag: Tag::USER_ID,
+ value: KeyParameterValue::Integer(
+ rustutils::users::multiuser_get_user_id(ThreadState::get_calling_uid())
+ .try_into()
+ .unwrap()
+ )
+ }
+ ));
}
/// Generate EC Key using given security level and domain with below key parameters and
@@ -455,7 +513,11 @@
assert!(key_metadata.key.blob.is_some());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(key_metadata)
}
Err(e) => Err(e),
@@ -498,7 +560,7 @@
} else {
assert!(key_metadata.key.blob.is_none());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -560,7 +622,7 @@
|| key_metadata.key.blob.is_none()
);
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
// If `RSA_OAEP_MGF_DIGEST` tag is not mentioned explicitly while generating/importing a key,
// then make sure `RSA_OAEP_MGF_DIGEST` tag with default value (SHA1) must not be included in
// key authorization list.
@@ -617,7 +679,7 @@
// Should not have an attestation record.
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -657,7 +719,7 @@
// Should not have an attestation record.
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(&key_metadata.authorizations, &gen_params, KeyOrigin::GENERATED);
Ok(key_metadata)
}
@@ -742,7 +804,11 @@
// Should have an attestation record.
assert!(attestation_key_metadata.certificateChain.is_some());
- check_key_authorizations(&attestation_key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &attestation_key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(attestation_key_metadata)
}
@@ -777,7 +843,7 @@
// Shouldn't have an attestation record.
assert!(ec_key_metadata.certificateChain.is_none());
- check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params);
+ check_key_authorizations(&ec_key_metadata.authorizations, &ec_gen_params, KeyOrigin::GENERATED);
Ok(ec_key_metadata)
}
@@ -802,7 +868,7 @@
assert!(key_metadata.certificate.is_some());
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -865,7 +931,7 @@
assert!(key_metadata.certificate.is_some());
assert!(key_metadata.certificateChain.is_none());
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -917,7 +983,7 @@
AES_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -976,7 +1042,7 @@
TRIPLE_DES_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -1036,7 +1102,7 @@
HMAC_KEY,
)?;
- check_key_authorizations(&key_metadata.authorizations, &import_params);
+ check_key_authorizations(&key_metadata.authorizations, &import_params, KeyOrigin::IMPORTED);
// Check below auths explicitly, they might not be addd in import parameters.
assert!(check_key_param(
@@ -1188,7 +1254,11 @@
assert!(key_metadata.key.blob.is_some());
}
- check_key_authorizations(&key_metadata.authorizations, &gen_params);
+ check_key_authorizations(
+ &key_metadata.authorizations,
+ &gen_params,
+ KeyOrigin::GENERATED,
+ );
Ok(key_metadata)
}
Err(e) => Err(e),
@@ -1288,3 +1358,51 @@
b"entropy",
)
}
+
+/// Generate Key and validate key characteristics.
+pub fn generate_key(
+ sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+ gen_params: &AuthSetBuilder,
+ alias: &str,
+) -> binder::Result<KeyMetadata> {
+ 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",
+ )?;
+
+ if gen_params.iter().any(|kp| {
+ matches!(
+ kp.value,
+ KeyParameterValue::Algorithm(Algorithm::RSA)
+ | KeyParameterValue::Algorithm(Algorithm::EC)
+ )
+ }) {
+ assert!(key_metadata.certificate.is_some());
+ if gen_params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) {
+ assert!(key_metadata.certificateChain.is_some());
+ }
+ }
+ check_key_authorizations(&key_metadata.authorizations, gen_params, KeyOrigin::GENERATED);
+
+ Ok(key_metadata)
+}
+
+/// Generate a key using given authorizations and create an operation using the generated key.
+pub fn create_key_and_operation(
+ sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+ gen_params: &AuthSetBuilder,
+ op_params: &AuthSetBuilder,
+ alias: &str,
+) -> binder::Result<CreateOperationResponse> {
+ let key_metadata = generate_key(sec_level, gen_params, alias)?;
+
+ sec_level.createOperation(&key_metadata.key, op_params, false)
+}
diff --git a/keystore2/tests/keystore2_client_authorizations_tests.rs b/keystore2/tests/keystore2_client_authorizations_tests.rs
new file mode 100644
index 0000000..e518a1c
--- /dev/null
+++ b/keystore2/tests/keystore2_client_authorizations_tests.rs
@@ -0,0 +1,322 @@
+// Copyright 2023, 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 std::time::SystemTime;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+ Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
+ ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+ SecurityLevel::SecurityLevel,
+};
+
+use keystore2_test_utils::{
+ authorizations, get_keystore_service, key_generations, key_generations::Error,
+};
+
+use crate::keystore2_client_test_utils::{
+ delete_app_key, perform_sample_hmac_sign_verify_op, perform_sample_sym_key_decrypt_op,
+ perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
+};
+
+/// Generate a key with `ACTIVE_DATETIME` set to current time. Test should successfully generate
+/// a key and verify the key characteristics. Test should be able to create a sign operation using
+/// the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_active_datetime_test_success() {
+ 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 active_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())
+ .active_date_time(active_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ );
+
+ assert!(result.is_ok());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ACTIVE_DATETIME` set to future date and time. Test should successfully
+/// generate a key and verify the key characteristics. Try to create a sign operation
+/// using the generated key, test should fail to create an operation with error code
+/// `KEY_NOT_YET_VALID`.
+#[test]
+fn keystore2_gen_key_auth_future_active_datetime_test_op_fail() {
+ 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 future_active_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ 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())
+ .active_date_time(future_active_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::map_ks_error(key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_NOT_YET_VALID), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ORIGINATION_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign operation using the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_future_origination_expire_datetime_test_success() {
+ 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 origination_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ 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())
+ .origination_expire_date_time(origination_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ );
+ assert!(result.is_ok());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `ORIGINATION_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Try to create a sign operation
+/// using the generated key, test should fail to create an operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_origination_expire_datetime_test_op_fail() {
+ 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 origination_expire_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())
+ .origination_expire_date_time(origination_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let result = key_generations::map_ks_error(key_generations::create_key_and_operation(
+ &sec_level,
+ &gen_params,
+ &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+ alias,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a HMAC key with `USAGE_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign and verify operations using the generated key successfully.
+#[test]
+fn keystore2_gen_key_auth_future_usage_expire_datetime_hmac_verify_op_success() {
+ 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 usage_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::HMAC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .key_size(128)
+ .min_mac_length(256)
+ .digest(Digest::SHA_2_256)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_hmac_verify_success";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+
+ perform_sample_hmac_sign_verify_op(&sec_level, &key_metadata.key);
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate a key with `USAGE_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// sign operation successfully and fail while performing verify operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_usage_expire_datetime_hmac_verify_op_fail() {
+ 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 usage_expire_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::HMAC)
+ .purpose(KeyPurpose::SIGN)
+ .purpose(KeyPurpose::VERIFY)
+ .key_size(128)
+ .min_mac_length(256)
+ .digest(Digest::SHA_2_256)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_hamc_verify_fail";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+
+ let result = key_generations::map_ks_error(
+ sec_level.createOperation(
+ &key_metadata.key,
+ &authorizations::AuthSetBuilder::new()
+ .purpose(KeyPurpose::VERIFY)
+ .digest(Digest::SHA_2_256),
+ false,
+ ),
+ );
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate AES key with `USAGE_EXPIRE_DATETIME` set to future date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// Encrypt and Decrypt operations successfully.
+#[test]
+fn keystore2_gen_key_auth_usage_future_expire_datetime_decrypt_op_success() {
+ 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 usage_expire_datetime = duration_since_epoch.as_millis() + (24 * 60 * 60 * 1000);
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::AES)
+ .purpose(KeyPurpose::ENCRYPT)
+ .purpose(KeyPurpose::DECRYPT)
+ .key_size(128)
+ .padding_mode(PaddingMode::PKCS7)
+ .block_mode(BlockMode::ECB)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+ let cipher_text = perform_sample_sym_key_encrypt_op(
+ &sec_level,
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+
+ assert!(cipher_text.is_some());
+
+ let plain_text = perform_sample_sym_key_decrypt_op(
+ &sec_level,
+ &cipher_text.unwrap(),
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+ assert!(plain_text.is_some());
+ assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+ delete_app_key(&keystore2, alias).unwrap();
+}
+
+/// Generate AES key with `USAGE_EXPIRE_DATETIME` set to current date and time. Test should
+/// successfully generate a key and verify the key characteristics. Test should be able to create
+/// Encrypt operation successfully and fail while performing decrypt operation with error code
+/// `KEY_EXPIRED`.
+#[test]
+fn keystore2_gen_key_auth_usage_expire_datetime_decrypt_op_fail() {
+ 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 usage_expire_datetime = duration_since_epoch.as_millis();
+ let gen_params = authorizations::AuthSetBuilder::new()
+ .no_auth_required()
+ .algorithm(Algorithm::AES)
+ .purpose(KeyPurpose::ENCRYPT)
+ .purpose(KeyPurpose::DECRYPT)
+ .key_size(128)
+ .padding_mode(PaddingMode::PKCS7)
+ .block_mode(BlockMode::ECB)
+ .usage_expire_date_time(usage_expire_datetime.try_into().unwrap());
+
+ let alias = "ks_test_auth_tags_test";
+ let key_metadata = key_generations::generate_key(&sec_level, &gen_params, alias).unwrap();
+ let cipher_text = perform_sample_sym_key_encrypt_op(
+ &sec_level,
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ )
+ .unwrap();
+
+ assert!(cipher_text.is_some());
+
+ let result = key_generations::map_ks_error(perform_sample_sym_key_decrypt_op(
+ &sec_level,
+ &cipher_text.unwrap(),
+ PaddingMode::PKCS7,
+ BlockMode::ECB,
+ &mut None,
+ None,
+ &key_metadata.key,
+ ));
+ assert!(result.is_err());
+ assert_eq!(Error::Km(ErrorCode::KEY_EXPIRED), result.unwrap_err());
+ delete_app_key(&keystore2, alias).unwrap();
+}
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 3b6a78c..ac7f19f 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -15,6 +15,7 @@
pub mod keystore2_client_3des_key_tests;
pub mod keystore2_client_aes_key_tests;
pub mod keystore2_client_attest_key_tests;
+pub mod keystore2_client_authorizations_tests;
pub mod keystore2_client_delete_key_tests;
pub mod keystore2_client_ec_key_tests;
pub mod keystore2_client_grant_key_tests;