Store the key characteristics for operations

Instead of storing the key blob and parsing the characteristics out,
which some implementations might not support, instead call get
characteristics on begin and store that result for subsequent auth
calls.

Change-Id: I75e39ee28cc440e4ed411b2daaa2744085e1aa12
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index f1553cc..a65a34c 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -105,16 +105,6 @@
 };
 typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
 
-struct keymaster_key_blob_t_Delete {
-    void operator()(keymaster_key_blob_t* blob) const {
-        if (blob) {
-            delete[] blob->key_material;
-        }
-        delete blob;
-    }
-};
-typedef  UniquePtr<keymaster_key_blob_t, keymaster_key_blob_t_Delete> Unique_keymaster_key_blob;
-
 static int keymaster_device_initialize(keymaster0_device_t** dev) {
     int rc;
 
@@ -2722,16 +2712,24 @@
         return true;
     }
 
-    int authorizeOperation(const keymaster_key_blob_t& key,
+    int authorizeOperation(const keymaster_key_characteristics_t& characteristics,
                             keymaster_operation_handle_t handle,
                             std::vector<keymaster_key_param_t>* params,
                             bool failOnTokenMissing=true) {
         if (!checkAllowedOperationParams(*params)) {
             return KM_ERROR_INVALID_ARGUMENT;
         }
+        std::vector<keymaster_key_param_t> allCharacteristics;
+        for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
+            allCharacteristics.push_back(characteristics.sw_enforced.params[i]);
+        }
+        for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
+            allCharacteristics.push_back(characteristics.hw_enforced.params[i]);
+        }
         // Check for auth token and add it to the param list if present.
         const hw_auth_token_t* authToken;
-        switch (mAuthTokenTable.FindAuthorization(key, handle, &authToken)) {
+        switch (mAuthTokenTable.FindAuthorization(allCharacteristics.data(),
+                                                  allCharacteristics.size(), handle, &authToken)) {
         case keymaster::AuthTokenTable::OK:
             // Auth token found.
             params->push_back(keymaster_param_blob(KM_TAG_AUTH_TOKEN,
@@ -2756,6 +2754,36 @@
         return KM_ERROR_OK;
     }
 
+    keymaster_error_t getOperationCharacteristics(const keymaster_key_blob_t& key,
+                                    const keymaster1_device_t* dev,
+                                    const std::vector<keymaster_key_param_t>& params,
+                                    keymaster_key_characteristics_t* out) {
+        UniquePtr<keymaster_blob_t> appId;
+        UniquePtr<keymaster_blob_t> appData;
+        for (auto param : params) {
+            if (param.tag == KM_TAG_APPLICATION_ID) {
+                appId.reset(new keymaster_blob_t);
+                appId->data = param.blob.data;
+                appId->data_length = param.blob.data_length;
+            } else if (param.tag == KM_TAG_APPLICATION_DATA) {
+                appData.reset(new keymaster_blob_t);
+                appData->data = param.blob.data;
+                appData->data_length = param.blob.data_length;
+            }
+        }
+        keymaster_key_characteristics_t* result = NULL;
+        if (!dev->get_key_characteristics) {
+            return KM_ERROR_UNIMPLEMENTED;
+        }
+        keymaster_error_t error = dev->get_key_characteristics(dev, &key, appId.get(),
+                                                               appData.get(), &result);
+        if (result) {
+            *out = *result;
+            free(result);
+        }
+        return error;
+    }
+
     void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
                bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
                size_t entropyLength, KeymasterArguments* outParams, OperationResult* result) {
@@ -2786,10 +2814,17 @@
         keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
         keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
         std::vector<keymaster_key_param_t> opParams(params.params);
+        Unique_keymaster_key_characteristics characteristics;
+        characteristics.reset(new keymaster_key_characteristics_t);
+        err = getOperationCharacteristics(key, dev, opParams, characteristics.get());
+        if (err) {
+            result->resultCode = err;
+            return;
+        }
         // Don't require an auth token for the call to begin, authentication can
         // require an operation handle. Update and finish will require the token
         // be present and valid.
-        int32_t authResult = authorizeOperation(key, 0, &opParams,
+        int32_t authResult = authorizeOperation(*characteristics, 0, &opParams,
                                                 /*failOnTokenMissing*/ false);
         if (authResult) {
             result->resultCode = err;
@@ -2833,7 +2868,8 @@
             free(out);
         }
 
-        sp<IBinder> operationToken = mOperationMap.addOperation(handle, dev, appToken, key,
+        sp<IBinder> operationToken = mOperationMap.addOperation(handle, dev, appToken,
+                                                                characteristics.release(),
                                                                 pruneable);
         result->resultCode = ::NO_ERROR;
         result->token = operationToken;
@@ -2844,9 +2880,8 @@
                 size_t dataLength, OperationResult* result) {
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        Unique_keymaster_key_blob key(new keymaster_key_blob_t);
-        *key = {NULL, 0};
-        if (!mOperationMap.getOperation(token, &handle, &dev, key.get())) {
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &dev, &characteristics)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
@@ -2854,7 +2889,7 @@
         size_t output_length = 0;
         size_t consumed = 0;
         std::vector<keymaster_key_param_t> opParams(params.params);
-        int32_t authResult = authorizeOperation(*key, handle, &opParams);
+        int32_t authResult = authorizeOperation(*characteristics, handle, &opParams);
         if (authResult) {
             result->resultCode = authResult;
             return;
@@ -2871,16 +2906,15 @@
                 const uint8_t* signature, size_t signatureLength, OperationResult* result) {
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        Unique_keymaster_key_blob key(new keymaster_key_blob_t);
-        *key = {NULL, 0};
-        if (!mOperationMap.getOperation(token, &handle, &dev, key.get())) {
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &dev, &characteristics)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
         uint8_t* output_buf = NULL;
         size_t output_length = 0;
         std::vector<keymaster_key_param_t> opParams(params.params);
-        int32_t authResult = authorizeOperation(*key, handle, &opParams);
+        int32_t authResult = authorizeOperation(*characteristics, handle, &opParams);
         if (authResult) {
             result->resultCode = authResult;
             return;
@@ -2919,13 +2953,12 @@
     bool isOperationAuthorized(const sp<IBinder>& token) {
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        Unique_keymaster_key_blob key(new keymaster_key_blob_t);
-        *key = {NULL, 0};
-        if(!mOperationMap.getOperation(token, &handle, &dev, key.get())) {
+        const keymaster_key_characteristics_t* characteristics;
+        if (!mOperationMap.getOperation(token, &handle, &dev, &characteristics)) {
             return false;
         }
         std::vector<keymaster_key_param_t> ignored;
-        int32_t authResult = authorizeOperation(*key, handle, &ignored);
+        int32_t authResult = authorizeOperation(*characteristics, handle, &ignored);
         return authResult == KM_ERROR_OK;
     }