Add keymaster authorization policy enforcement to keystore.

Bug: 19511945
Change-Id: I76c04e8d3253ba490cedac53bbc75943ec68df1d
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index ae3b1e4..b36f65f 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -67,6 +67,7 @@
 
 #include "auth_token_table.h"
 #include "defaults.h"
+#include "keystore_keymaster_enforcement.h"
 #include "operation.h"
 
 /* KeyStore is a secured storage for key-value pairs. In this implementation,
@@ -2480,6 +2481,26 @@
         keymaster_key_param_set_t outParams = {NULL, 0};
         err = dev->begin(dev, purpose, &key, &inParams, &outParams, &handle);
 
+        // Create a keyid for this key.
+        keymaster::km_id_t keyid;
+        if (!enforcement_policy.CreateKeyId(key, &keyid)) {
+            ALOGE("Failed to create a key ID for authorization checking.");
+            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            return;
+        }
+
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                    0 /* op_handle */,
+                                                    true /* is_begin_operation */);
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+
         // If there are too many operations abort the oldest operation that was
         // started as pruneable and try again.
         while (err == KM_ERROR_TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
@@ -2495,8 +2516,8 @@
             return;
         }
 
-        sp<IBinder> operationToken = mOperationMap.addOperation(handle, purpose, dev, appToken,
-                                                                characteristics.release(),
+        sp<IBinder> operationToken = mOperationMap.addOperation(handle, keyid, purpose, dev,
+                                                                appToken, characteristics.release(),
                                                                 pruneable);
         if (authToken) {
             mOperationMap.setOperationAuthToken(operationToken, authToken);
@@ -2524,7 +2545,9 @@
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
         keymaster_purpose_t purpose;
-        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+        keymaster::km_id_t keyid;
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
@@ -2540,6 +2563,18 @@
         keymaster_blob_t output = {NULL, 0};
         keymaster_key_param_set_t outParams = {NULL, 0};
 
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        result->resultCode =
+                enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths,
+                                                      operation_params, handle,
+                                                      false /* is_begin_operation */);
+        if (result->resultCode) {
+            return;
+        }
+
         keymaster_error_t err = dev->update(dev, handle, &inParams, &input, &consumed, &outParams,
                                             &output);
         result->data.reset(const_cast<uint8_t*>(output.data));
@@ -2562,7 +2597,9 @@
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
         keymaster_purpose_t purpose;
-        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+        keymaster::km_id_t keyid;
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
@@ -2589,6 +2626,18 @@
         keymaster_blob_t input = {signature, signatureLength};
         keymaster_blob_t output = {NULL, 0};
         keymaster_key_param_set_t outParams = {NULL, 0};
+
+        // Check that all key authorization policy requirements are met.
+        keymaster::AuthorizationSet key_auths(characteristics->hw_enforced);
+        key_auths.push_back(characteristics->sw_enforced);
+        keymaster::AuthorizationSet operation_params(inParams);
+        err = enforcement_policy.AuthorizeOperation(purpose, keyid, key_auths, operation_params,
+                                                    handle, false /* is_begin_operation */);
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
+
         err = dev->finish(dev, handle, &inParams, &input, &outParams, &output);
         // Remove the operation regardless of the result
         mOperationMap.removeOperation(token);
@@ -2607,7 +2656,8 @@
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
         keymaster_purpose_t purpose;
-        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
             return KM_ERROR_INVALID_OPERATION_HANDLE;
         }
         mOperationMap.removeOperation(token);
@@ -2629,7 +2679,8 @@
         keymaster_operation_handle_t handle;
         const keymaster_key_characteristics_t* characteristics;
         keymaster_purpose_t purpose;
-        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
+        keymaster::km_id_t keyid;
+        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
             return false;
         }
         const hw_auth_token_t* authToken = NULL;
@@ -2894,7 +2945,9 @@
             keymaster_operation_handle_t handle;
             const keymaster_key_characteristics_t* characteristics = NULL;
             keymaster_purpose_t purpose;
-            if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
+            keymaster::km_id_t keyid;
+            if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev,
+                                            &characteristics)) {
                 return KM_ERROR_INVALID_OPERATION_HANDLE;
             }
             int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
@@ -3034,6 +3087,7 @@
     ::KeyStore* mKeyStore;
     OperationMap mOperationMap;
     keymaster::AuthTokenTable mAuthTokenTable;
+    KeystoreKeymasterEnforcement enforcement_policy;
 };
 
 }; // namespace android