Remove legacy functions from IKeystoreService.aidl

In preparation for making the keystore service asynchronous we remove
redundant legacy functionality from the protocol.

This patch removes the functions get_pubkey, sign, verify, generate,
and import_key. Which have long been superseded by exportKey
(get_pubkey), begin/update/finish (sign, verify), generateKey
(generate), and importKey (import_key).

This patch also removes the implementations of these functions from
key_store_service and updates keystore-engine which still used the
legacy functionality.

It also remove the call isOperationAuthorized which was unused.

Test: Keystore CTS tests
Bug: 109769728
Change-Id: I0de359b3e43fd72faa9d1511f84b7c024968c884
diff --git a/keystore-engine/keystore_backend_binder.cpp b/keystore-engine/keystore_backend_binder.cpp
index 79b0ec3..cd407c8 100644
--- a/keystore-engine/keystore_backend_binder.cpp
+++ b/keystore-engine/keystore_backend_binder.cpp
@@ -22,20 +22,61 @@
 
 #include "keystore_backend_binder.h"
 
+#include <android-base/logging.h>
 #include <android/security/IKeystoreService.h>
 #include <binder/IServiceManager.h>
+#include <keystore/KeyCharacteristics.h>
+#include <keystore/KeymasterArguments.h>
+#include <keystore/KeymasterBlob.h>
+#include <keystore/OperationResult.h>
+#include <keystore/keymaster_types.h>
 #include <keystore/keystore.h>
 #include <keystore/keystore_hidl_support.h>
+#include <keystore/keystore_return_types.h>
 
 using android::security::IKeystoreService;
 using namespace android;
-using keystore::blob2hidlVec;
 using keystore::hidl_vec;
 
+using android::hardware::keymaster::V4_0::Algorithm;
+using android::hardware::keymaster::V4_0::authorizationValue;
+using android::hardware::keymaster::V4_0::Digest;
+using android::hardware::keymaster::V4_0::KeyFormat;
+using android::hardware::keymaster::V4_0::KeyParameter;
+using android::hardware::keymaster::V4_0::KeyPurpose;
+using android::hardware::keymaster::V4_0::NullOr;
+using android::hardware::keymaster::V4_0::PaddingMode;
+using android::hardware::keymaster::V4_0::TAG_ALGORITHM;
+using android::hardware::keymaster::V4_0::TAG_DIGEST;
+using android::hardware::keymaster::V4_0::TAG_PADDING;
+using android::security::keymaster::ExportResult;
+using android::security::keymaster::KeyCharacteristics;
+using android::security::keymaster::KeymasterArguments;
+using android::security::keymaster::KeymasterBlob;
+using android::security::keymaster::OperationResult;
+
+using KSReturn = keystore::KeyStoreNativeReturnCode;
+
 namespace {
 const char keystore_service_name[] = "android.security.keystore";
+constexpr int32_t UID_SELF = -1;
 };
 
+#define AT __func__ << ":" << __LINE__ << " "
+
+static NullOr<const Algorithm&> getKeyAlgoritmFromKeyCharacteristics(
+    const ::android::security::keymaster::KeyCharacteristics& characteristics) {
+    for (const auto& param : characteristics.hardwareEnforced.getParameters()) {
+        auto algo = authorizationValue(TAG_ALGORITHM, param);
+        if (algo.isOk()) return algo;
+    }
+    for (const auto& param : characteristics.softwareEnforced.getParameters()) {
+        auto algo = authorizationValue(TAG_ALGORITHM, param);
+        if (algo.isOk()) return algo;
+    }
+    return {};
+}
+
 int32_t KeystoreBackendBinder::sign(const char* key_id, const uint8_t* in, size_t len,
                                     uint8_t** reply, size_t* reply_len) {
     sp<IServiceManager> sm = defaultServiceManager();
@@ -43,20 +84,88 @@
     sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
 
     if (service == nullptr) {
-        ALOGE("could not contact keystore");
+        LOG(ERROR) << AT << "could not contact keystore";
         return -1;
     }
 
-    auto inBlob = blob2hidlVec(in, len);
-    std::vector<uint8_t> reply_vec;
-    auto ret = service->sign(String16(key_id), inBlob, &reply_vec);
-    if (!ret.isOk()) {
+    KeyCharacteristics keyCharacteristics;
+    String16 key_name16(key_id);
+    int32_t aidl_result;
+    auto binder_result = service->getKeyCharacteristics(
+        key_name16, KeymasterBlob(), KeymasterBlob(), UID_SELF, &keyCharacteristics, &aidl_result);
+    if (!binder_result.isOk()) {
+        LOG(ERROR) << AT << "communication error while calling keystore";
+        return -1;
+    }
+    if (KSReturn(aidl_result).isOk()) {
+        LOG(ERROR) << AT << "getKeyCharacteristics failed: " << aidl_result;
+    }
+
+    auto algorithm = getKeyAlgoritmFromKeyCharacteristics(keyCharacteristics);
+    if (!algorithm.isOk()) {
+        LOG(ERROR) << AT << "could not get algorithm from key characteristics";
         return -1;
     }
 
-    hidl_vec<uint8_t> reply_hidl(reply_vec);  // makes copy
-    *reply = reply_hidl.releaseData();
-    *reply_len = reply_vec.size();
+    hidl_vec<KeyParameter> params(3);
+    params[0] = Authorization(TAG_DIGEST, Digest::NONE);
+    params[1] = Authorization(TAG_PADDING, PaddingMode::NONE);
+    params[2] = Authorization(TAG_ALGORITHM, algorithm.value());
+
+    android::sp<android::IBinder> token(new android::BBinder);
+    OperationResult result;
+    binder_result = service->begin(token, key_name16, (int)KeyPurpose::SIGN, true /*pruneable*/,
+                                   KeymasterArguments(params), std::vector<uint8_t>() /* entropy */,
+                                   UID_SELF, &result);
+    if (!binder_result.isOk()) {
+        LOG(ERROR) << AT << "communication error while calling keystore";
+        return -1;
+    }
+    if (!result.resultCode.isOk()) {
+        LOG(ERROR) << AT << "begin failed: " << int32_t(result.resultCode);
+        return -1;
+    }
+    auto handle = std::move(result.token);
+
+    do {
+        binder_result = service->update(handle, KeymasterArguments(params),
+                                        std::vector<uint8_t>(in, in + len), &result);
+        if (!binder_result.isOk()) {
+            LOG(ERROR) << AT << "communication error while calling keystore";
+            return -1;
+        }
+        if (!result.resultCode.isOk()) {
+            LOG(ERROR) << AT << "update failed: " << int32_t(result.resultCode);
+            return -1;
+        }
+        if (result.inputConsumed > len) {
+            LOG(ERROR) << AT << "update consumed more data than provided";
+            service->abort(handle, &aidl_result);
+            return -1;
+        }
+        len -= result.inputConsumed;
+        in += result.inputConsumed;
+    } while (len > 0);
+
+    binder_result =
+        service->finish(handle, KeymasterArguments(params), std::vector<uint8_t>() /* signature */,
+                        std::vector<uint8_t>() /* entropy */, &result);
+    if (!binder_result.isOk()) {
+        LOG(ERROR) << AT << "communication error while calling keystore";
+        return -1;
+    }
+    if (!result.resultCode.isOk()) {
+        LOG(ERROR) << AT << "finish failed: " << int32_t(result.resultCode);
+        return -1;
+    }
+
+    hidl_vec<uint8_t> reply_hidl(result.data);
+    if (reply_len) {
+        *reply_len = reply_hidl.size();
+    }
+    if (reply) {
+        *reply = reply_hidl.releaseData();
+    }
     return 0;
 }
 
@@ -67,18 +176,29 @@
     sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
 
     if (service == nullptr) {
-        ALOGE("could not contact keystore");
+        LOG(ERROR) << AT << "could not contact keystore";
         return -1;
     }
 
-    std::vector<uint8_t> pubkey_vec;
-    auto ret = service->get_pubkey(String16(key_id), &pubkey_vec);
-    if (!ret.isOk()) {
+    ExportResult result;
+    auto binder_result = service->exportKey(String16(key_id), static_cast<int32_t>(KeyFormat::X509),
+                                            KeymasterBlob() /* clientId */,
+                                            KeymasterBlob() /* appData */, UID_SELF, &result);
+    if (!binder_result.isOk()) {
+        LOG(ERROR) << AT << "communication error while calling keystore";
+        return -1;
+    }
+    if (!result.resultCode.isOk()) {
+        LOG(ERROR) << AT << "exportKey failed: " << int32_t(result.resultCode);
         return -1;
     }
 
-    hidl_vec<uint8_t> hidl_pubkey(pubkey_vec);  // makes copy
-    *pubkey = hidl_pubkey.releaseData();        // caller should clean up memory.
-    *pubkey_len = pubkey_vec.size();
+    hidl_vec<uint8_t> reply_hidl(result.exportData);
+    if (pubkey_len) {
+        *pubkey_len = reply_hidl.size();
+    }
+    if (pubkey) {
+        *pubkey = reply_hidl.releaseData();
+    }
     return 0;
 }