Add keymaster authorization policy enforcement to keystore.

Bug: 19511945
Change-Id: I76c04e8d3253ba490cedac53bbc75943ec68df1d
diff --git a/keystore/Android.mk b/keystore/Android.mk
index 9463f3d..e18b2d8 100644
--- a/keystore/Android.mk
+++ b/keystore/Android.mk
@@ -33,7 +33,8 @@
 	libutils \
 	libselinux \
 	libsoftkeymasterdevice \
-	libkeymaster_messages
+	libkeymaster_messages \
+	libkeymaster1
 LOCAL_MODULE := keystore
 LOCAL_MODULE_TAGS := optional
 LOCAL_C_INCLUES := system/keymaster/
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
diff --git a/keystore/keystore_keymaster_enforcement.h b/keystore/keystore_keymaster_enforcement.h
new file mode 100644
index 0000000..904bf66
--- /dev/null
+++ b/keystore/keystore_keymaster_enforcement.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+#define KEYSTORE_KEYMASTER_ENFORCEMENT_H_
+
+#include <time.h>
+
+#include <keymaster/keymaster_enforcement.h>
+
+/**
+ * This is a specialization of the KeymasterEnforcement class to be used by Keystore to enforce
+ * keymaster requirements on all key operation.
+ */
+class KeystoreKeymasterEnforcement : public keymaster::KeymasterEnforcement {
+  public:
+    KeystoreKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
+
+    uint32_t get_current_time() const override {
+        struct timespec tp;
+        int err = clock_gettime(CLOCK_MONOTONIC, &tp);
+        if (err || tp.tv_sec < 0)
+            return 0;
+        return static_cast<uint32_t>(tp.tv_sec);
+    }
+
+    bool activation_date_valid(uint64_t activation_date) const override {
+        // Convert java date to time_t, non-portably.
+        time_t activation_time = activation_date / 1000;
+        return difftime(time(NULL), activation_time) >= 0;
+    }
+
+    bool expiration_date_passed(uint64_t expiration_date) const override {
+        // Convert jave date to time_t, non-portably.
+        time_t expiration_time = expiration_date / 1000;
+        return difftime(time(NULL), expiration_time) > 0;
+    }
+
+    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const {
+        // Non-secure world cannot check token timeouts because it doesn't have access to the secure
+        // clock.  Assume the token is good.
+        return true;
+    }
+
+    bool ValidateTokenSignature(const hw_auth_token_t&) const override {
+        // Non-secure world cannot validate token signatures because it doesn't have access to the
+        // signing key. Assume the token is good.
+        return true;
+    }
+};
+
+#endif  // KEYSTORE_KEYMASTER_ENFORCEMENT_H_
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 087beff..aa37101 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -25,13 +25,13 @@
 }
 
 sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
-                                       keymaster_purpose_t purpose,
+                                       uint64_t keyid, keymaster_purpose_t purpose,
                                        const keymaster1_device_t* dev,
                                        sp<IBinder> appToken,
                                        keymaster_key_characteristics_t* characteristics,
                                        bool pruneable) {
     sp<IBinder> token = new BBinder();
-    mMap[token] = std::move(Operation(handle, purpose, dev, characteristics, appToken));
+    mMap[token] = std::move(Operation(handle, keyid, purpose, dev, characteristics, appToken));
     if (pruneable) {
         mLru.push_back(token);
     }
@@ -43,7 +43,7 @@
 }
 
 bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
-                                keymaster_purpose_t* outPurpose,
+                                uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
                                 const keymaster1_device_t** outDevice,
                                 const keymaster_key_characteristics_t** outCharacteristics) {
     if (!outHandle || !outDevice) {
@@ -56,6 +56,7 @@
     updateLru(token);
 
     *outHandle = entry->second.handle;
+    *outKeyid = entry->second.keyid;
     *outPurpose = entry->second.purpose;
     *outDevice = entry->second.device;
     if (outCharacteristics) {
@@ -142,11 +143,13 @@
 }
 
 OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
+                                   uint64_t keyid_,
                                    keymaster_purpose_t purpose_,
                                    const keymaster1_device_t* device_,
                                    keymaster_key_characteristics_t* characteristics_,
                                    sp<IBinder> appToken_)
     : handle(handle_),
+      keyid(keyid_),
       purpose(purpose_),
       device(device_),
       characteristics(characteristics_),
diff --git a/keystore/operation.h b/keystore/operation.h
index d0e65a5..6806388 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -47,12 +47,13 @@
 class OperationMap {
 public:
     OperationMap(IBinder::DeathRecipient* deathRecipient);
-    sp<IBinder> addOperation(keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
-                             const keymaster1_device_t* dev, sp<IBinder> appToken,
-                             keymaster_key_characteristics_t* characteristics, bool pruneable);
-    bool hasOperation(sp<IBinder> token);
+    sp<IBinder> addOperation(keymaster_operation_handle_t handle, uint64_t keyid,
+                             keymaster_purpose_t purpose, const keymaster1_device_t* dev,
+                             sp<IBinder> appToken, keymaster_key_characteristics_t* characteristics,
+                             bool pruneable);
     bool getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
-                      keymaster_purpose_t* outPurpose, const keymaster1_device_t** outDev,
+                      uint64_t* outKeyid, keymaster_purpose_t* outPurpose,
+                      const keymaster1_device_t** outDev,
                       const keymaster_key_characteristics_t** outCharacteristics);
     bool removeOperation(sp<IBinder> token);
     bool hasPruneableOperation();
@@ -66,10 +67,11 @@
     void removeOperationTracking(sp<IBinder> token, sp<IBinder> appToken);
     struct Operation {
         Operation();
-        Operation(keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
+        Operation(keymaster_operation_handle_t handle, uint64_t keyid, keymaster_purpose_t purpose,
                   const keymaster1_device_t* device,
                   keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
         keymaster_operation_handle_t handle;
+        uint64_t keyid;
         keymaster_purpose_t purpose;
         const keymaster1_device_t* device;
         Unique_keymaster_key_characteristics characteristics;