Don't check authorizations for pubkey operations.

Bug: 21877150
Change-Id: I43dafb66fc3246f4d8e3bf4743fbdcbe072468d1
diff --git a/keystore/auth_token_table.cpp b/keystore/auth_token_table.cpp
index 98731b3..c6e5843 100644
--- a/keystore/auth_token_table.cpp
+++ b/keystore/auth_token_table.cpp
@@ -60,18 +60,33 @@
     }
 }
 
-inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info) {
-    return key_info.find(TAG_NO_AUTH_REQUIRED) == -1;
+inline bool is_secret_key_operation(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose) {
+    if ((algorithm != KM_ALGORITHM_RSA || algorithm != KM_ALGORITHM_EC))
+        return true;
+    if (purpose == KM_PURPOSE_SIGN || purpose == KM_PURPOSE_DECRYPT)
+        return true;
+    return false;
 }
 
-inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info) {
-    return key_info.find(TAG_AUTH_TIMEOUT) == -1;
+inline bool KeyRequiresAuthentication(const AuthorizationSet& key_info,
+                                      keymaster_purpose_t purpose) {
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+    key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
+    return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_NO_AUTH_REQUIRED) == -1;
+}
+
+inline bool KeyRequiresAuthPerOperation(const AuthorizationSet& key_info,
+                                        keymaster_purpose_t purpose) {
+    keymaster_algorithm_t algorithm = KM_ALGORITHM_AES;
+    key_info.GetTagValue(TAG_ALGORITHM, &algorithm);
+    return is_secret_key_operation(algorithm, purpose) && key_info.find(TAG_AUTH_TIMEOUT) == -1;
 }
 
 AuthTokenTable::Error AuthTokenTable::FindAuthorization(const AuthorizationSet& key_info,
+                                                        keymaster_purpose_t purpose,
                                                         keymaster_operation_handle_t op_handle,
                                                         const hw_auth_token_t** found) {
-    if (!KeyRequiresAuthentication(key_info))
+    if (!KeyRequiresAuthentication(key_info, purpose))
         return AUTH_NOT_REQUIRED;
 
     hw_authenticator_type_t auth_type = HW_AUTH_NONE;
@@ -80,7 +95,7 @@
     std::vector<uint64_t> key_sids;
     ExtractSids(key_info, &key_sids);
 
-    if (KeyRequiresAuthPerOperation(key_info))
+    if (KeyRequiresAuthPerOperation(key_info, purpose))
         return FindAuthPerOpAuthorization(key_sids, auth_type, op_handle, found);
     else
         return FindTimedAuthorization(key_sids, auth_type, key_info, found);
diff --git a/keystore/auth_token_table.h b/keystore/auth_token_table.h
index a63e2d8..24aa774 100644
--- a/keystore/auth_token_table.h
+++ b/keystore/auth_token_table.h
@@ -70,7 +70,7 @@
      *
      * The table retains ownership of the returned object.
      */
-    Error FindAuthorization(const AuthorizationSet& key_info,
+    Error FindAuthorization(const AuthorizationSet& key_info, keymaster_purpose_t purpose,
                             keymaster_operation_handle_t op_handle, const hw_auth_token_t** found);
 
     /**
@@ -84,8 +84,9 @@
      * The table retains ownership of the returned object.
      */
     Error FindAuthorization(const keymaster_key_param_t* params, size_t params_count,
-                            keymaster_operation_handle_t op_handle, const hw_auth_token_t** found) {
-        return FindAuthorization(AuthorizationSet(params, params_count), op_handle, found);
+                            keymaster_purpose_t purpose, keymaster_operation_handle_t op_handle,
+                            const hw_auth_token_t** found) {
+        return FindAuthorization(AuthorizationSet(params, params_count), purpose, op_handle, found);
     }
 
     /**
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 639866c..33fb499 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2454,7 +2454,7 @@
             return;
         }
         const hw_auth_token_t* authToken = NULL;
-        int32_t authResult = getAuthToken(characteristics.get(), 0, &authToken,
+        int32_t authResult = getAuthToken(characteristics.get(), 0, purpose, &authToken,
                                                 /*failOnTokenMissing*/ false);
         // If per-operation auth is needed we need to begin the operation and
         // the client will need to authorize that operation before calling
@@ -2495,7 +2495,7 @@
             return;
         }
 
