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)
+}