Multi-threaded keystore
This patches changes the keystore to use the asychronous api model for
begin, update, finish, and abort.
Also removes unused class KeystoreArguments (aidl and implementation).
Test: Keystore CTS tests
Bug: 111443219
Change-Id: Icc6def9ff6dbe32193272d7d015079a006ebc430
diff --git a/keystore/keystore_client_impl.cpp b/keystore/keystore_client_impl.cpp
index 6d998ad..18e9eb1 100644
--- a/keystore/keystore_client_impl.cpp
+++ b/keystore/keystore_client_impl.cpp
@@ -16,10 +16,11 @@
#include "keystore/keystore_client_impl.h"
+#include <future>
#include <string>
#include <vector>
-#include <android/security/IKeystoreService.h>
+#include <android/security/keystore/IKeystoreService.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IServiceManager.h>
@@ -30,6 +31,7 @@
#include <keystore/keymaster_types.h>
#include <keystore/keystore_hidl_support.h>
+#include <keystore/keystore_promises.h>
#include "keystore_client.pb.h"
@@ -46,6 +48,7 @@
using android::String16;
using android::security::keymaster::ExportResult;
using android::security::keymaster::OperationResult;
+using android::security::keystore::KeystoreResponse;
using keystore::AuthorizationSet;
using keystore::AuthorizationSetBuilder;
using keystore::KeyCharacteristics;
@@ -57,7 +60,8 @@
KeystoreClientImpl::KeystoreClientImpl() {
service_manager_ = android::defaultServiceManager();
keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
- keystore_ = android::interface_cast<android::security::IKeystoreService>(keystore_binder_);
+ keystore_ =
+ android::interface_cast<android::security::keystore::IKeystoreService>(keystore_binder_);
}
bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
@@ -180,10 +184,21 @@
KeyStoreNativeReturnCode
KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy, int32_t flags) {
- int32_t result;
- auto binder_result = keystore_->addRngEntropy(blob2hidlVec(entropy), flags, &result);
+ int32_t error_code;
+
+ android::sp<KeystoreResponsePromise> promise(new KeystoreResponsePromise());
+ auto future = promise->get_future();
+
+ auto binder_result =
+ keystore_->addRngEntropy(promise, blob2hidlVec(entropy), flags, &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
- return KeyStoreNativeReturnCode(result);
+
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ auto result = future.get();
+
+ return KeyStoreNativeReturnCode(result.response_code());
}
KeyStoreNativeReturnCode
@@ -191,19 +206,26 @@
int32_t flags, AuthorizationSet* hardware_enforced_characteristics,
AuthorizationSet* software_enforced_characteristics) {
String16 key_name16(key_name.data(), key_name.size());
- ::android::security::keymaster::KeyCharacteristics characteristics;
- int32_t result;
+ int32_t error_code;
+ android::sp<KeyCharacteristicsPromise> promise(new KeyCharacteristicsPromise);
+ auto future = promise->get_future();
auto binder_result = keystore_->generateKey(
- key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
- hidl_vec<uint8_t>() /* entropy */, kDefaultUID, flags, &characteristics, &result);
+ promise, key_name16,
+ ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+ hidl_vec<uint8_t>() /* entropy */, kDefaultUID, flags, &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ auto [km_response, characteristics] = future.get();
+
/* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
* There are no references to Parcel memory after that, and ownership of the newly acquired
* memory is with the AuthorizationSet objects. */
*hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
*software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
- return KeyStoreNativeReturnCode(result);
+ return KeyStoreNativeReturnCode(km_response.response_code());
}
KeyStoreNativeReturnCode
@@ -211,18 +233,25 @@
AuthorizationSet* hardware_enforced_characteristics,
AuthorizationSet* software_enforced_characteristics) {
String16 key_name16(key_name.data(), key_name.size());
- ::android::security::keymaster::KeyCharacteristics characteristics;
- int32_t result;
+ int32_t error_code;
+ android::sp<KeyCharacteristicsPromise> promise(new KeyCharacteristicsPromise);
+ auto future = promise->get_future();
auto binder_result = keystore_->getKeyCharacteristics(
- key_name16, android::security::keymaster::KeymasterBlob(),
- android::security::keymaster::KeymasterBlob(), kDefaultUID, &characteristics, &result);
+ promise, key_name16, android::security::keymaster::KeymasterBlob(),
+ android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ auto [km_response, characteristics] = future.get();
/* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
* There are no references to Parcel memory after that, and ownership of the newly acquired
* memory is with the AuthorizationSet objects. */
*hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
*software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
- return KeyStoreNativeReturnCode(result);
+ return KeyStoreNativeReturnCode(km_response.response_code());
}
KeyStoreNativeReturnCode
@@ -232,29 +261,48 @@
AuthorizationSet* software_enforced_characteristics) {
String16 key_name16(key_name.data(), key_name.size());
auto hidlKeyData = blob2hidlVec(key_data);
- ::android::security::keymaster::KeyCharacteristics characteristics;
- int32_t result;
+ int32_t error_code;
+ android::sp<KeyCharacteristicsPromise> promise(new KeyCharacteristicsPromise);
+ auto future = promise->get_future();
auto binder_result = keystore_->importKey(
- key_name16, ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
- (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics, &result);
+ promise, key_name16,
+ ::android::security::keymaster::KeymasterArguments(key_parameters.hidl_data()),
+ (int)key_format, hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &error_code);
+ if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ auto [km_response, characteristics] = future.get();
+
/* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
* There are no references to Parcel memory after that, and ownership of the newly acquired
* memory is with the AuthorizationSet objects. */
*hardware_enforced_characteristics = characteristics.hardwareEnforced.getParameters();
*software_enforced_characteristics = characteristics.softwareEnforced.getParameters();
- return KeyStoreNativeReturnCode(result);
+ return KeyStoreNativeReturnCode(km_response.response_code());
}
KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format,
const std::string& key_name,
std::string* export_data) {
String16 key_name16(key_name.data(), key_name.size());
- ExportResult export_result;
+ int32_t error_code;
+ android::sp<KeystoreExportPromise> promise(new KeystoreExportPromise);
+ auto future = promise->get_future();
auto binder_result = keystore_->exportKey(
- key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(),
- android::security::keymaster::KeymasterBlob(), kDefaultUID, &export_result);
+ promise, key_name16, (int)export_format, android::security::keymaster::KeymasterBlob(),
+ android::security::keymaster::KeymasterBlob(), kDefaultUID, &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ auto export_result = future.get();
+ if (!export_result.resultCode.isOk()) return export_result.resultCode;
+
*export_data = hidlVec2String(export_result.exportData);
+
return export_result.resultCode;
}
@@ -279,12 +327,18 @@
AuthorizationSet* output_parameters, uint64_t* handle) {
android::sp<android::IBinder> token(new android::BBinder);
String16 key_name16(key_name.data(), key_name.size());
- OperationResult result;
+ int32_t error_code;
+ android::sp<OperationResultPromise> promise(new OperationResultPromise{});
+ auto future = promise->get_future();
auto binder_result = keystore_->begin(
- token, key_name16, (int)purpose, true /*pruneable*/,
+ promise, token, key_name16, (int)purpose, true /*pruneable*/,
android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
- hidl_vec<uint8_t>() /* entropy */, kDefaultUID, &result);
+ hidl_vec<uint8_t>() /* entropy */, kDefaultUID, &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ OperationResult result = future.get();
if (result.resultCode.isOk()) {
*handle = getNextVirtualHandle();
active_operations_[*handle] = result.token;
@@ -302,13 +356,19 @@
if (active_operations_.count(handle) == 0) {
return ErrorCode::INVALID_OPERATION_HANDLE;
}
- OperationResult result;
auto hidlInputData = blob2hidlVec(input_data);
+ int32_t error_code;
+ android::sp<OperationResultPromise> promise(new OperationResultPromise{});
+ auto future = promise->get_future();
auto binder_result = keystore_->update(
- active_operations_[handle],
+ promise, active_operations_[handle],
android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
- hidlInputData, &result);
+ hidlInputData, &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+
+ OperationResult result = future.get();
if (result.resultCode.isOk()) {
*num_input_bytes_consumed = result.inputConsumed;
@@ -328,14 +388,19 @@
if (active_operations_.count(handle) == 0) {
return ErrorCode::INVALID_OPERATION_HANDLE;
}
- OperationResult result;
+ int32_t error_code;
auto hidlSignature = blob2hidlVec(signature_to_verify);
+ android::sp<OperationResultPromise> promise(new OperationResultPromise{});
+ auto future = promise->get_future();
auto binder_result = keystore_->finish(
- active_operations_[handle],
+ promise, active_operations_[handle],
android::security::keymaster::KeymasterArguments(input_parameters.hidl_data()),
- (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(), &result);
+ (std::vector<uint8_t>)hidlSignature, hidl_vec<uint8_t>(), &error_code);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
+ KeyStoreNativeReturnCode rc(error_code);
+ if (!rc.isOk()) return rc;
+ OperationResult result = future.get();
if (result.resultCode.isOk()) {
if (result.outParams.size()) {
*output_parameters = result.outParams;
@@ -352,13 +417,18 @@
return ErrorCode::INVALID_OPERATION_HANDLE;
}
int32_t result;
+ android::sp<KeystoreResponsePromise> promise(new KeystoreResponsePromise{});
+ auto future = promise->get_future();
// Current implementation does not return exceptions in android::binder::Status
- auto binder_result = keystore_->abort(active_operations_[handle], &result);
+ auto binder_result = keystore_->abort(promise, active_operations_[handle], &result);
if (!binder_result.isOk()) return ResponseCode::SYSTEM_ERROR;
- if (KeyStoreNativeReturnCode(result).isOk()) {
+ KeyStoreNativeReturnCode rc(result);
+ if (!rc.isOk()) return rc;
+ rc = KeyStoreNativeReturnCode(future.get().response_code());
+ if (rc.isOk()) {
active_operations_.erase(handle);
}
- return KeyStoreNativeReturnCode(result);
+ return rc;
}
bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {