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;
}