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