summaryrefslogtreecommitdiff
path: root/keystore/keymaster_worker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'keystore/keymaster_worker.cpp')
-rw-r--r--keystore/keymaster_worker.cpp1144
1 files changed, 0 insertions, 1144 deletions
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
deleted file mode 100644
index cbb184c2..00000000
--- a/keystore/keymaster_worker.cpp
+++ /dev/null
@@ -1,1144 +0,0 @@
-/*
-**
-** Copyright 2018, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-#define LOG_TAG "keymaster_worker"
-
-#include "keymaster_worker.h"
-
-#include "keystore_utils.h"
-
-#include <android-base/logging.h>
-
-#include <log/log_event_list.h>
-
-#include <private/android_logger.h>
-
-#include "KeyStore.h"
-#include "keymaster_enforcement.h"
-
-#include "key_creation_log_handler.h"
-#include "keystore_utils.h"
-
-#include <chrono>
-
-namespace keystore {
-
-using namespace std::chrono;
-
-constexpr size_t kMaxOperations = 15;
-
-using AndroidKeymasterArguments = android::security::keymaster::KeymasterArguments;
-using android::security::keymaster::ExportResult;
-using android::security::keymaster::operationFailed;
-using android::security::keymaster::OperationResult;
-
-Worker::Worker() {}
-Worker::~Worker() {
- std::unique_lock<std::mutex> lock(pending_requests_mutex_);
- terminate_ = true;
- pending_requests_cond_var_.notify_all();
- pending_requests_cond_var_.wait(lock, [this] { return !running_; });
-}
-void Worker::addRequest(WorkerTask request) {
- std::unique_lock<std::mutex> lock(pending_requests_mutex_);
- bool start_thread = !running_;
- running_ = true;
- pending_requests_.push(std::move(request));
- lock.unlock();
- pending_requests_cond_var_.notify_all();
- if (start_thread) {
- auto worker = std::thread([this] {
- std::unique_lock<std::mutex> lock(pending_requests_mutex_);
- while (running_) {
- // Wait for 30s if the request queue is empty, then kill die.
- // Die immediately if termiate_ was set which happens in the destructor.
- auto status = pending_requests_cond_var_.wait_for(
- lock, 30s, [this]() { return !pending_requests_.empty() || terminate_; });
- if (status && !terminate_) {
- auto request = std::move(pending_requests_.front());
- lock.unlock();
- request();
- lock.lock();
- pending_requests_.pop();
- } else {
- running_ = false;
- }
- pending_requests_cond_var_.notify_all();
- }
- });
- worker.detach();
- }
-}
-
-KeymasterWorker::KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore,
- SecurityLevel internalSecurityLevel)
- : keymasterDevice_(std::move(keymasterDevice)), operationMap_(keyStore), keyStore_(keyStore),
- internalSecurityLevel_(internalSecurityLevel) {
- // make sure that hal version is cached.
- if (keymasterDevice_) keymasterDevice_->halVersion();
-}
-
-void KeymasterWorker::logIfKeymasterVendorError(ErrorCode ec) const {
- keymasterDevice_->logIfKeymasterVendorError(ec);
-}
-
-void KeymasterWorker::deleteOldKeyOnUpgrade(const LockedKeyBlobEntry& blobfile, Blob keyBlob) {
- // if we got the blob successfully, we try and delete it from the keymaster device
- auto& dev = keymasterDevice_;
- uid_t uid = blobfile->uid();
- const auto& alias = blobfile->alias();
-
- if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
- auto ret = KS_HANDLE_HIDL_ERROR(dev, dev->deleteKey(blob2hidlVec(keyBlob)));
- // A device doesn't have to implement delete_key.
- bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
- if (__android_log_security()) {
- android_log_event_list(SEC_TAG_KEY_DESTROYED)
- << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY;
- }
- if (!success) {
- LOG(ERROR) << "Keymaster delete for key " << alias << " of uid " << uid << " failed";
- }
- }
-}
-
-std::tuple<KeyStoreServiceReturnCode, Blob>
-KeymasterWorker::upgradeKeyBlob(const LockedKeyBlobEntry& lockedEntry,
- const AuthorizationSet& params) {
- LOG(INFO) << "upgradeKeyBlob " << lockedEntry->alias() << " " << (uint32_t)lockedEntry->uid();
-
- std::tuple<KeyStoreServiceReturnCode, Blob> result;
-
- auto userState = keyStore_->getUserStateDB().getUserStateByUid(lockedEntry->uid());
-
- Blob& blob = std::get<1>(result);
- KeyStoreServiceReturnCode& error = std::get<0>(result);
-
- Blob charBlob;
- ResponseCode rc;
-
- std::tie(rc, blob, charBlob) =
- lockedEntry.readBlobs(userState->getEncryptionKey(), userState->getState());
-
- userState = {};
-
- if (rc != ResponseCode::NO_ERROR) {
- return error = rc, result;
- }
-
- auto hidlKey = blob2hidlVec(blob);
- auto& dev = keymasterDevice_;
-
- auto hidlCb = [&](ErrorCode ret, const ::std::vector<uint8_t>& upgradedKeyBlob) {
- dev->logIfKeymasterVendorError(ret);
- error = ret;
- if (!error.isOk()) {
- if (error == ErrorCode::INVALID_KEY_BLOB) {
- log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
- }
- return;
- }
-
- Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
- 0 /* infoLength */, ::TYPE_KEYMASTER_10);
- newBlob.setSecurityLevel(blob.getSecurityLevel());
- newBlob.setEncrypted(blob.isEncrypted());
- newBlob.setSuperEncrypted(blob.isSuperEncrypted());
- newBlob.setCriticalToDeviceEncryption(blob.isCriticalToDeviceEncryption());
-
- error = keyStore_->put(lockedEntry, newBlob, charBlob);
- if (!error.isOk()) {
- ALOGI("upgradeKeyBlob keystore->put failed %d", error.getErrorCode());
- return;
- }
-
- deleteOldKeyOnUpgrade(lockedEntry, std::move(blob));
- blob = std::move(newBlob);
- };
-
- KeyStoreServiceReturnCode error2;
- error2 = KS_HANDLE_HIDL_ERROR(dev, dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
- if (!error2.isOk()) {
- return error = error2, result;
- }
-
- return result;
-}
-
-std::tuple<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob>
-KeymasterWorker::createKeyCharacteristicsCache(const LockedKeyBlobEntry& lockedEntry,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData, Blob keyBlob,
- Blob charBlob) {
- std::tuple<KeyStoreServiceReturnCode, KeyCharacteristics, Blob, Blob> result;
-
-#if __cplusplus == 201703L
- auto& [rc, resultCharacteristics, outBlob, charOutBlob] = result;
-#else
- KeyStoreServiceReturnCode& rc = std::get<0>(result);
- KeyCharacteristics& resultCharacteristics = std::get<1>(result);
- Blob& outBlob = std::get<2>(result);
- Blob& charOutBlob = std::get<3>(result);
-#endif
-
- rc = ResponseCode::SYSTEM_ERROR;
- if (!keyBlob) return result;
- auto hidlKeyBlob = blob2hidlVec(keyBlob);
- auto& dev = keymasterDevice_;
-
- KeyStoreServiceReturnCode error;
-
- AuthorizationSet hwEnforced, swEnforced;
- bool success = true;
-
- if (charBlob) {
- std::tie(success, hwEnforced, swEnforced) = charBlob.getKeyCharacteristics();
- }
- if (!success) {
- LOG(ERROR) << "Failed to read cached key characteristics";
- return rc = ResponseCode::SYSTEM_ERROR, result;
- }
-
- auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
- dev->logIfKeymasterVendorError(ret);
- error = ret;
- if (!error.isOk()) {
- if (error == ErrorCode::INVALID_KEY_BLOB) {
- log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
- }
- return;
- }
-
- // Replace the sw_enforced set with those persisted to disk, minus hw_enforced
- AuthorizationSet softwareEnforced = keyCharacteristics.softwareEnforced;
- hwEnforced = keyCharacteristics.hardwareEnforced;
- swEnforced.Union(softwareEnforced);
- softwareEnforced.Subtract(hwEnforced);
-
- // We only get the characteristics from keymaster if there was no cache file or the
- // the chach file was a legacy cache file. So lets write a new cache file for the next time.
- Blob newCharBlob;
- success = newCharBlob.putKeyCharacteristics(hwEnforced, swEnforced);
- if (!success) {
- error = ResponseCode::SYSTEM_ERROR;
- LOG(ERROR) << "Failed to serialize cached key characteristics";
- return;
- }
-
- error = keyStore_->put(lockedEntry, {}, newCharBlob);
- if (!error.isOk()) {
- ALOGE("Failed to write key characteristics cache");
- return;
- }
- charBlob = std::move(newCharBlob);
- };
-
- if (!charBlob || charBlob.getType() == TYPE_KEY_CHARACTERISTICS) {
- // this updates the key characteristics cache file to the new format or creates one in
- // in the first place
- rc = KS_HANDLE_HIDL_ERROR(
- dev, dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
- if (!rc.isOk()) {
- return result;
- }
-
- if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
- AuthorizationSet upgradeParams;
- if (clientId.size()) {
- upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
- }
- if (appData.size()) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
- }
- std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, upgradeParams);
- if (!rc.isOk()) {
- return result;
- }
-
- auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
-
- rc = KS_HANDLE_HIDL_ERROR(
- dev, dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
- if (!rc.isOk()) {
- return result;
- }
- }
- }
-
- resultCharacteristics.hardwareEnforced = hwEnforced.hidl_data();
- resultCharacteristics.softwareEnforced = swEnforced.hidl_data();
-
- outBlob = std::move(keyBlob);
- charOutBlob = std::move(charBlob);
- rc = error;
- return result;
-}
-
-/**
- * Get the auth token for this operation from the auth token table.
- *
- * Returns ResponseCode::NO_ERROR if the auth token was set or none was required.
- * ::OP_AUTH_NEEDED if it is a per op authorization, no
- * authorization token exists for that operation and
- * failOnTokenMissing is false.
- * KM_ERROR_KEY_USER_NOT_AUTHENTICATED if there is no valid auth
- * token for the operation
- */
-std::pair<KeyStoreServiceReturnCode, HardwareAuthToken>
-KeymasterWorker::getAuthToken(const KeyCharacteristics& characteristics, uint64_t handle,
- KeyPurpose purpose, bool failOnTokenMissing) {
-
- AuthorizationSet allCharacteristics(characteristics.softwareEnforced);
- allCharacteristics.append(characteristics.hardwareEnforced.begin(),
- characteristics.hardwareEnforced.end());
-
- HardwareAuthToken authToken;
- AuthTokenTable::Error err;
- std::tie(err, authToken) = keyStore_->getAuthTokenTable().FindAuthorization(
- allCharacteristics, static_cast<KeyPurpose>(purpose), handle);
-
- KeyStoreServiceReturnCode rc;
-
- switch (err) {
- case AuthTokenTable::OK:
- case AuthTokenTable::AUTH_NOT_REQUIRED:
- rc = ResponseCode::NO_ERROR;
- break;
-
- case AuthTokenTable::AUTH_TOKEN_NOT_FOUND:
- case AuthTokenTable::AUTH_TOKEN_EXPIRED:
- case AuthTokenTable::AUTH_TOKEN_WRONG_SID:
- ALOGE("getAuthToken failed: %d", err); // STOPSHIP: debug only, to be removed
- rc = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
- break;
-
- case AuthTokenTable::OP_HANDLE_REQUIRED:
- rc = failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
- : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
- break;
-
- default:
- ALOGE("Unexpected FindAuthorization return value %d", err);
- rc = ErrorCode::INVALID_ARGUMENT;
- }
-
- return {rc, std::move(authToken)};
-}
-
-KeyStoreServiceReturnCode KeymasterWorker::abort(const sp<IBinder>& token,
- ResponseCode reason_for_abort) {
- auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */,
- static_cast<int32_t>(reason_for_abort));
- if (op) {
- keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- return KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
- } else {
- return ErrorCode::INVALID_OPERATION_HANDLE;
- }
-}
-
-/**
- * Prune the oldest pruneable operation.
- */
-bool KeymasterWorker::pruneOperation() {
- sp<IBinder> oldest = operationMap_.getOldestPruneableOperation();
- ALOGD("Trying to prune operation %p", oldest.get());
- size_t op_count_before_abort = operationMap_.getOperationCount();
- // We mostly ignore errors from abort() because all we care about is whether at least
- // one operation has been removed.
- auto rc = abort(oldest, ResponseCode::PRUNED);
- keyStore_->removeOperationDevice(oldest);
- if (operationMap_.getOperationCount() >= op_count_before_abort) {
- ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), rc.getErrorCode());
- return false;
- }
- return true;
-}
-
-// My IDE defines "CAPTURE_MOVE(x) x" because it does not understand generalized lambda captures.
-// It should never be redefined by a build system though.
-#ifndef CAPTURE_MOVE
-#define CAPTURE_MOVE(x) x = std::move(x)
-#endif
-
-void KeymasterWorker::begin(LockedKeyBlobEntry lockedEntry, sp<IBinder> appToken, Blob keyBlob,
- Blob charBlob, bool pruneable, KeyPurpose purpose,
- AuthorizationSet opParams, hidl_vec<uint8_t> entropy,
- worker_begin_cb worker_cb) {
-
- Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(appToken),
- CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob), pruneable, purpose,
- CAPTURE_MOVE(opParams), CAPTURE_MOVE(entropy),
- CAPTURE_MOVE(worker_cb)]() mutable {
- // Concurrently executed
-
- auto& dev = keymasterDevice_;
-
- KeyCharacteristics characteristics;
-
- {
- hidl_vec<uint8_t> clientId;
- hidl_vec<uint8_t> appData;
- for (const auto& param : opParams) {
- if (param.tag == Tag::APPLICATION_ID) {
- clientId = authorizationValue(TAG_APPLICATION_ID, param).value();
- } else if (param.tag == Tag::APPLICATION_DATA) {
- appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
- }
- }
- KeyStoreServiceReturnCode error;
- std::tie(error, characteristics, keyBlob, charBlob) = createKeyCharacteristicsCache(
- lockedEntry, clientId, appData, std::move(keyBlob), std::move(charBlob));
- if (!error.isOk()) {
- worker_cb(operationFailed(error));
- return;
- }
- }
-
- KeyStoreServiceReturnCode rc, authRc;
- HardwareAuthToken authToken;
- std::tie(authRc, authToken) = getAuthToken(characteristics, 0 /* no challenge */, purpose,
- /*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
- // update. Any other auth issues stop here.
- if (!authRc.isOk() && authRc != ResponseCode::OP_AUTH_NEEDED) {
- return worker_cb(operationFailed(authRc));
- }
-
- // Add entropy to the device first.
- if (entropy.size()) {
- rc = KS_HANDLE_HIDL_ERROR(dev, dev->addRngEntropy(entropy));
- if (!rc.isOk()) {
- return worker_cb(operationFailed(rc));
- }
- }
-
- // Create a keyid for this key.
- auto keyid = KeymasterEnforcement::CreateKeyId(blob2hidlVec(keyBlob));
- if (!keyid) {
- ALOGE("Failed to create a key ID for authorization checking.");
- return worker_cb(operationFailed(ErrorCode::UNKNOWN_ERROR));
- }
-
- // Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths = characteristics.hardwareEnforced;
- key_auths.append(characteristics.softwareEnforced.begin(),
- characteristics.softwareEnforced.end());
-
- rc = keyStore_->getEnforcementPolicy().AuthorizeOperation(
- purpose, *keyid, key_auths, opParams, authToken, 0 /* op_handle */,
- true /* is_begin_operation */);
- if (!rc.isOk()) {
- return worker_cb(operationFailed(rc));
- }
-
- // If there are more than kMaxOperations, abort the oldest operation that was started as
- // pruneable.
- while (operationMap_.getOperationCount() >= kMaxOperations) {
- ALOGD("Reached or exceeded concurrent operations limit");
- if (!pruneOperation()) {
- break;
- }
- }
-
- android::security::keymaster::OperationResult result;
-
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
- uint64_t operationHandle) {
- dev->logIfKeymasterVendorError(ret);
- result.resultCode = ret;
- if (!result.resultCode.isOk()) {
- if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) {
- log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
- }
- return;
- }
- result.handle = operationHandle;
- result.outParams = outParams;
- };
-
- do {
- rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob),
- opParams.hidl_data(), authToken, hidlCb));
- if (!rc.isOk()) {
- LOG(ERROR) << "Got error " << rc << " from begin()";
- return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR));
- }
-
- if (result.resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
- std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, opParams);
- if (!rc.isOk()) {
- return worker_cb(operationFailed(rc));
- }
-
- rc = KS_HANDLE_HIDL_ERROR(dev, dev->begin(purpose, blob2hidlVec(keyBlob),
- opParams.hidl_data(), authToken, hidlCb));
- if (!rc.isOk()) {
- LOG(ERROR) << "Got error " << rc << " from begin()";
- return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR));
- }
- }
- // If there are too many operations abort the oldest operation that was
- // started as pruneable and try again.
- } while (result.resultCode == ErrorCode::TOO_MANY_OPERATIONS && pruneOperation());
-
- rc = result.resultCode;
- if (!rc.isOk()) {
- return worker_cb(operationFailed(rc));
- }
-
- // Note: The operation map takes possession of the contents of "characteristics".
- // It is safe to use characteristics after the following line but it will be empty.
- sp<IBinder> operationToken =
- operationMap_.addOperation(result.handle, *keyid, purpose, dev, appToken,
- std::move(characteristics), opParams.hidl_data(), pruneable);
- assert(characteristics.hardwareEnforced.size() == 0);
- assert(characteristics.softwareEnforced.size() == 0);
- result.token = operationToken;
-
- auto operation = operationMap_.getOperation(operationToken);
- if (!operation) {
- return worker_cb(operationFailed(ResponseCode::SYSTEM_ERROR));
- }
-
- if (authRc.isOk() && authToken.mac.size() &&
- dev->halVersion().securityLevel == SecurityLevel::STRONGBOX) {
- operation->authTokenFuture = operation->authTokenPromise.get_future();
- std::weak_ptr<Operation> weak_operation = operation;
-
- auto verifyTokenCB = [weak_operation](KeyStoreServiceReturnCode rc,
- HardwareAuthToken authToken,
- VerificationToken verificationToken) {
- auto operation = weak_operation.lock();
- if (!operation) {
- // operation aborted, nothing to do
- return;
- }
- if (rc.isOk()) {
- operation->authToken = std::move(authToken);
- operation->verificationToken = std::move(verificationToken);
- }
- operation->authTokenPromise.set_value(rc);
- };
- auto teeKmDevice = keyStore_->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
- teeKmDevice->verifyAuthorization(result.handle, {}, std::move(authToken),
- std::move(verifyTokenCB));
- }
-
- // Return the authentication lookup result. If this is a per operation
- // auth'd key then the resultCode will be ::OP_AUTH_NEEDED and the
- // application should get an auth token using the handle before the
- // first call to update, which will fail if keystore hasn't received the
- // auth token.
- if (result.resultCode.isOk()) {
- result.resultCode = authRc;
- }
- return worker_cb(result);
- });
-}
-
-KeyStoreServiceReturnCode
-KeymasterWorker::getOperationAuthTokenIfNeeded(std::shared_ptr<Operation> op) {
- if (!op) return ErrorCode::INVALID_OPERATION_HANDLE;
-
- if (op->authTokenFuture.valid()) {
- LOG(INFO) << "Waiting for verification token";
- op->authTokenFuture.wait();
- auto rc = op->authTokenFuture.get();
- if (!rc.isOk()) {
- return rc;
- }
- op->authTokenFuture = {};
- } else if (!op->hasAuthToken()) {
- KeyStoreServiceReturnCode rc;
- HardwareAuthToken found;
- std::tie(rc, found) = getAuthToken(op->characteristics, op->handle, op->purpose);
- if (!rc.isOk()) return rc;
- op->authToken = std::move(found);
- }
-
- return ResponseCode::NO_ERROR;
-}
-
-namespace {
-
-class Finalize {
- private:
- std::function<void()> f_;
-
- public:
- explicit Finalize(std::function<void()> f) : f_(f) {}
- ~Finalize() {
- if (f_) f_();
- }
- void release() { f_ = {}; }
-};
-
-} // namespace
-
-void KeymasterWorker::update(sp<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> data,
- update_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(params), CAPTURE_MOVE(data),
- CAPTURE_MOVE(worker_cb)]() {
- KeyStoreServiceReturnCode rc;
- auto op = operationMap_.getOperation(token);
- if (!op) {
- return worker_cb(operationFailed(ErrorCode::INVALID_OPERATION_HANDLE));
- }
-
- Finalize abort_operation_in_case_of_error([&] {
- operationMap_.removeOperation(token, false, rc.getErrorCode());
- keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
- });
-
- rc = getOperationAuthTokenIfNeeded(op);
- if (!rc.isOk()) return worker_cb(operationFailed(rc));
-
- // Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(op->characteristics.hardwareEnforced);
- key_auths.append(op->characteristics.softwareEnforced.begin(),
- op->characteristics.softwareEnforced.end());
-
- rc = keyStore_->getEnforcementPolicy().AuthorizeOperation(op->purpose, op->keyid, key_auths,
- params, op->authToken, op->handle,
- false /* is_begin_operation */);
- if (!rc.isOk()) return worker_cb(operationFailed(rc));
-
- OperationResult result;
- auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
- const hidl_vec<KeyParameter>& outParams,
- const ::std::vector<uint8_t>& output) {
- op->device->logIfKeymasterVendorError(ret);
- result.resultCode = ret;
- if (result.resultCode.isOk()) {
- result.inputConsumed = inputConsumed;
- result.outParams = outParams;
- result.data = output;
- }
- };
-
- rc = KS_HANDLE_HIDL_ERROR(op->device,
- op->device->update(op->handle, params.hidl_data(), data,
- op->authToken, op->verificationToken, hidlCb));
-
- // just a reminder: on success result->resultCode was set in the callback. So we only
- // overwrite it if there was a communication error indicated by the ErrorCode.
- if (!rc.isOk()) result.resultCode = rc;
- if (result.resultCode.isOk()) {
- // if everything went well we don't abort the operation.
- abort_operation_in_case_of_error.release();
- }
- return worker_cb(std::move(result));
- });
-}
-
-/**
- * Check that all KeyParameters provided by the application are allowed. Any parameter that keystore
- * adds itself should be disallowed here.
- */
-template <typename ParamsIter>
-static bool checkAllowedOperationParams(ParamsIter begin, const ParamsIter end) {
- while (begin != end) {
- switch (begin->tag) {
- case Tag::ATTESTATION_APPLICATION_ID:
- case Tag::RESET_SINCE_ID_ROTATION:
- return false;
- default:
- break;
- }
- ++begin;
- }
- return true;
-}
-
-void KeymasterWorker::finish(sp<IBinder> token, AuthorizationSet params, hidl_vec<uint8_t> input,
- hidl_vec<uint8_t> signature, hidl_vec<uint8_t> entropy,
- finish_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(params), CAPTURE_MOVE(input),
- CAPTURE_MOVE(signature), CAPTURE_MOVE(entropy),
- CAPTURE_MOVE(worker_cb)]() mutable {
- KeyStoreServiceReturnCode rc;
- auto op = operationMap_.getOperation(token);
- if (!op) {
- return worker_cb(operationFailed(ErrorCode::INVALID_OPERATION_HANDLE));
- }
-
- bool finished = false;
- Finalize abort_operation_in_case_of_error([&] {
- operationMap_.removeOperation(token, finished && rc.isOk(), rc.getErrorCode());
- keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
- if (!finished)
- KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->abort(op->handle));
- });
-
- if (!checkAllowedOperationParams(params.begin(), params.end())) {
- return worker_cb(operationFailed(ErrorCode::INVALID_ARGUMENT));
- }
-
- rc = getOperationAuthTokenIfNeeded(op);
- if (!rc.isOk()) return worker_cb(operationFailed(rc));
-
- // Check that all key authorization policy requirements are met.
- AuthorizationSet key_auths(op->characteristics.hardwareEnforced);
- key_auths.append(op->characteristics.softwareEnforced.begin(),
- op->characteristics.softwareEnforced.end());
-
- if (key_auths.Contains(Tag::TRUSTED_CONFIRMATION_REQUIRED)) {
- hidl_vec<uint8_t> confirmationToken =
- keyStore_->getConfirmationManager().getLatestConfirmationToken();
- if (confirmationToken.size() == 0) {
- LOG(ERROR) << "Confirmation token required but none found";
- return worker_cb(operationFailed(ErrorCode::NO_USER_CONFIRMATION));
- }
- params.push_back(keymaster::TAG_CONFIRMATION_TOKEN, std::move(confirmationToken));
- }
-
- rc = keyStore_->getEnforcementPolicy().AuthorizeOperation(op->purpose, op->keyid, key_auths,
- params, op->authToken, op->handle,
- false /* is_begin_operation */);
- if (!rc.isOk()) return worker_cb(operationFailed(rc));
-
- if (entropy.size()) {
- rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->addRngEntropy(entropy));
- if (!rc.isOk()) {
- return worker_cb(operationFailed(rc));
- }
- }
-
- OperationResult result;
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
- const ::std::vector<uint8_t>& output) {
- op->device->logIfKeymasterVendorError(ret);
- result.resultCode = ret;
- if (result.resultCode.isOk()) {
- result.outParams = outParams;
- result.data = output;
- }
- };
-
- rc = KS_HANDLE_HIDL_ERROR(op->device, op->device->finish(op->handle, params.hidl_data(),
- input, signature, op->authToken,
- op->verificationToken, hidlCb));
-
- if (rc.isOk()) {
- // inform the finalizer that the finish call went through
- finished = true;
- // and what the result was
- rc = result.resultCode;
- } else {
- return worker_cb(operationFailed(rc));
- }
- return worker_cb(std::move(result));
- });
-}
-
-void KeymasterWorker::abort(sp<IBinder> token, abort_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(token), CAPTURE_MOVE(worker_cb)]() {
- return worker_cb(abort(token, ResponseCode::ABORT_CALLED));
- });
-}
-
-void KeymasterWorker::verifyAuthorization(uint64_t challenge, hidl_vec<KeyParameter> params,
- HardwareAuthToken token,
- verifyAuthorization_cb worker_cb) {
- Worker::addRequest([this, challenge, CAPTURE_MOVE(params), CAPTURE_MOVE(token),
- CAPTURE_MOVE(worker_cb)]() {
- KeyStoreServiceReturnCode error;
- VerificationToken verificationToken;
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- keymasterDevice_,
- keymasterDevice_->verifyAuthorization(
- challenge, params, token, [&](ErrorCode ret, const VerificationToken& vToken) {
- keymasterDevice_->logIfKeymasterVendorError(ret);
- error = ret;
- verificationToken = vToken;
- }));
- worker_cb(rc.isOk() ? error : rc, std::move(token), std::move(verificationToken));
- });
-}
-
-void KeymasterWorker::addRngEntropy(hidl_vec<uint8_t> data, addRngEntropy_cb _hidl_cb) {
- addRequest(&Keymaster::addRngEntropy, std::move(_hidl_cb), std::move(data));
-}
-
-namespace {
-bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
- return params.end() !=
- std::find_if(params.begin(), params.end(),
- [&](const KeyParameter& param) { return param.tag == tag; });
-}
-
-bool isAuthenticationBound(const hidl_vec<KeyParameter>& params) {
- return !containsTag(params, Tag::NO_AUTH_REQUIRED);
-}
-} // namespace
-
-void KeymasterWorker::generateKey(LockedKeyBlobEntry lockedEntry, hidl_vec<KeyParameter> keyParams,
- hidl_vec<uint8_t> entropy, int flags, generateKey_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(keyParams),
- CAPTURE_MOVE(entropy), CAPTURE_MOVE(worker_cb), flags]() mutable {
- KeyStoreServiceReturnCode rc =
- KS_HANDLE_HIDL_ERROR(keymasterDevice_, keymasterDevice_->addRngEntropy(entropy));
- if (!rc.isOk()) {
- return worker_cb(rc, {});
- }
-
- SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel;
-
- // Fallback cannot be considered for Strongbox. Further versions restrictions are enforced
- // by KeyStore::getFallbackDevice()
- bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
-
- Finalize logOnFail([&] {
- logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
- rc.getErrorCode());
- });
-
- KeyCharacteristics outCharacteristics;
- KeyStoreServiceReturnCode error;
- auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
- const KeyCharacteristics& keyCharacteristics) {
- keymasterDevice_->logIfKeymasterVendorError(ret);
- error = ret;
- if (!error.isOk()) {
- return;
- }
- consider_fallback = false;
- outCharacteristics = keyCharacteristics;
-
- Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setSecurityLevel(internalSecurityLevel_);
- keyBlob.setCriticalToDeviceEncryption(flags &
- KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
- if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) {
- keyBlob.setSuperEncrypted(true);
- }
- keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-
- AuthorizationSet sw_enforced = keyParams;
- sw_enforced.Subtract(outCharacteristics.hardwareEnforced);
- sw_enforced.Union(outCharacteristics.softwareEnforced);
- sw_enforced.Filter([](const KeyParameter& param) -> bool {
- return !(param.tag == Tag::APPLICATION_DATA || param.tag == Tag::APPLICATION_ID);
- });
- if (!sw_enforced.Contains(Tag::USER_ID)) {
- // Most Java processes don't have access to this tag
- sw_enforced.push_back(keymaster::TAG_USER_ID, get_user_id(lockedEntry->uid()));
- }
- Blob keyCharBlob;
- keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced);
- error = keyStore_->put(lockedEntry, std::move(keyBlob), std::move(keyCharBlob));
- };
-
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
- keymasterDevice_->generateKey(keyParams, hidl_cb));
- if (!rc.isOk()) {
- return worker_cb(rc, {});
- }
-
- if (consider_fallback && !error.isOk()) {
- auto fallback = keyStore_->getFallbackDevice();
- if (!fallback) {
- return worker_cb(error, {});
- }
- // No fallback for 3DES
- for (auto& param : keyParams) {
- auto algorithm = authorizationValue(TAG_ALGORITHM, param);
- if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
- return worker_cb(ErrorCode::UNSUPPORTED_ALGORITHM, {});
- }
- }
-
- // delegate to fallback worker
- fallback->generateKey(std::move(lockedEntry), std::move(keyParams), std::move(entropy),
- flags, std::move(worker_cb));
- // let fallback do the logging
- logOnFail.release();
- return;
- }
-
- if (!error.isOk()) return worker_cb(error, {});
-
- // log on success
- logOnFail.release();
- logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
- error.getErrorCode());
-
- return worker_cb(error, std::move(outCharacteristics));
- });
-}
-
-void KeymasterWorker::generateKey(hidl_vec<KeyParameter> keyParams, generateKey2_cb worker_cb) {
- addRequest(&Keymaster::generateKey, std::move(worker_cb), std::move(keyParams));
-}
-
-void KeymasterWorker::getKeyCharacteristics(LockedKeyBlobEntry lockedEntry,
- hidl_vec<uint8_t> clientId, hidl_vec<uint8_t> appData,
- Blob keyBlob, Blob charBlob,
- getKeyCharacteristics_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(clientId),
- CAPTURE_MOVE(appData), CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob),
- CAPTURE_MOVE(worker_cb)]() {
- auto result = createKeyCharacteristicsCache(lockedEntry, clientId, appData,
- std::move(keyBlob), std::move(charBlob));
- return worker_cb(std::get<0>(result), std::move(std::get<1>(result)));
- });
-}
-
-void KeymasterWorker::importKey(LockedKeyBlobEntry lockedEntry, hidl_vec<KeyParameter> keyParams,
- KeyFormat keyFormat, hidl_vec<uint8_t> keyData, int flags,
- importKey_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), CAPTURE_MOVE(keyParams), keyFormat,
- CAPTURE_MOVE(keyData), flags, CAPTURE_MOVE(worker_cb)]() mutable {
- SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel;
-
- // Fallback cannot be considered for Strongbox. Further versions restrictions are enforced
- // by KeyStore::getFallbackDevice()
- bool consider_fallback = securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
-
- KeyStoreServiceReturnCode error;
- Finalize logOnFail([&] {
- logKeystoreKeyCreationEvent(keyParams, false /*wasCreationSuccessful*/,
- error.getErrorCode());
- });
-
- KeyCharacteristics outCharacteristics;
- auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
- const KeyCharacteristics& keyCharacteristics) {
- keymasterDevice_->logIfKeymasterVendorError(ret);
- error = ret;
- if (!error.isOk()) {
- LOG(INFO) << "importKey failed";
- return;
- }
- consider_fallback = false;
- outCharacteristics = keyCharacteristics;
-
- Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setSecurityLevel(internalSecurityLevel_);
- keyBlob.setCriticalToDeviceEncryption(flags &
- KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
- if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) {
- keyBlob.setSuperEncrypted(true);
- }
- keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
-
- AuthorizationSet sw_enforced = keyParams;
- sw_enforced.Subtract(outCharacteristics.hardwareEnforced);
- sw_enforced.Union(outCharacteristics.softwareEnforced);
- sw_enforced.Filter([](const KeyParameter& param) -> bool {
- return !(param.tag == Tag::APPLICATION_DATA || param.tag == Tag::APPLICATION_ID);
- });
- if (!sw_enforced.Contains(Tag::USER_ID)) {
- // Most Java processes don't have access to this tag
- sw_enforced.push_back(keymaster::TAG_USER_ID, get_user_id(lockedEntry->uid()));
- }
- Blob keyCharBlob;
- keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced);
- error = keyStore_->put(lockedEntry, std::move(keyBlob), std::move(keyCharBlob));
- };
-
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- keymasterDevice_, keymasterDevice_->importKey(keyParams, keyFormat, keyData, hidl_cb));
- if (!rc.isOk()) {
- return worker_cb(rc, {});
- }
-
- if (consider_fallback && !error.isOk()) {
- auto fallback = keyStore_->getFallbackDevice();
- if (!fallback) {
- return worker_cb(error, {});
- }
- // No fallback for 3DES
- for (auto& param : keyParams) {
- auto algorithm = authorizationValue(TAG_ALGORITHM, param);
- if (algorithm.isOk() && algorithm.value() == Algorithm::TRIPLE_DES) {
- return worker_cb(ErrorCode::UNSUPPORTED_ALGORITHM, {});
- }
- }
-
- // delegate to fallback worker
- fallback->importKey(std::move(lockedEntry), std::move(keyParams), keyFormat,
- std::move(keyData), flags, std::move(worker_cb));
- // let fallback to the logging
- logOnFail.release();
- return;
- }
-
- if (!error.isOk()) return worker_cb(error, {});
-
- // log on success
- logOnFail.release();
- logKeystoreKeyCreationEvent(keyParams, true /*wasCreationSuccessful*/,
- error.getErrorCode());
-
- return worker_cb(error, std::move(outCharacteristics));
- });
-}
-
-void KeymasterWorker::importWrappedKey(LockedKeyBlobEntry wrappingLockedEntry,
- LockedKeyBlobEntry wrapppedLockedEntry,
- hidl_vec<uint8_t> wrappedKeyData,
- hidl_vec<uint8_t> maskingKey,
- hidl_vec<KeyParameter> unwrappingParams, Blob wrappingBlob,
- Blob wrappingCharBlob, uint64_t passwordSid,
- uint64_t biometricSid, importWrappedKey_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(wrappingLockedEntry), CAPTURE_MOVE(wrapppedLockedEntry),
- CAPTURE_MOVE(wrappedKeyData), CAPTURE_MOVE(maskingKey),
- CAPTURE_MOVE(unwrappingParams), CAPTURE_MOVE(wrappingBlob),
- CAPTURE_MOVE(wrappingCharBlob), passwordSid, biometricSid,
- CAPTURE_MOVE(worker_cb)]() mutable {
- auto hidlWrappingKey = blob2hidlVec(wrappingBlob);
-
- KeyCharacteristics outCharacteristics;
- KeyStoreServiceReturnCode error;
-
- auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
- const KeyCharacteristics& keyCharacteristics) {
- keymasterDevice_->logIfKeymasterVendorError(ret);
- error = ret;
- if (!error.isOk()) {
- return;
- }
- outCharacteristics = keyCharacteristics;
-
- Blob keyBlob(hidlKeyBlob.data(), hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
- keyBlob.setSecurityLevel(internalSecurityLevel_);
- if (isAuthenticationBound(keyCharacteristics.hardwareEnforced)) {
- keyBlob.setSuperEncrypted(true);
- }
-
- AuthorizationSet sw_enforced = outCharacteristics.softwareEnforced;
- if (!sw_enforced.Contains(Tag::USER_ID)) {
- // Most Java processes don't have access to this tag
- sw_enforced.push_back(keymaster::TAG_USER_ID,
- get_user_id(wrapppedLockedEntry->uid()));
- }
- Blob keyCharBlob;
- keyCharBlob.putKeyCharacteristics(outCharacteristics.hardwareEnforced, sw_enforced);
- error = keyStore_->put(wrapppedLockedEntry, std::move(keyBlob), std::move(keyCharBlob));
- };
-
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- keymasterDevice_, keymasterDevice_->importWrappedKey(
- wrappedKeyData, hidlWrappingKey, maskingKey, unwrappingParams,
- passwordSid, biometricSid, hidlCb));
-
- // possible hidl error
- if (!rc.isOk()) {
- return worker_cb(rc, {});
- }
-
- if (error == ErrorCode::KEY_REQUIRES_UPGRADE) {
- std::tie(rc, wrappingBlob) = upgradeKeyBlob(wrappingLockedEntry, {});
- if (!rc.isOk()) {
- return worker_cb(rc, {});
- }
-
- auto upgradedHidlKeyBlob = blob2hidlVec(wrappingBlob);
-
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
- keymasterDevice_->importWrappedKey(
- wrappedKeyData, upgradedHidlKeyBlob, maskingKey,
- unwrappingParams, passwordSid, biometricSid, hidlCb));
- if (!rc.isOk()) {
- error = rc;
- }
- }
- return worker_cb(error, std::move(outCharacteristics));
- });
-}
-
-void KeymasterWorker::exportKey(LockedKeyBlobEntry lockedEntry, KeyFormat exportFormat,
- hidl_vec<uint8_t> clientId, hidl_vec<uint8_t> appData, Blob keyBlob,
- Blob charBlob, exportKey_cb worker_cb) {
- Worker::addRequest([this, CAPTURE_MOVE(lockedEntry), exportFormat, CAPTURE_MOVE(clientId),
- CAPTURE_MOVE(appData), CAPTURE_MOVE(keyBlob), CAPTURE_MOVE(charBlob),
- CAPTURE_MOVE(worker_cb)]() mutable {
- auto key = blob2hidlVec(keyBlob);
-
- ExportResult result;
- auto hidlCb = [&](ErrorCode ret,
- const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
- keymasterDevice_->logIfKeymasterVendorError(ret);
- result.resultCode = ret;
- if (!result.resultCode.isOk()) {
- if (result.resultCode == ErrorCode::INVALID_KEY_BLOB) {
- log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
- }
- return;
- }
- result.exportData = keyMaterial;
- };
- KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(
- keymasterDevice_,
- keymasterDevice_->exportKey(exportFormat, key, clientId, appData, hidlCb));
-
- // Overwrite result->resultCode only on HIDL error. Otherwise we want the result set in the
- // callback hidlCb.
- if (!rc.isOk()) {
- result.resultCode = rc;
- }
-
- if (result.resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
- AuthorizationSet upgradeParams;
- if (clientId.size()) {
- upgradeParams.push_back(TAG_APPLICATION_ID, clientId);
- }
- if (appData.size()) {
- upgradeParams.push_back(TAG_APPLICATION_DATA, appData);
- }
- std::tie(rc, keyBlob) = upgradeKeyBlob(lockedEntry, upgradeParams);
- if (!rc.isOk()) {
- return worker_cb(std::move(result));
- }
-
- auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);
-
- rc = KS_HANDLE_HIDL_ERROR(keymasterDevice_,
- keymasterDevice_->exportKey(exportFormat, upgradedHidlKeyBlob,
- clientId, appData, hidlCb));
- if (!rc.isOk()) {
- result.resultCode = rc;
- }
- }
- return worker_cb(std::move(result));
- });
-}
-void KeymasterWorker::attestKey(hidl_vec<uint8_t> keyToAttest, hidl_vec<KeyParameter> attestParams,
- attestKey_cb worker_cb) {
- addRequest(&Keymaster::attestKey, std::move(worker_cb), std::move(keyToAttest),
- std::move(attestParams));
-}
-
-void KeymasterWorker::deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb) {
- addRequest(&Keymaster::deleteKey, std::move(_hidl_cb), std::move(keyBlob));
-}
-
-void KeymasterWorker::binderDied(android::wp<IBinder> who) {
- Worker::addRequest([this, who]() {
- auto operations = operationMap_.getOperationsForToken(who.unsafe_get());
- for (const auto& token : operations) {
- abort(token, ResponseCode::BINDER_DIED);
- keyStore_->removeOperationDevice(token);
- }
- });
-}
-
-} // namespace keystore