Keystore 2.0: Revisit Enforcements.

This patch revisits the Keystore 2.0 enforcements module to support
KM4.1 hardware enforced device locked keys.
* Consolidate the background handler into async_task.
* The auth token handler became AuthInfo and was moved into
  enforcements.rs.
* The auth token validity check moved from database.rs to
  enforcements.rs.

Bug: 171503362
Test: Keystore CTS tests
Change-Id: If37d38183901b356242079af812c7a0e1e79abf3
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 943f69f..7f41ae8 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -17,20 +17,19 @@
 //! This crate implements the IKeystoreSecurityLevel interface.
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    Algorithm::Algorithm, HardwareAuthToken::HardwareAuthToken,
-    HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
-    KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
-    KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
+    Algorithm::Algorithm, HardwareAuthenticatorType::HardwareAuthenticatorType,
+    IKeyMintDevice::IKeyMintDevice, KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat,
+    KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel,
+    Tag::Tag,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
     AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
     Domain::Domain, IKeystoreOperation::IKeystoreOperation,
     IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
     IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
-    KeyMetadata::KeyMetadata, KeyParameters::KeyParameters, OperationChallenge::OperationChallenge,
+    KeyMetadata::KeyMetadata, KeyParameters::KeyParameters,
 };
 
-use crate::auth_token_handler::AuthTokenHandler;
 use crate::globals::ENFORCEMENTS;
 use crate::key_parameter::KeyParameter as KsKeyParam;
 use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
@@ -223,34 +222,19 @@
             },
         )?;
 
-        let mut auth_token_for_km: &HardwareAuthToken = &Default::default();
-        let mut auth_token_handler = AuthTokenHandler::NoAuthRequired;
+        let (immediate_hat, mut auth_info) = ENFORCEMENTS
+            .authorize_create(
+                purpose,
+                key_parameters.as_deref(),
+                operation_parameters,
+                // TODO b/178222844 Replace this with the configuration returned by
+                //      KeyMintDevice::getHardwareInfo.
+                //      For now we assume that strongbox implementations need secure timestamps.
+                self.security_level == SecurityLevel::STRONGBOX,
+            )
+            .context("In create_operation.")?;
 
-        // keystore performs authorizations only if the key parameters are loaded above
-        if let Some(ref key_params) = key_parameters {
-            // Note: although currently only one operation parameter is checked in authorizing the
-            // operation, the whole operation_parameter vector is converted into the internal
-            // representation of key parameter because we might need to sanitize operation
-            // parameters (b/175792701)
-            let mut op_params: Vec<KsKeyParam> = Vec::new();
-            for op_param in operation_parameters.iter() {
-                op_params.push(KsKeyParam::new(op_param.into(), self.security_level));
-            }
-            // authorize the operation, and receive an AuthTokenHandler, if authorized, else
-            // propagate the error
-            auth_token_handler = ENFORCEMENTS
-                .authorize_create(
-                    purpose,
-                    key_params.as_slice(),
-                    op_params.as_slice(),
-                    self.security_level,
-                )
-                .context("In create_operation.")?;
-            // if an auth token was found, pass it to keymint
-            if let Some(auth_token) = auth_token_handler.get_auth_token() {
-                auth_token_for_km = auth_token;
-            }
-        }
+        let immediate_hat = immediate_hat.unwrap_or_default();
 
         let km_dev: Box<dyn IKeyMintDevice> = self
             .keymint
@@ -268,7 +252,7 @@
                         purpose,
                         blob,
                         &operation_parameters,
-                        auth_token_for_km,
+                        &immediate_hat,
                     )) {
                         Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
                             self.operation_db.prune(caller_uid)?;
@@ -280,35 +264,11 @@
             )
             .context("In create_operation: Failed to begin operation.")?;
 
-        let mut operation_challenge: Option<OperationChallenge> = None;
-
-        // take actions based on the authorization decision (if any) received via auth token handler
-        match auth_token_handler {
-            AuthTokenHandler::OpAuthRequired => {
-                operation_challenge =
-                    Some(OperationChallenge { challenge: begin_result.challenge });
-                ENFORCEMENTS.insert_to_op_auth_map(begin_result.challenge);
-            }
-            AuthTokenHandler::TimestampRequired(auth_token) => {
-                //request a timestamp token, given the auth token and the challenge
-                auth_token_handler = ENFORCEMENTS
-                    .request_timestamp_token(
-                        auth_token,
-                        OperationChallenge { challenge: begin_result.challenge },
-                    )
-                    .context("In create_operation.")?;
-            }
-            _ => {}
-        }
+        let operation_challenge = auth_info.finalize_create_authorization(begin_result.challenge);
 
         let operation = match begin_result.operation {
             Some(km_op) => {
-                let mut op_challenge_copy: Option<OperationChallenge> = None;
-                if let Some(ref op_challenge) = operation_challenge {
-                    op_challenge_copy = Some(OperationChallenge{challenge: op_challenge.challenge});
-                }
-                self.operation_db.create_operation(km_op, caller_uid,
-                 auth_token_handler, key_parameters, op_challenge_copy)
+                self.operation_db.create_operation(km_op, caller_uid, auth_info)
             },
             None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
         };
@@ -319,8 +279,6 @@
                 .into_interface()
                 .context("In create_operation: Failed to create IKeystoreOperation.")?;
 
-        // TODO we need to the enforcement module to determine if we need to return the challenge.
-        // We return None for now because we don't support auth bound keys yet.
         Ok(CreateOperationResponse {
             iOperation: Some(op_binder),
             operationChallenge: operation_challenge,