-        sp<IBinder> operationToken = mOperationMap.addOperation(handle, dev, appToken,
+        sp<IBinder> operationToken = mOperationMap.addOperation(handle, purpose, dev, appToken,
                                                                 characteristics.release(),
                                                                 pruneable);
         if (authToken) {
@@ -2523,7 +2523,8 @@
         }
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        if (!mOperationMap.getOperation(token, &handle, &dev, NULL)) {
+        keymaster_purpose_t purpose;
+        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
@@ -2560,7 +2561,8 @@
         }
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        if (!mOperationMap.getOperation(token, &handle, &dev, NULL)) {
+        keymaster_purpose_t purpose;
+        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
             result->resultCode = KM_ERROR_INVALID_OPERATION_HANDLE;
             return;
         }
@@ -2604,7 +2606,8 @@
     int32_t abort(const sp<IBinder>& token) {
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
-        if (!mOperationMap.getOperation(token, &handle, &dev, NULL)) {
+        keymaster_purpose_t purpose;
+        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, NULL)) {
             return KM_ERROR_INVALID_OPERATION_HANDLE;
         }
         mOperationMap.removeOperation(token);
@@ -2625,7 +2628,8 @@
         const keymaster1_device_t* dev;
         keymaster_operation_handle_t handle;
         const keymaster_key_characteristics_t* characteristics;
-        if (!mOperationMap.getOperation(token, &handle, &dev, &characteristics)) {
+        keymaster_purpose_t purpose;
+        if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
             return false;
         }
         const hw_auth_token_t* authToken = NULL;
@@ -2831,6 +2835,7 @@
      */
     int32_t getAuthToken(const keymaster_key_characteristics_t* characteristics,
                          keymaster_operation_handle_t handle,
+                         keymaster_purpose_t purpose,
                          const hw_auth_token_t** authToken,
                          bool failOnTokenMissing = true) {
 
@@ -2841,9 +2846,8 @@
         for (size_t i = 0; i < characteristics->hw_enforced.length; i++) {
             allCharacteristics.push_back(characteristics->hw_enforced.params[i]);
         }
-        keymaster::AuthTokenTable::Error err =
-                mAuthTokenTable.FindAuthorization(allCharacteristics.data(),
-                                                  allCharacteristics.size(), handle, authToken);
+        keymaster::AuthTokenTable::Error err = mAuthTokenTable.FindAuthorization(
+                allCharacteristics.data(), allCharacteristics.size(), purpose, handle, authToken);
         switch (err) {
             case keymaster::AuthTokenTable::OK:
             case keymaster::AuthTokenTable::AUTH_NOT_REQUIRED:
@@ -2889,10 +2893,11 @@
             const keymaster1_device_t* dev;
             keymaster_operation_handle_t handle;
             const keymaster_key_characteristics_t* characteristics = NULL;
-            if (!mOperationMap.getOperation(token, &handle, &dev, &characteristics)) {
+            keymaster_purpose_t purpose;
+            if (!mOperationMap.getOperation(token, &handle, &purpose, &dev, &characteristics)) {
                 return KM_ERROR_INVALID_OPERATION_HANDLE;
             }
-            int32_t result = getAuthToken(characteristics, handle, &authToken);
+            int32_t result = getAuthToken(characteristics, handle, purpose, &authToken);
             if (result != ::NO_ERROR) {
                 return result;
             }
diff --git a/keystore/operation.cpp b/keystore/operation.cpp
index 74d65f6..087beff 100644
--- a/keystore/operation.cpp
+++ b/keystore/operation.cpp
@@ -25,12 +25,13 @@
 }
 
 sp<IBinder> OperationMap::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) {
     sp<IBinder> token = new BBinder();
-    mMap[token] = std::move(Operation(handle, dev, characteristics, appToken));
+    mMap[token] = std::move(Operation(handle, purpose, dev, characteristics, appToken));
     if (pruneable) {
         mLru.push_back(token);
     }
@@ -42,6 +43,7 @@
 }
 
 bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
+                                keymaster_purpose_t* outPurpose,
                                 const keymaster1_device_t** outDevice,
                                 const keymaster_key_characteristics_t** outCharacteristics) {
     if (!outHandle || !outDevice) {
@@ -54,6 +56,7 @@
     updateLru(token);
 
     *outHandle = entry->second.handle;
+    *outPurpose = entry->second.purpose;
     *outDevice = entry->second.device;
     if (outCharacteristics) {
         *outCharacteristics = entry->second.characteristics.get();
@@ -139,10 +142,12 @@
 }
 
 OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
+                                   keymaster_purpose_t purpose_,
                                    const keymaster1_device_t* device_,
                                    keymaster_key_characteristics_t* characteristics_,
                                    sp<IBinder> appToken_)
     : handle(handle_),
+      purpose(purpose_),
       device(device_),
       characteristics(characteristics_),
       appToken(appToken_) {
diff --git a/keystore/operation.h b/keystore/operation.h
index 07238d1..d0e65a5 100644
--- a/keystore/operation.h
+++ b/keystore/operation.h
@@ -47,11 +47,12 @@
 class OperationMap {
 public:
     OperationMap(IBinder::DeathRecipient* deathRecipient);
-    sp<IBinder> addOperation(keymaster_operation_handle_t handle,
+    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);
     bool getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
-                      const keymaster1_device_t** outDev,
+                      keymaster_purpose_t* outPurpose, const keymaster1_device_t** outDev,
                       const keymaster_key_characteristics_t** outCharacteristics);
     bool removeOperation(sp<IBinder> token);
     bool hasPruneableOperation();
@@ -65,9 +66,11 @@
     void removeOperationTracking(sp<IBinder> token, sp<IBinder> appToken);
     struct Operation {
         Operation();
-        Operation(keymaster_operation_handle_t handle, const keymaster1_device_t* device,
+        Operation(keymaster_operation_handle_t handle, keymaster_purpose_t purpose,
+                  const keymaster1_device_t* device,
                   keymaster_key_characteristics_t* characteristics, sp<IBinder> appToken);
         keymaster_operation_handle_t handle;
+        keymaster_purpose_t purpose;
         const keymaster1_device_t* device;
         Unique_keymaster_key_characteristics characteristics;
         sp<IBinder> appToken;