/*
**
** 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 "KeyStore.h"
#include "keymaster_enforcement.h"

#include "key_proto_handler.h"
#include "keystore_utils.h"

namespace keystore {

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_);
    pending_requests_cond_var_.wait(lock, [this] { return pending_requests_.empty(); });
}
void Worker::addRequest(WorkerTask request) {
    std::unique_lock<std::mutex> lock(pending_requests_mutex_);
    bool start_thread = pending_requests_.empty();
    pending_requests_.push(std::move(request));
    lock.unlock();
    if (start_thread) {
        auto worker = std::thread([this] {
            std::unique_lock<std::mutex> lock(pending_requests_mutex_);
            running_ = true;
            while (!pending_requests_.empty()) {
                auto request = std::move(pending_requests_.front());
                lock.unlock();
                request();
                lock.lock();
                pending_requests_.pop();
                pending_requests_cond_var_.notify_all();
            }
        });
        worker.detach();
    }
}

KeymasterWorker::KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore)
    : keymasterDevice_(std::move(keymasterDevice)), operationMap_(keyStore), keyStore_(keyStore) {
    // make sure that hal version is cached.
    if (keymasterDevice_) keymasterDevice_->halVersion();
}

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) {
        error = ret;
        if (!error.isOk()) {
            if (error == ErrorCode::INVALID_KEY_BLOB) {
                log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
            }
            return;
        }

        error = keyStore_->del(lockedEntry);
        if (!error.isOk()) {
            ALOGI("upgradeKeyBlob keystore->del failed %d", error.getErrorCode());
            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;
        }
        blob = std::move(newBlob);
    };

    KeyStoreServiceReturnCode error2;
    error2 = KS_HANDLE_HIDL_ERROR(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) {
        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->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->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) {
    auto op = operationMap_.removeOperation(token, false /* wasOpSuccessful */);
    if (op) {
        keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
        return KS_HANDLE_HIDL_ERROR(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);
    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->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) {
            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->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->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);
            keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
            KS_HANDLE_HIDL_ERROR(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) {
            result.resultCode = ret;
            if (result.resultCode.isOk()) {
                result.inputConsumed = inputConsumed;
                result.outParams = outParams;
                result.data = output;
            }
        };

        rc = KS_HANDLE_HIDL_ERROR(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());
            keyStore_->getAuthTokenTable().MarkCompleted(op->handle);
            if (!finished) KS_HANDLE_HIDL_ERROR(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->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) {
            result.resultCode = ret;
            if (result.resultCode.isOk()) {
                result.outParams = outParams;
                result.data = output;
            }
        };

        rc = KS_HANDLE_HIDL_ERROR(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)); });
}

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_->verifyAuthorization(
            challenge, params, token, [&](ErrorCode error_, const VerificationToken& vToken) {
                error = error_;
                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_->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(
            [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });

        KeyCharacteristics outCharacteristics;
        KeyStoreServiceReturnCode error;
        auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
                           const KeyCharacteristics& keyCharacteristics) {
            error = ret;
            if (!error.isOk()) {
                return;
            }
            consider_fallback = false;
            outCharacteristics = keyCharacteristics;

            Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
            keyBlob.setSecurityLevel(securityLevel);
            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_->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();
        uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);

        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;

        Finalize logOnFail(
            [&] { uploadKeyCharacteristicsAsProto(keyParams, false /* wasCreationSuccessful */); });

        KeyCharacteristics outCharacteristics;
        KeyStoreServiceReturnCode error;
        auto hidl_cb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
                           const KeyCharacteristics& keyCharacteristics) {
            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(securityLevel);
            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_->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();
        uploadKeyCharacteristicsAsProto(keyParams, true /* wasCreationSuccessful */);

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

        SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel;

        KeyCharacteristics outCharacteristics;
        KeyStoreServiceReturnCode error;

        auto hidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
                          const KeyCharacteristics& keyCharacteristics) {
            error = ret;
            if (!error.isOk()) {
                return;
            }
            outCharacteristics = keyCharacteristics;

            Blob keyBlob(hidlKeyBlob.data(), hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
            keyBlob.setSecurityLevel(securityLevel);
            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_->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_->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) {
            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_->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_->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::upgradeKey(hidl_vec<uint8_t> keyBlobToUpgrade,
                                 hidl_vec<KeyParameter> upgradeParams, upgradeKey_cb _hidl_cb) {
    addRequest(&Keymaster::upgradeKey, std::move(_hidl_cb), std::move(keyBlobToUpgrade),
               std::move(upgradeParams));
}

void KeymasterWorker::deleteKey(hidl_vec<uint8_t> keyBlob, deleteKey_cb _hidl_cb) {
    addRequest(&Keymaster::deleteKey, std::move(_hidl_cb), std::move(keyBlob));
}
void KeymasterWorker::deleteAllKeys(deleteAllKeys_cb _hidl_cb) {
    addRequest(&Keymaster::deleteAllKeys, std::move(_hidl_cb));
}
void KeymasterWorker::destroyAttestationIds(destroyAttestationIds_cb _hidl_cb) {
    addRequest(&Keymaster::destroyAttestationIds, move(_hidl_cb));
}

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

}  // namespace keystore
