/*
 * Copyright (C) 2016 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 "keystore"

#include "key_store_service.h"

#include <fcntl.h>
#include <sys/stat.h>

#include <algorithm>
#include <sstream>

#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>

#include <private/android_filesystem_config.h>

#include <android/hardware/keymaster/3.0/IHwKeymasterDevice.h>

#include "defaults.h"
#include "keystore_attestation_id.h"
#include "keystore_keymaster_enforcement.h"
#include "keystore_utils.h"
#include <keystore/keystore_hidl_support.h>

namespace keystore {

using namespace android;

namespace {

constexpr size_t kMaxOperations = 15;
constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
const char* kTimestampFilePath = "timestamp";

struct BIGNUM_Delete {
    void operator()(BIGNUM* p) const { BN_free(p); }
};
typedef std::unique_ptr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;

bool containsTag(const hidl_vec<KeyParameter>& params, Tag tag) {
    return params.end() != std::find_if(params.begin(), params.end(),
                                        [&](auto& param) { return param.tag == tag; });
}

bool isAuthenticationBound(const hidl_vec<KeyParameter>& params) {
    return !containsTag(params, Tag::NO_AUTH_REQUIRED);
}

std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
    struct stat sbuf;
    if (stat(kTimestampFilePath, &sbuf) == 0) {
        double diff_secs = difftime(time(NULL), sbuf.st_ctime);
        return {ResponseCode::NO_ERROR, diff_secs < kIdRotationPeriod};
    }

    if (errno != ENOENT) {
        ALOGE("Failed to stat \"timestamp\" file, with error %d", errno);
        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
    }

    int fd = creat(kTimestampFilePath, 0600);
    if (fd < 0) {
        ALOGE("Couldn't create \"timestamp\" file, with error %d", errno);
        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
    }

    if (close(fd)) {
        ALOGE("Couldn't close \"timestamp\" file, with error %d", errno);
        return {ResponseCode::SYSTEM_ERROR, false /* don't care */};
    }

    return {ResponseCode::NO_ERROR, true};
}

constexpr size_t KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE = 1024;

KeyStoreServiceReturnCode updateParamsForAttestation(uid_t callingUid, AuthorizationSet* params) {
    KeyStoreServiceReturnCode responseCode;
    bool factoryResetSinceIdRotation;
    std::tie(responseCode, factoryResetSinceIdRotation) = hadFactoryResetSinceIdRotation();

    if (!responseCode.isOk()) return responseCode;
    if (factoryResetSinceIdRotation) params->push_back(TAG_RESET_SINCE_ID_ROTATION);

    auto asn1_attestation_id_result = security::gather_attestation_application_id(callingUid);
    if (!asn1_attestation_id_result.isOk()) {
        ALOGE("failed to gather attestation_id");
        return ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
    }
    std::vector<uint8_t>& asn1_attestation_id = asn1_attestation_id_result;

    /*
     * The attestation application ID cannot be longer than
     * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, so we truncate if too long.
     */
    if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) {
        asn1_attestation_id.resize(KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE);
    }

    params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id);

    return ResponseCode::NO_ERROR;
}

}  // anonymous namespace

void KeyStoreService::binderDied(const wp<IBinder>& who) {
    auto operations = mOperationMap.getOperationsForToken(who.unsafe_get());
    for (const auto& token : operations) {
        abort(token);
    }
}

KeyStoreServiceReturnCode KeyStoreService::getState(int32_t userId) {
    if (!checkBinderPermission(P_GET_STATE)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    return ResponseCode(mKeyStore->getState(userId));
}

KeyStoreServiceReturnCode KeyStoreService::get(const String16& name, int32_t uid,
                                               hidl_vec<uint8_t>* item) {
    uid_t targetUid = getEffectiveUid(uid);
    if (!checkBinderPermission(P_GET, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    String8 name8(name);
    Blob keyBlob;

    KeyStoreServiceReturnCode rc =
        mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_GENERIC);
    if (!rc.isOk()) {
        if (item) *item = hidl_vec<uint8_t>();
        return rc;
    }

    // Do not replace this with "if (item) *item = blob2hidlVec(keyBlob)"!
    // blob2hidlVec creates a hidl_vec<uint8_t> that references, but not owns, the data in keyBlob
    // the subsequent assignment (*item = resultBlob) makes a deep copy, so that *item will own the
    // corresponding resources.
    auto resultBlob = blob2hidlVec(keyBlob);
    if (item) {
        *item = resultBlob;
    }

    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::insert(const String16& name,
                                                  const hidl_vec<uint8_t>& item, int targetUid,
                                                  int32_t flags) {
    targetUid = getEffectiveUid(targetUid);
    auto result =
        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!result.isOk()) {
        return result;
    }

    String8 name8(name);
    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_GENERIC));

    Blob keyBlob(&item[0], item.size(), NULL, 0, ::TYPE_GENERIC);
    keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);

    return mKeyStore->put(filename.string(), &keyBlob, get_user_id(targetUid));
}

KeyStoreServiceReturnCode KeyStoreService::del(const String16& name, int targetUid) {
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_DELETE, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    String8 name8(name);
    ALOGI("del %s %d", name8.string(), targetUid);
    auto filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_ANY);
    if (!filename.isOk()) return ResponseCode::KEY_NOT_FOUND;

    ResponseCode result = mKeyStore->del(filename.value().string(), ::TYPE_ANY,
            get_user_id(targetUid));
    if (result != ResponseCode::NO_ERROR) {
        return result;
    }

    filename = mKeyStore->getBlobFileNameIfExists(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS);
    if (filename.isOk()) {
        return mKeyStore->del(filename.value().string(), ::TYPE_KEY_CHARACTERISTICS,
                get_user_id(targetUid));
    }
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::exist(const String16& name, int targetUid) {
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_EXIST, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);
    return filename.isOk() ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND;
}

KeyStoreServiceReturnCode KeyStoreService::list(const String16& prefix, int targetUid,
                                                Vector<String16>* matches) {
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_LIST, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    const String8 prefix8(prefix);
    String8 filename(mKeyStore->getKeyNameForUid(prefix8, targetUid, TYPE_ANY));

    if (mKeyStore->list(filename, matches, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
        return ResponseCode::SYSTEM_ERROR;
    }
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::reset() {
    if (!checkBinderPermission(P_RESET)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    mKeyStore->resetUser(get_user_id(callingUid), false);
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::onUserPasswordChanged(int32_t userId,
                                                                 const String16& password) {
    if (!checkBinderPermission(P_PASSWORD)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    const String8 password8(password);
    // Flush the auth token table to prevent stale tokens from sticking
    // around.
    mAuthTokenTable.Clear();

    if (password.size() == 0) {
        ALOGI("Secure lockscreen for user %d removed, deleting encrypted entries", userId);
        mKeyStore->resetUser(userId, true);
        return ResponseCode::NO_ERROR;
    } else {
        switch (mKeyStore->getState(userId)) {
        case ::STATE_UNINITIALIZED: {
            // generate master key, encrypt with password, write to file,
            // initialize mMasterKey*.
            return mKeyStore->initializeUser(password8, userId);
        }
        case ::STATE_NO_ERROR: {
            // rewrite master key with new password.
            return mKeyStore->writeMasterKey(password8, userId);
        }
        case ::STATE_LOCKED: {
            ALOGE("Changing user %d's password while locked, clearing old encryption", userId);
            mKeyStore->resetUser(userId, true);
            return mKeyStore->initializeUser(password8, userId);
        }
        }
        return ResponseCode::SYSTEM_ERROR;
    }
}

KeyStoreServiceReturnCode KeyStoreService::onUserAdded(int32_t userId, int32_t parentId) {
    if (!checkBinderPermission(P_USER_CHANGED)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    // Sanity check that the new user has an empty keystore.
    if (!mKeyStore->isEmpty(userId)) {
        ALOGW("New user %d's keystore not empty. Clearing old entries.", userId);
    }
    // Unconditionally clear the keystore, just to be safe.
    mKeyStore->resetUser(userId, false);
    if (parentId != -1) {
        // This profile must share the same master key password as the parent profile. Because the
        // password of the parent profile is not known here, the best we can do is copy the parent's
        // master key and master key file. This makes this profile use the same master key as the
        // parent profile, forever.
        return mKeyStore->copyMasterKey(parentId, userId);
    } else {
        return ResponseCode::NO_ERROR;
    }
}

KeyStoreServiceReturnCode KeyStoreService::onUserRemoved(int32_t userId) {
    if (!checkBinderPermission(P_USER_CHANGED)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    mKeyStore->resetUser(userId, false);
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::lock(int32_t userId) {
    if (!checkBinderPermission(P_LOCK)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    State state = mKeyStore->getState(userId);
    if (state != ::STATE_NO_ERROR) {
        ALOGD("calling lock in state: %d", state);
        return ResponseCode(state);
    }

    mKeyStore->lock(userId);
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::unlock(int32_t userId, const String16& pw) {
    if (!checkBinderPermission(P_UNLOCK)) {
        return ResponseCode::PERMISSION_DENIED;
    }

    State state = mKeyStore->getState(userId);
    if (state != ::STATE_LOCKED) {
        switch (state) {
        case ::STATE_NO_ERROR:
            ALOGI("calling unlock when already unlocked, ignoring.");
            break;
        case ::STATE_UNINITIALIZED:
            ALOGE("unlock called on uninitialized keystore.");
            break;
        default:
            ALOGE("unlock called on keystore in unknown state: %d", state);
            break;
        }
        return ResponseCode(state);
    }

    const String8 password8(pw);
    // read master key, decrypt with password, initialize mMasterKey*.
    return mKeyStore->readMasterKey(password8, userId);
}

bool KeyStoreService::isEmpty(int32_t userId) {
    if (!checkBinderPermission(P_IS_EMPTY)) {
        return false;
    }

    return mKeyStore->isEmpty(userId);
}

KeyStoreServiceReturnCode KeyStoreService::generate(const String16& name, int32_t targetUid,
                                                    int32_t keyType, int32_t keySize, int32_t flags,
                                                    Vector<sp<KeystoreArg>>* args) {
    targetUid = getEffectiveUid(targetUid);
    auto result =
        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!result.isOk()) {
        return result;
    }

    keystore::AuthorizationSet params;
    add_legacy_key_authorizations(keyType, &params);

    switch (keyType) {
    case EVP_PKEY_EC: {
        params.push_back(TAG_ALGORITHM, Algorithm::EC);
        if (keySize == -1) {
            keySize = EC_DEFAULT_KEY_SIZE;
        } else if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) {
            ALOGI("invalid key size %d", keySize);
            return ResponseCode::SYSTEM_ERROR;
        }
        params.push_back(TAG_KEY_SIZE, keySize);
        break;
    }
    case EVP_PKEY_RSA: {
        params.push_back(TAG_ALGORITHM, Algorithm::RSA);
        if (keySize == -1) {
            keySize = RSA_DEFAULT_KEY_SIZE;
        } else if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) {
            ALOGI("invalid key size %d", keySize);
            return ResponseCode::SYSTEM_ERROR;
        }
        params.push_back(TAG_KEY_SIZE, keySize);
        unsigned long exponent = RSA_DEFAULT_EXPONENT;
        if (args->size() > 1) {
            ALOGI("invalid number of arguments: %zu", args->size());
            return ResponseCode::SYSTEM_ERROR;
        } else if (args->size() == 1) {
            const sp<KeystoreArg>& expArg = args->itemAt(0);
            if (expArg != NULL) {
                Unique_BIGNUM pubExpBn(BN_bin2bn(
                    reinterpret_cast<const unsigned char*>(expArg->data()), expArg->size(), NULL));
                if (pubExpBn.get() == NULL) {
                    ALOGI("Could not convert public exponent to BN");
                    return ResponseCode::SYSTEM_ERROR;
                }
                exponent = BN_get_word(pubExpBn.get());
                if (exponent == 0xFFFFFFFFL) {
                    ALOGW("cannot represent public exponent as a long value");
                    return ResponseCode::SYSTEM_ERROR;
                }
            } else {
                ALOGW("public exponent not read");
                return ResponseCode::SYSTEM_ERROR;
            }
        }
        params.push_back(TAG_RSA_PUBLIC_EXPONENT, exponent);
        break;
    }
    default: {
        ALOGW("Unsupported key type %d", keyType);
        return ResponseCode::SYSTEM_ERROR;
    }
    }

    auto rc = generateKey(name, params.hidl_data(), hidl_vec<uint8_t>(), targetUid, flags,
                          /*outCharacteristics*/ NULL);
    if (!rc.isOk()) {
        ALOGW("generate failed: %d", int32_t(rc));
    }
    return translateResultToLegacyResult(rc);
}

KeyStoreServiceReturnCode KeyStoreService::import(const String16& name,
                                                  const hidl_vec<uint8_t>& data, int targetUid,
                                                  int32_t flags) {

    const uint8_t* ptr = &data[0];

    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &ptr, data.size()));
    if (!pkcs8.get()) {
        return ResponseCode::SYSTEM_ERROR;
    }
    Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
    if (!pkey.get()) {
        return ResponseCode::SYSTEM_ERROR;
    }
    int type = EVP_PKEY_type(pkey->type);
    AuthorizationSet params;
    add_legacy_key_authorizations(type, &params);
    switch (type) {
    case EVP_PKEY_RSA:
        params.push_back(TAG_ALGORITHM, Algorithm::RSA);
        break;
    case EVP_PKEY_EC:
        params.push_back(TAG_ALGORITHM, Algorithm::EC);
        break;
    default:
        ALOGW("Unsupported key type %d", type);
        return ResponseCode::SYSTEM_ERROR;
    }

    auto rc = importKey(name, params.hidl_data(), KeyFormat::PKCS8, data, targetUid, flags,
                        /*outCharacteristics*/ NULL);

    if (!rc.isOk()) {
        ALOGW("importKey failed: %d", int32_t(rc));
    }
    return translateResultToLegacyResult(rc);
}

KeyStoreServiceReturnCode KeyStoreService::sign(const String16& name, const hidl_vec<uint8_t>& data,
                                                hidl_vec<uint8_t>* out) {
    if (!checkBinderPermission(P_SIGN)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    return doLegacySignVerify(name, data, out, hidl_vec<uint8_t>(), KeyPurpose::SIGN);
}

KeyStoreServiceReturnCode KeyStoreService::verify(const String16& name,
                                                  const hidl_vec<uint8_t>& data,
                                                  const hidl_vec<uint8_t>& signature) {
    if (!checkBinderPermission(P_VERIFY)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    return doLegacySignVerify(name, data, nullptr, signature, KeyPurpose::VERIFY);
}

/*
 * TODO: The abstraction between things stored in hardware and regular blobs
 * of data stored on the filesystem should be moved down to keystore itself.
 * Unfortunately the Java code that calls this has naming conventions that it
 * knows about. Ideally keystore shouldn't be used to store random blobs of
 * data.
 *
 * Until that happens, it's necessary to have a separate "get_pubkey" and
 * "del_key" since the Java code doesn't really communicate what it's
 * intentions are.
 */
KeyStoreServiceReturnCode KeyStoreService::get_pubkey(const String16& name,
                                                      hidl_vec<uint8_t>* pubKey) {
    ExportResult result;
    exportKey(name, KeyFormat::X509, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF, &result);
    if (!result.resultCode.isOk()) {
        ALOGW("export failed: %d", int32_t(result.resultCode));
        return translateResultToLegacyResult(result.resultCode);
    }

    if (pubKey) *pubKey = std::move(result.exportData);
    return ResponseCode::NO_ERROR;
}

String16 KeyStoreService::grant(const String16& name, int32_t granteeUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
    if (!result.isOk()) {
        return String16();
    }

    String8 name8(name);
    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));

    if (access(filename.string(), R_OK) == -1) {
        return String16();
    }

    return String16(mKeyStore->addGrant(String8(name).string(), callingUid, granteeUid).c_str());
}

KeyStoreServiceReturnCode KeyStoreService::ungrant(const String16& name, int32_t granteeUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    auto result = checkBinderPermissionAndKeystoreState(P_GRANT);
    if (!result.isOk()) {
        return result;
    }

    String8 name8(name);
    String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, callingUid, ::TYPE_ANY));

    if (access(filename.string(), R_OK) == -1) {
        return (errno != ENOENT) ? ResponseCode::SYSTEM_ERROR : ResponseCode::KEY_NOT_FOUND;
    }

    return mKeyStore->removeGrant(name8, callingUid, granteeUid) ? ResponseCode::NO_ERROR
                                                     : ResponseCode::KEY_NOT_FOUND;
}

int64_t KeyStoreService::getmtime(const String16& name, int32_t uid) {
    uid_t targetUid = getEffectiveUid(uid);
    if (!checkBinderPermission(P_GET, targetUid)) {
        ALOGW("permission denied for %d: getmtime", targetUid);
        return -1L;
    }

    auto filename = mKeyStore->getBlobFileNameIfExists(String8(name), targetUid, ::TYPE_ANY);

    if (!filename.isOk()) {
        ALOGW("could not access %s for getmtime", filename.value().string());
        return -1L;
    }

    int fd = TEMP_FAILURE_RETRY(open(filename.value().string(), O_NOFOLLOW, O_RDONLY));
    if (fd < 0) {
        ALOGW("could not open %s for getmtime", filename.value().string());
        return -1L;
    }

    struct stat s;
    int ret = fstat(fd, &s);
    close(fd);
    if (ret == -1) {
        ALOGW("could not stat %s for getmtime", filename.value().string());
        return -1L;
    }

    return static_cast<int64_t>(s.st_mtime);
}

// TODO(tuckeris): This is dead code, remove it.  Don't bother copying over key characteristics here
KeyStoreServiceReturnCode KeyStoreService::duplicate(const String16& srcKey, int32_t srcUid,
                                                     const String16& destKey, int32_t destUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    pid_t spid = IPCThreadState::self()->getCallingPid();
    if (!has_permission(callingUid, P_DUPLICATE, spid)) {
        ALOGW("permission denied for %d: duplicate", callingUid);
        return ResponseCode::PERMISSION_DENIED;
    }

    State state = mKeyStore->getState(get_user_id(callingUid));
    if (!isKeystoreUnlocked(state)) {
        ALOGD("calling duplicate in state: %d", state);
        return ResponseCode(state);
    }

    if (srcUid == -1 || static_cast<uid_t>(srcUid) == callingUid) {
        srcUid = callingUid;
    } else if (!is_granted_to(callingUid, srcUid)) {
        ALOGD("migrate not granted from source: %d -> %d", callingUid, srcUid);
        return ResponseCode::PERMISSION_DENIED;
    }

    if (destUid == -1) {
        destUid = callingUid;
    }

    if (srcUid != destUid) {
        if (static_cast<uid_t>(srcUid) != callingUid) {
            ALOGD("can only duplicate from caller to other or to same uid: "
                  "calling=%d, srcUid=%d, destUid=%d",
                  callingUid, srcUid, destUid);
            return ResponseCode::PERMISSION_DENIED;
        }

        if (!is_granted_to(callingUid, destUid)) {
            ALOGD("duplicate not granted to dest: %d -> %d", callingUid, destUid);
            return ResponseCode::PERMISSION_DENIED;
        }
    }

    String8 source8(srcKey);
    String8 sourceFile(mKeyStore->getKeyNameForUidWithDir(source8, srcUid, ::TYPE_ANY));

    String8 target8(destKey);
    String8 targetFile(mKeyStore->getKeyNameForUidWithDir(target8, destUid, ::TYPE_ANY));

    if (access(targetFile.string(), W_OK) != -1 || errno != ENOENT) {
        ALOGD("destination already exists: %s", targetFile.string());
        return ResponseCode::SYSTEM_ERROR;
    }

    Blob keyBlob;
    ResponseCode responseCode =
        mKeyStore->get(sourceFile.string(), &keyBlob, TYPE_ANY, get_user_id(srcUid));
    if (responseCode != ResponseCode::NO_ERROR) {
        return responseCode;
    }

    return mKeyStore->put(targetFile.string(), &keyBlob, get_user_id(destUid));
}

int32_t KeyStoreService::is_hardware_backed(const String16& keyType) {
    return mKeyStore->isHardwareBacked(keyType) ? 1 : 0;
}

KeyStoreServiceReturnCode KeyStoreService::clear_uid(int64_t targetUid64) {
    uid_t targetUid = getEffectiveUid(targetUid64);
    if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    ALOGI("clear_uid %" PRId64, targetUid64);

    mKeyStore->removeAllGrantsToUid(targetUid);

    String8 prefix = String8::format("%u_", targetUid);
    Vector<String16> aliases;
    if (mKeyStore->list(prefix, &aliases, get_user_id(targetUid)) != ResponseCode::NO_ERROR) {
        return ResponseCode::SYSTEM_ERROR;
    }

    for (uint32_t i = 0; i < aliases.size(); i++) {
        String8 name8(aliases[i]);
        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_ANY));

        if (get_app_id(targetUid) == AID_SYSTEM) {
            Blob keyBlob;
            ResponseCode responseCode =
                mKeyStore->get(filename.string(), &keyBlob, ::TYPE_ANY, get_user_id(targetUid));
            if (responseCode == ResponseCode::NO_ERROR && keyBlob.isCriticalToDeviceEncryption()) {
                // Do not clear keys critical to device encryption under system uid.
                continue;
            }
        }

        mKeyStore->del(filename.string(), ::TYPE_ANY, get_user_id(targetUid));

        // del() will fail silently if no cached characteristics are present for this alias.
        String8 chr_filename(
            mKeyStore->getKeyNameForUidWithDir(name8, targetUid, ::TYPE_KEY_CHARACTERISTICS));
        mKeyStore->del(chr_filename.string(), ::TYPE_KEY_CHARACTERISTICS, get_user_id(targetUid));
    }
    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::addRngEntropy(const hidl_vec<uint8_t>& entropy) {
    const auto& device = mKeyStore->getDevice();
    return KS_HANDLE_HIDL_ERROR(device->addRngEntropy(entropy));
}

KeyStoreServiceReturnCode KeyStoreService::generateKey(const String16& name,
                                                       const hidl_vec<KeyParameter>& params,
                                                       const hidl_vec<uint8_t>& entropy, int uid,
                                                       int flags,
                                                       KeyCharacteristics* outCharacteristics) {
    // TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
    uid_t originalUid = IPCThreadState::self()->getCallingUid();
    uid = getEffectiveUid(uid);
    KeyStoreServiceReturnCode rc =
        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!rc.isOk()) {
        return rc;
    }
    if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
        return ResponseCode::PERMISSION_DENIED;
    }
    if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
        if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
              originalUid != IPCThreadState::self()->getCallingUid()) {
            return ResponseCode::PERMISSION_DENIED;
        }
    }

    bool usingFallback = false;
    auto& dev = mKeyStore->getDevice();
    AuthorizationSet keyCharacteristics = params;

    // TODO: Seed from Linux RNG before this.
    rc = addRngEntropy(entropy);
    if (!rc.isOk()) {
        return rc;
    }

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

        // Write the key
        String8 name8(name);
        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));

        Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
        keyBlob.setFallback(usingFallback);
        keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
        if (isAuthenticationBound(params) && !keyBlob.isCriticalToDeviceEncryption()) {
            keyBlob.setSuperEncrypted(true);
        }
        keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);

        error = mKeyStore->put(filename.string(), &keyBlob, get_user_id(uid));
    };

    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(params, hidl_cb));
    if (!rc.isOk()) {
        return rc;
    }
    if (!error.isOk()) {
        ALOGE("Failed to generate key -> falling back to software keymaster");
        usingFallback = true;
        auto fallback = mKeyStore->getFallbackDevice();
        if (!fallback.isOk()) {
            return error;
        }
        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->generateKey(params, hidl_cb));
        if (!rc.isOk()) {
            return rc;
        }
        if (!error.isOk()) {
            return error;
        }
    }

    // Write the characteristics:
    String8 name8(name);
    String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));

    std::stringstream kc_stream;
    keyCharacteristics.Serialize(&kc_stream);
    if (kc_stream.bad()) {
        return ResponseCode::SYSTEM_ERROR;
    }
    auto kc_buf = kc_stream.str();
    Blob charBlob(reinterpret_cast<const uint8_t*>(kc_buf.data()), kc_buf.size(), NULL, 0,
                  ::TYPE_KEY_CHARACTERISTICS);
    charBlob.setFallback(usingFallback);
    charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);

    return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
}

KeyStoreServiceReturnCode
KeyStoreService::getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
                                       const hidl_vec<uint8_t>& appData, int32_t uid,
                                       KeyCharacteristics* outCharacteristics) {
    if (!outCharacteristics) {
        return ErrorCode::UNEXPECTED_NULL_POINTER;
    }

    uid_t targetUid = getEffectiveUid(uid);
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    if (!is_granted_to(callingUid, targetUid)) {
        ALOGW("uid %d not permitted to act for uid %d in getKeyCharacteristics", callingUid,
              targetUid);
        return ResponseCode::PERMISSION_DENIED;
    }

    Blob keyBlob;
    String8 name8(name);

    KeyStoreServiceReturnCode rc =
        mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
    if (rc == ResponseCode::UNINITIALIZED) {
        /*
         * If we fail reading the blob because the master key is missing we try to retrieve the
         * key characteristics from the characteristics file. This happens when auth-bound
         * keys are used after a screen lock has been removed by the user.
         */
        rc = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
        if (!rc.isOk()) {
            return rc;
        }
        AuthorizationSet keyCharacteristics;
        // TODO write one shot stream buffer to avoid copying (twice here)
        std::string charBuffer(reinterpret_cast<const char*>(keyBlob.getValue()),
                               keyBlob.getLength());
        std::stringstream charStream(charBuffer);
        keyCharacteristics.Deserialize(&charStream);

        outCharacteristics->softwareEnforced = keyCharacteristics.hidl_data();
        return rc;
    } else if (!rc.isOk()) {
        return rc;
    }

    auto hidlKeyBlob = blob2hidlVec(keyBlob);
    auto& dev = mKeyStore->getDevice(keyBlob);

    KeyStoreServiceReturnCode error;

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

    rc = KS_HANDLE_HIDL_ERROR(dev->getKeyCharacteristics(hidlKeyBlob, clientId, appData, hidlCb));
    if (!rc.isOk()) {
        return rc;
    }

    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);
        }
        rc = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
        if (!rc.isOk()) {
            return rc;
        }

        auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);

        rc = KS_HANDLE_HIDL_ERROR(
            dev->getKeyCharacteristics(upgradedHidlKeyBlob, clientId, appData, hidlCb));
        if (!rc.isOk()) {
            return rc;
        }
        // Note that, on success, "error" will have been updated by the hidlCB callback.
        // So it is fine to return "error" below.
    }
    return error;
}

KeyStoreServiceReturnCode
KeyStoreService::importKey(const String16& name, const hidl_vec<KeyParameter>& params,
                           KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, int flags,
                           KeyCharacteristics* outCharacteristics) {
    uid = getEffectiveUid(uid);
    KeyStoreServiceReturnCode rc =
        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!rc.isOk()) {
        return rc;
    }
    if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
        return ResponseCode::PERMISSION_DENIED;
    }

    bool usingFallback = false;
    auto& dev = mKeyStore->getDevice();

    String8 name8(name);

    KeyStoreServiceReturnCode error;

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

        if (outCharacteristics) *outCharacteristics = keyCharacteristics;

        // Write the key:
        String8 filename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEYMASTER_10));

        Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
        ksBlob.setFallback(usingFallback);
        ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
        if (isAuthenticationBound(params) && !ksBlob.isCriticalToDeviceEncryption()) {
            ksBlob.setSuperEncrypted(true);
        }
        ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);

        error = mKeyStore->put(filename.string(), &ksBlob, get_user_id(uid));
    };

    rc = KS_HANDLE_HIDL_ERROR(dev->importKey(params, format, keyData, hidlCb));
    // possible hidl error
    if (!rc.isOk()) {
        return rc;
    }
    // now check error from callback
    if (!error.isOk()) {
        ALOGE("Failed to import key -> falling back to software keymaster");
        usingFallback = true;
        auto fallback = mKeyStore->getFallbackDevice();
        if (!fallback.isOk()) {
            return error;
        }
        rc = KS_HANDLE_HIDL_ERROR(fallback.value()->importKey(params, format, keyData, hidlCb));
        // possible hidl error
        if (!rc.isOk()) {
            return rc;
        }
        // now check error from callback
        if (!error.isOk()) {
            return error;
        }
    }

    // Write the characteristics:
    String8 cFilename(mKeyStore->getKeyNameForUidWithDir(name8, uid, ::TYPE_KEY_CHARACTERISTICS));

    AuthorizationSet opParams = params;
    std::stringstream kcStream;
    opParams.Serialize(&kcStream);
    if (kcStream.bad()) return ResponseCode::SYSTEM_ERROR;
    auto kcBuf = kcStream.str();

    Blob charBlob(reinterpret_cast<const uint8_t*>(kcBuf.data()), kcBuf.size(), NULL, 0,
                  ::TYPE_KEY_CHARACTERISTICS);
    charBlob.setFallback(usingFallback);
    charBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);

    return mKeyStore->put(cFilename.string(), &charBlob, get_user_id(uid));
}

void KeyStoreService::exportKey(const String16& name, KeyFormat format,
                                const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
                                int32_t uid, ExportResult* result) {

    uid_t targetUid = getEffectiveUid(uid);
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    if (!is_granted_to(callingUid, targetUid)) {
        ALOGW("uid %d not permitted to act for uid %d in exportKey", callingUid, targetUid);
        result->resultCode = ResponseCode::PERMISSION_DENIED;
        return;
    }

    Blob keyBlob;
    String8 name8(name);

    result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
    if (!result->resultCode.isOk()) {
        return;
    }

    auto key = blob2hidlVec(keyBlob);
    auto& dev = mKeyStore->getDevice(keyBlob);

    auto hidlCb = [&](ErrorCode ret, const ::android::hardware::hidl_vec<uint8_t>& keyMaterial) {
        result->resultCode = ret;
        if (!result->resultCode.isOk()) {
            return;
        }
        result->exportData = keyMaterial;
    };
    KeyStoreServiceReturnCode rc =
        KS_HANDLE_HIDL_ERROR(dev->exportKey(format, 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);
        }
        result->resultCode = upgradeKeyBlob(name, targetUid, upgradeParams, &keyBlob);
        if (!result->resultCode.isOk()) {
            return;
        }

        auto upgradedHidlKeyBlob = blob2hidlVec(keyBlob);

        result->resultCode = KS_HANDLE_HIDL_ERROR(
            dev->exportKey(format, upgradedHidlKeyBlob, clientId, appData, hidlCb));
        if (!result->resultCode.isOk()) {
            return;
        }
    }
}

static inline void addAuthTokenToParams(AuthorizationSet* params, const HardwareAuthToken* token) {
    if (token) {
        params->push_back(TAG_AUTH_TOKEN, authToken2HidlVec(*token));
    }
}

void KeyStoreService::begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
                            bool pruneable, const hidl_vec<KeyParameter>& params,
                            const hidl_vec<uint8_t>& entropy, int32_t uid,
                            OperationResult* result) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    uid_t targetUid = getEffectiveUid(uid);
    if (!is_granted_to(callingUid, targetUid)) {
        ALOGW("uid %d not permitted to act for uid %d in begin", callingUid, targetUid);
        result->resultCode = ResponseCode::PERMISSION_DENIED;
        return;
    }
    if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
        ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
        result->resultCode = ResponseCode::PERMISSION_DENIED;
        return;
    }
    if (!checkAllowedOperationParams(params)) {
        result->resultCode = ErrorCode::INVALID_ARGUMENT;
        return;
    }
    Blob keyBlob;
    String8 name8(name);
    result->resultCode = mKeyStore->getKeyForName(&keyBlob, name8, targetUid, TYPE_KEYMASTER_10);
    if (result->resultCode == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
        result->resultCode = ErrorCode::KEY_USER_NOT_AUTHENTICATED;
    }
    if (!result->resultCode.isOk()) {
        return;
    }

    auto key = blob2hidlVec(keyBlob);
    auto& dev = mKeyStore->getDevice(keyBlob);
    AuthorizationSet opParams = params;
    KeyCharacteristics characteristics;
    result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);

    if (result->resultCode == ErrorCode::KEY_REQUIRES_UPGRADE) {
        result->resultCode = upgradeKeyBlob(name, targetUid, opParams, &keyBlob);
        if (!result->resultCode.isOk()) {
            return;
        }
        key = blob2hidlVec(keyBlob);
        result->resultCode = getOperationCharacteristics(key, &dev, opParams, &characteristics);
    }
    if (!result->resultCode.isOk()) {
        return;
    }

    const HardwareAuthToken* authToken = NULL;

    // Merge these characteristics with the ones cached when the key was generated or imported
    Blob charBlob;
    AuthorizationSet persistedCharacteristics;
    result->resultCode =
        mKeyStore->getKeyForName(&charBlob, name8, targetUid, TYPE_KEY_CHARACTERISTICS);
    if (result->resultCode.isOk()) {
        // TODO write one shot stream buffer to avoid copying (twice here)
        std::string charBuffer(reinterpret_cast<const char*>(charBlob.getValue()),
                               charBlob.getLength());
        std::stringstream charStream(charBuffer);
        persistedCharacteristics.Deserialize(&charStream);
    } else {
        ALOGD("Unable to read cached characteristics for key");
    }

    // Replace the sw_enforced set with those persisted to disk, minus hw_enforced
    AuthorizationSet softwareEnforced = characteristics.softwareEnforced;
    AuthorizationSet teeEnforced = characteristics.teeEnforced;
    persistedCharacteristics.Union(softwareEnforced);
    persistedCharacteristics.Subtract(teeEnforced);
    characteristics.softwareEnforced = persistedCharacteristics.hidl_data();

    auto authResult = getAuthToken(characteristics, 0, purpose, &authToken,
                                   /*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 (!authResult.isOk() && authResult != ResponseCode::OP_AUTH_NEEDED) {
        result->resultCode = authResult;
        return;
    }

    addAuthTokenToParams(&opParams, authToken);

    // Add entropy to the device first.
    if (entropy.size()) {
        result->resultCode = addRngEntropy(entropy);
        if (!result->resultCode.isOk()) {
            return;
        }
    }

    // Create a keyid for this key.
    km_id_t keyid;
    if (!enforcement_policy.CreateKeyId(key, &keyid)) {
        ALOGE("Failed to create a key ID for authorization checking.");
        result->resultCode = ErrorCode::UNKNOWN_ERROR;
        return;
    }

    // Check that all key authorization policy requirements are met.
    AuthorizationSet key_auths = characteristics.teeEnforced;
    key_auths.append(&characteristics.softwareEnforced[0],
                     &characteristics.softwareEnforced[characteristics.softwareEnforced.size()]);

    result->resultCode = enforcement_policy.AuthorizeOperation(
        purpose, keyid, key_auths, opParams, 0 /* op_handle */, true /* is_begin_operation */);
    if (!result->resultCode.isOk()) {
        return;
    }

    // If there are more than kMaxOperations, abort the oldest operation that was started as
    // pruneable.
    while (mOperationMap.getOperationCount() >= kMaxOperations) {
        ALOGD("Reached or exceeded concurrent operations limit");
        if (!pruneOperation()) {
            break;
        }
    }

    auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
                      uint64_t operationHandle) {
        result->resultCode = ret;
        if (!result->resultCode.isOk()) {
            return;
        }
        result->handle = operationHandle;
        result->outParams = outParams;
    };

    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
    if (rc != ErrorCode::OK) {
        ALOGW("Got error %d from begin()", rc);
    }

    // If there are too many operations abort the oldest operation that was
    // started as pruneable and try again.
    while (rc == ErrorCode::TOO_MANY_OPERATIONS && mOperationMap.hasPruneableOperation()) {
        ALOGW("Ran out of operation handles");
        if (!pruneOperation()) {
            break;
        }
        rc = KS_HANDLE_HIDL_ERROR(dev->begin(purpose, key, opParams.hidl_data(), hidlCb));
    }
    if (rc != ErrorCode::OK) {
        result->resultCode = rc;
        return;
    }

    // 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 = mOperationMap.addOperation(
        result->handle, keyid, purpose, dev, appToken, std::move(characteristics), pruneable);
    assert(characteristics.teeEnforced.size() == 0);
    assert(characteristics.softwareEnforced.size() == 0);
    result->token = operationToken;

    if (authToken) {
        mOperationMap.setOperationAuthToken(operationToken, authToken);
    }
    // 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 == ErrorCode::OK) {
        result->resultCode = authResult;
    }

    // Other result fields were set in the begin operation's callback.
}

void KeyStoreService::update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
                             const hidl_vec<uint8_t>& data, OperationResult* result) {
    if (!checkAllowedOperationParams(params)) {
        result->resultCode = ErrorCode::INVALID_ARGUMENT;
        return;
    }
    km_device_t dev;
    uint64_t handle;
    KeyPurpose purpose;
    km_id_t keyid;
    const KeyCharacteristics* characteristics;
    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
        result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
        return;
    }
    AuthorizationSet opParams = params;
    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
    if (!result->resultCode.isOk()) {
        return;
    }

    // Check that all key authorization policy requirements are met.
    AuthorizationSet key_auths(characteristics->teeEnforced);
    key_auths.append(&characteristics->softwareEnforced[0],
                     &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
    result->resultCode = enforcement_policy.AuthorizeOperation(
        purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
    if (!result->resultCode.isOk()) {
        return;
    }

    auto hidlCb = [&](ErrorCode ret, uint32_t inputConsumed,
                      const hidl_vec<KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
        result->resultCode = ret;
        if (!result->resultCode.isOk()) {
            return;
        }
        result->inputConsumed = inputConsumed;
        result->outParams = outParams;
        result->data = output;
    };

    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->update(handle, opParams.hidl_data(),
                                                        data, 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;
    }
}

void KeyStoreService::finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
                             const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
                             OperationResult* result) {
    if (!checkAllowedOperationParams(params)) {
        result->resultCode = ErrorCode::INVALID_ARGUMENT;
        return;
    }
    km_device_t dev;
    uint64_t handle;
    KeyPurpose purpose;
    km_id_t keyid;
    const KeyCharacteristics* characteristics;
    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
        result->resultCode = ErrorCode::INVALID_OPERATION_HANDLE;
        return;
    }
    AuthorizationSet opParams = params;
    result->resultCode = addOperationAuthTokenIfNeeded(token, &opParams);
    if (!result->resultCode.isOk()) {
        return;
    }

    if (entropy.size()) {
        result->resultCode = addRngEntropy(entropy);
        if (!result->resultCode.isOk()) {
            return;
        }
    }

    // Check that all key authorization policy requirements are met.
    AuthorizationSet key_auths(characteristics->teeEnforced);
    key_auths.append(&characteristics->softwareEnforced[0],
                     &characteristics->softwareEnforced[characteristics->softwareEnforced.size()]);
    result->resultCode = enforcement_policy.AuthorizeOperation(
        purpose, keyid, key_auths, opParams, handle, false /* is_begin_operation */);
    if (!result->resultCode.isOk()) return;

    auto hidlCb = [&](ErrorCode ret, const hidl_vec<KeyParameter>& outParams,
                      const hidl_vec<uint8_t>& output) {
        result->resultCode = ret;
        if (!result->resultCode.isOk()) {
            return;
        }
        result->outParams = outParams;
        result->data = output;
    };

    KeyStoreServiceReturnCode rc = KS_HANDLE_HIDL_ERROR(dev->finish(
        handle, opParams.hidl_data(),
        hidl_vec<uint8_t>() /* TODO(swillden): wire up input to finish() */, signature, hidlCb));
    // Remove the operation regardless of the result
    mOperationMap.removeOperation(token);
    mAuthTokenTable.MarkCompleted(handle);

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

KeyStoreServiceReturnCode KeyStoreService::abort(const sp<IBinder>& token) {
    km_device_t dev;
    uint64_t handle;
    KeyPurpose purpose;
    km_id_t keyid;
    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, NULL)) {
        return ErrorCode::INVALID_OPERATION_HANDLE;
    }
    mOperationMap.removeOperation(token);

    ErrorCode rc = KS_HANDLE_HIDL_ERROR(dev->abort(handle));
    mAuthTokenTable.MarkCompleted(handle);
    return rc;
}

bool KeyStoreService::isOperationAuthorized(const sp<IBinder>& token) {
    km_device_t dev;
    uint64_t handle;
    const KeyCharacteristics* characteristics;
    KeyPurpose purpose;
    km_id_t keyid;
    if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
        return false;
    }
    const HardwareAuthToken* authToken = NULL;
    mOperationMap.getOperationAuthToken(token, &authToken);
    AuthorizationSet ignored;
    auto authResult = addOperationAuthTokenIfNeeded(token, &ignored);
    return authResult.isOk();
}

KeyStoreServiceReturnCode KeyStoreService::addAuthToken(const uint8_t* token, size_t length) {
    // TODO(swillden): When gatekeeper and fingerprint are ready, this should be updated to
    // receive a HardwareAuthToken, rather than an opaque byte array.

    if (!checkBinderPermission(P_ADD_AUTH)) {
        ALOGW("addAuthToken: permission denied for %d", IPCThreadState::self()->getCallingUid());
        return ResponseCode::PERMISSION_DENIED;
    }
    if (length != sizeof(hw_auth_token_t)) {
        return ErrorCode::INVALID_ARGUMENT;
    }

    hw_auth_token_t authToken;
    memcpy(reinterpret_cast<void*>(&authToken), token, sizeof(hw_auth_token_t));
    if (authToken.version != 0) {
        return ErrorCode::INVALID_ARGUMENT;
    }

    std::unique_ptr<HardwareAuthToken> hidlAuthToken(new HardwareAuthToken);
    hidlAuthToken->challenge = authToken.challenge;
    hidlAuthToken->userId = authToken.user_id;
    hidlAuthToken->authenticatorId = authToken.authenticator_id;
    hidlAuthToken->authenticatorType = authToken.authenticator_type;
    hidlAuthToken->timestamp = authToken.timestamp;
    static_assert(
        std::is_same<decltype(hidlAuthToken->hmac),
                     ::android::hardware::hidl_array<uint8_t, sizeof(authToken.hmac)>>::value,
        "This function assumes token HMAC is 32 bytes, but it might not be.");
    std::copy(authToken.hmac, authToken.hmac + sizeof(authToken.hmac), hidlAuthToken->hmac.data());

    // The table takes ownership of authToken.
    mAuthTokenTable.AddAuthenticationToken(hidlAuthToken.release());
    return ResponseCode::NO_ERROR;
}

bool isDeviceIdAttestationRequested(const hidl_vec<KeyParameter>& params) {
    for (size_t i = 0; i < params.size(); ++i) {
        switch (params[i].tag) {
        case Tag::ATTESTATION_ID_BRAND:
        case Tag::ATTESTATION_ID_DEVICE:
        case Tag::ATTESTATION_ID_IMEI:
        case Tag::ATTESTATION_ID_MANUFACTURER:
        case Tag::ATTESTATION_ID_MEID:
        case Tag::ATTESTATION_ID_MODEL:
        case Tag::ATTESTATION_ID_PRODUCT:
        case Tag::ATTESTATION_ID_SERIAL:
            return true;
        default:
            break;
        }
    }
    return false;
}

KeyStoreServiceReturnCode KeyStoreService::attestKey(const String16& name,
                                                     const hidl_vec<KeyParameter>& params,
                                                     hidl_vec<hidl_vec<uint8_t>>* outChain) {
    if (!outChain) {
        return ErrorCode::OUTPUT_PARAMETER_NULL;
    }

    if (!checkAllowedOperationParams(params)) {
        return ErrorCode::INVALID_ARGUMENT;
    }

    if (isDeviceIdAttestationRequested(params)) {
        // There is a dedicated attestDeviceIds() method for device ID attestation.
        return ErrorCode::INVALID_ARGUMENT;
    }

    uid_t callingUid = IPCThreadState::self()->getCallingUid();

    AuthorizationSet mutableParams = params;
    KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
    if (!rc.isOk()) {
        return rc;
    }

    Blob keyBlob;
    String8 name8(name);
    rc = mKeyStore->getKeyForName(&keyBlob, name8, callingUid, TYPE_KEYMASTER_10);
    if (!rc.isOk()) {
        return rc;
    }

    KeyStoreServiceReturnCode error;
    auto hidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
        error = ret;
        if (!error.isOk()) {
            return;
        }
        if (outChain) *outChain = certChain;
    };

    auto hidlKey = blob2hidlVec(keyBlob);
    auto& dev = mKeyStore->getDevice(keyBlob);
    rc = KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), hidlCb));
    if (!rc.isOk()) {
        return rc;
    }
    return error;
}

KeyStoreServiceReturnCode KeyStoreService::attestDeviceIds(const hidl_vec<KeyParameter>& params,
                                                           hidl_vec<hidl_vec<uint8_t>>* outChain) {
    if (!outChain) {
        return ErrorCode::OUTPUT_PARAMETER_NULL;
    }

    if (!checkAllowedOperationParams(params)) {
        return ErrorCode::INVALID_ARGUMENT;
    }

    if (!isDeviceIdAttestationRequested(params)) {
        // There is an attestKey() method for attesting keys without device ID attestation.
        return ErrorCode::INVALID_ARGUMENT;
    }

    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
    if (binder == 0) {
        return ErrorCode::CANNOT_ATTEST_IDS;
    }
    if (!interface_cast<IPermissionController>(binder)->checkPermission(
            String16("android.permission.READ_PRIVILEGED_PHONE_STATE"),
            IPCThreadState::self()->getCallingPid(), callingUid)) {
        return ErrorCode::CANNOT_ATTEST_IDS;
    }

    AuthorizationSet mutableParams = params;
    KeyStoreServiceReturnCode rc = updateParamsForAttestation(callingUid, &mutableParams);
    if (!rc.isOk()) {
        return rc;
    }

    // Generate temporary key.
    auto& dev = mKeyStore->getDevice();
    KeyStoreServiceReturnCode error;
    hidl_vec<uint8_t> hidlKey;

    AuthorizationSet keyCharacteristics;
    keyCharacteristics.push_back(TAG_PURPOSE, KeyPurpose::VERIFY);
    keyCharacteristics.push_back(TAG_ALGORITHM, Algorithm::EC);
    keyCharacteristics.push_back(TAG_DIGEST, Digest::SHA_2_256);
    keyCharacteristics.push_back(TAG_NO_AUTH_REQUIRED);
    keyCharacteristics.push_back(TAG_EC_CURVE, EcCurve::P_256);
    auto generateHidlCb = [&](ErrorCode ret, const hidl_vec<uint8_t>& hidlKeyBlob,
                              const KeyCharacteristics&) {
        error = ret;
        if (!error.isOk()) {
            return;
        }
        hidlKey = hidlKeyBlob;
    };

    rc = KS_HANDLE_HIDL_ERROR(dev->generateKey(keyCharacteristics.hidl_data(), generateHidlCb));
    if (!rc.isOk()) {
        return rc;
    }
    if (!error.isOk()) {
        return error;
    }

    // Attest key and device IDs.
    auto attestHidlCb = [&](ErrorCode ret, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
        error = ret;
        if (!error.isOk()) {
            return;
        }
        *outChain = certChain;
    };
    KeyStoreServiceReturnCode attestationRc =
            KS_HANDLE_HIDL_ERROR(dev->attestKey(hidlKey, mutableParams.hidl_data(), attestHidlCb));

    // Delete temporary key.
    KeyStoreServiceReturnCode deletionRc = KS_HANDLE_HIDL_ERROR(dev->deleteKey(hidlKey));

    if (!attestationRc.isOk()) {
        return attestationRc;
    }
    if (!error.isOk()) {
        return error;
    }
    return deletionRc;
}

KeyStoreServiceReturnCode KeyStoreService::onDeviceOffBody() {
    // TODO(tuckeris): add permission check.  This should be callable from ClockworkHome only.
    mAuthTokenTable.onDeviceOffBody();
    return ResponseCode::NO_ERROR;
}

/**
 * Prune the oldest pruneable operation.
 */
bool KeyStoreService::pruneOperation() {
    sp<IBinder> oldest = mOperationMap.getOldestPruneableOperation();
    ALOGD("Trying to prune operation %p", oldest.get());
    size_t op_count_before_abort = mOperationMap.getOperationCount();
    // We mostly ignore errors from abort() because all we care about is whether at least
    // one operation has been removed.
    int abort_error = abort(oldest);
    if (mOperationMap.getOperationCount() >= op_count_before_abort) {
        ALOGE("Failed to abort pruneable operation %p, error: %d", oldest.get(), abort_error);
        return false;
    }
    return true;
}

/**
 * Get the effective target uid for a binder operation that takes an
 * optional uid as the target.
 */
uid_t KeyStoreService::getEffectiveUid(int32_t targetUid) {
    if (targetUid == UID_SELF) {
        return IPCThreadState::self()->getCallingUid();
    }
    return static_cast<uid_t>(targetUid);
}

/**
 * Check if the caller of the current binder method has the required
 * permission and if acting on other uids the grants to do so.
 */
bool KeyStoreService::checkBinderPermission(perm_t permission, int32_t targetUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    pid_t spid = IPCThreadState::self()->getCallingPid();
    if (!has_permission(callingUid, permission, spid)) {
        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
        return false;
    }
    if (!is_granted_to(callingUid, getEffectiveUid(targetUid))) {
        ALOGW("uid %d not granted to act for %d", callingUid, targetUid);
        return false;
    }
    return true;
}

/**
 * Check if the caller of the current binder method has the required
 * permission and the target uid is the caller or the caller is system.
 */
bool KeyStoreService::checkBinderPermissionSelfOrSystem(perm_t permission, int32_t targetUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    pid_t spid = IPCThreadState::self()->getCallingPid();
    if (!has_permission(callingUid, permission, spid)) {
        ALOGW("permission %s denied for %d", get_perm_label(permission), callingUid);
        return false;
    }
    return getEffectiveUid(targetUid) == callingUid || callingUid == AID_SYSTEM;
}

/**
 * Check if the caller of the current binder method has the required
 * permission or the target of the operation is the caller's uid. This is
 * for operation where the permission is only for cross-uid activity and all
 * uids are allowed to act on their own (ie: clearing all entries for a
 * given uid).
 */
bool KeyStoreService::checkBinderPermissionOrSelfTarget(perm_t permission, int32_t targetUid) {
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    if (getEffectiveUid(targetUid) == callingUid) {
        return true;
    } else {
        return checkBinderPermission(permission, targetUid);
    }
}

/**
 * Helper method to check that the caller has the required permission as
 * well as the keystore is in the unlocked state if checkUnlocked is true.
 *
 * Returns NO_ERROR on success, PERMISSION_DENIED on a permission error and
 * otherwise the state of keystore when not unlocked and checkUnlocked is
 * true.
 */
KeyStoreServiceReturnCode
KeyStoreService::checkBinderPermissionAndKeystoreState(perm_t permission, int32_t targetUid,
                                                       bool checkUnlocked) {
    if (!checkBinderPermission(permission, targetUid)) {
        return ResponseCode::PERMISSION_DENIED;
    }
    State state = mKeyStore->getState(get_user_id(getEffectiveUid(targetUid)));
    if (checkUnlocked && !isKeystoreUnlocked(state)) {
        // All State values coincide with ResponseCodes
        return static_cast<ResponseCode>(state);
    }

    return ResponseCode::NO_ERROR;
}

bool KeyStoreService::isKeystoreUnlocked(State state) {
    switch (state) {
    case ::STATE_NO_ERROR:
        return true;
    case ::STATE_UNINITIALIZED:
    case ::STATE_LOCKED:
        return false;
    }
    return false;
}

/**
 * Check that all KeyParameter's provided by the application are
 * allowed. Any parameter that keystore adds itself should be disallowed here.
 */
bool KeyStoreService::checkAllowedOperationParams(const hidl_vec<KeyParameter>& params) {
    for (size_t i = 0; i < params.size(); ++i) {
        switch (params[i].tag) {
        case Tag::ATTESTATION_APPLICATION_ID:
        case Tag::AUTH_TOKEN:
        case Tag::RESET_SINCE_ID_ROTATION:
            return false;
        default:
            break;
        }
    }
    return true;
}

ErrorCode KeyStoreService::getOperationCharacteristics(const hidl_vec<uint8_t>& key,
                                                       km_device_t* dev,
                                                       const AuthorizationSet& params,
                                                       KeyCharacteristics* out) {
    hidl_vec<uint8_t> appId;
    hidl_vec<uint8_t> appData;
    for (auto param : params) {
        if (param.tag == Tag::APPLICATION_ID) {
            appId = authorizationValue(TAG_APPLICATION_ID, param).value();
        } else if (param.tag == Tag::APPLICATION_DATA) {
            appData = authorizationValue(TAG_APPLICATION_DATA, param).value();
        }
    }
    ErrorCode error = ErrorCode::OK;

    auto hidlCb = [&](ErrorCode ret, const KeyCharacteristics& keyCharacteristics) {
        error = ret;
        if (error != ErrorCode::OK) {
            return;
        }
        if (out) *out = keyCharacteristics;
    };

    ErrorCode rc = KS_HANDLE_HIDL_ERROR((*dev)->getKeyCharacteristics(key, appId, appData, hidlCb));
    if (rc != ErrorCode::OK) {
        return rc;
    }
    return error;
}

/**
 * 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
 */
KeyStoreServiceReturnCode KeyStoreService::getAuthToken(const KeyCharacteristics& characteristics,
                                                        uint64_t handle, KeyPurpose purpose,
                                                        const HardwareAuthToken** authToken,
                                                        bool failOnTokenMissing) {

    AuthorizationSet allCharacteristics;
    for (size_t i = 0; i < characteristics.softwareEnforced.size(); i++) {
        allCharacteristics.push_back(characteristics.softwareEnforced[i]);
    }
    for (size_t i = 0; i < characteristics.teeEnforced.size(); i++) {
        allCharacteristics.push_back(characteristics.teeEnforced[i]);
    }
    AuthTokenTable::Error err =
        mAuthTokenTable.FindAuthorization(allCharacteristics, purpose, handle, authToken);
    switch (err) {
    case AuthTokenTable::OK:
    case AuthTokenTable::AUTH_NOT_REQUIRED:
        return ResponseCode::NO_ERROR;
    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
        return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
    case AuthTokenTable::OP_HANDLE_REQUIRED:
        return failOnTokenMissing ? KeyStoreServiceReturnCode(ErrorCode::KEY_USER_NOT_AUTHENTICATED)
                                  : KeyStoreServiceReturnCode(ResponseCode::OP_AUTH_NEEDED);
    default:
        ALOGE("Unexpected FindAuthorization return value %d", err);
        return ErrorCode::INVALID_ARGUMENT;
    }
}

/**
 * Add the auth token for the operation to the param list if the operation
 * requires authorization. Uses the cached result in the OperationMap if available
 * otherwise gets the token from the AuthTokenTable and caches the result.
 *
 * Returns ResponseCode::NO_ERROR if the auth token was added or not needed.
 *         KM_ERROR_KEY_USER_NOT_AUTHENTICATED if the operation is not
 *         authenticated.
 *         KM_ERROR_INVALID_OPERATION_HANDLE if token is not a valid
 *         operation token.
 */
KeyStoreServiceReturnCode KeyStoreService::addOperationAuthTokenIfNeeded(const sp<IBinder>& token,
                                                                         AuthorizationSet* params) {
    const HardwareAuthToken* authToken = nullptr;
    mOperationMap.getOperationAuthToken(token, &authToken);
    if (!authToken) {
        km_device_t dev;
        uint64_t handle;
        const KeyCharacteristics* characteristics = nullptr;
        KeyPurpose purpose;
        km_id_t keyid;
        if (!mOperationMap.getOperation(token, &handle, &keyid, &purpose, &dev, &characteristics)) {
            return ErrorCode::INVALID_OPERATION_HANDLE;
        }
        auto result = getAuthToken(*characteristics, handle, purpose, &authToken);
        if (!result.isOk()) {
            return result;
        }
        if (authToken) {
            mOperationMap.setOperationAuthToken(token, authToken);
        }
    }
    addAuthTokenToParams(params, authToken);
    return ResponseCode::NO_ERROR;
}

/**
 * Translate a result value to a legacy return value. All keystore errors are
 * preserved and keymaster errors become SYSTEM_ERRORs
 */
KeyStoreServiceReturnCode KeyStoreService::translateResultToLegacyResult(int32_t result) {
    if (result > 0) {
        return static_cast<ResponseCode>(result);
    }
    return ResponseCode::SYSTEM_ERROR;
}

static NullOr<const Algorithm&>
getKeyAlgoritmFromKeyCharacteristics(const KeyCharacteristics& characteristics) {
    for (size_t i = 0; i < characteristics.teeEnforced.size(); ++i) {
        auto algo = authorizationValue(TAG_ALGORITHM, characteristics.teeEnforced[i]);
        if (algo.isOk()) return algo.value();
    }
    for (size_t i = 0; i < characteristics.softwareEnforced.size(); ++i) {
        auto algo = authorizationValue(TAG_ALGORITHM, characteristics.softwareEnforced[i]);
        if (algo.isOk()) return algo.value();
    }
    return {};
}

void KeyStoreService::addLegacyBeginParams(const String16& name, AuthorizationSet* params) {
    // All legacy keys are DIGEST_NONE/PAD_NONE.
    params->push_back(TAG_DIGEST, Digest::NONE);
    params->push_back(TAG_PADDING, PaddingMode::NONE);

    // Look up the algorithm of the key.
    KeyCharacteristics characteristics;
    auto rc = getKeyCharacteristics(name, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(), UID_SELF,
                                    &characteristics);
    if (!rc.isOk()) {
        ALOGE("Failed to get key characteristics");
        return;
    }
    auto algorithm = getKeyAlgoritmFromKeyCharacteristics(characteristics);
    if (!algorithm.isOk()) {
        ALOGE("getKeyCharacteristics did not include KM_TAG_ALGORITHM");
        return;
    }
    params->push_back(TAG_ALGORITHM, algorithm.value());
}

KeyStoreServiceReturnCode KeyStoreService::doLegacySignVerify(const String16& name,
                                                              const hidl_vec<uint8_t>& data,
                                                              hidl_vec<uint8_t>* out,
                                                              const hidl_vec<uint8_t>& signature,
                                                              KeyPurpose purpose) {

    std::basic_stringstream<uint8_t> outBuffer;
    OperationResult result;
    AuthorizationSet inArgs;
    addLegacyBeginParams(name, &inArgs);
    sp<IBinder> appToken(new BBinder);
    sp<IBinder> token;

    begin(appToken, name, purpose, true, inArgs.hidl_data(), hidl_vec<uint8_t>(), UID_SELF,
          &result);
    if (!result.resultCode.isOk()) {
        if (result.resultCode == ResponseCode::KEY_NOT_FOUND) {
            ALOGW("Key not found");
        } else {
            ALOGW("Error in begin: %d", int32_t(result.resultCode));
        }
        return translateResultToLegacyResult(result.resultCode);
    }
    inArgs.Clear();
    token = result.token;
    size_t consumed = 0;
    size_t lastConsumed = 0;
    hidl_vec<uint8_t> data_view;
    do {
        data_view.setToExternal(const_cast<uint8_t*>(&data[consumed]), data.size() - consumed);
        update(token, inArgs.hidl_data(), data_view, &result);
        if (result.resultCode != ResponseCode::NO_ERROR) {
            ALOGW("Error in update: %d", int32_t(result.resultCode));
            return translateResultToLegacyResult(result.resultCode);
        }
        if (out) {
            outBuffer.write(&result.data[0], result.data.size());
        }
        lastConsumed = result.inputConsumed;
        consumed += lastConsumed;
    } while (consumed < data.size() && lastConsumed > 0);

    if (consumed != data.size()) {
        ALOGW("Not all data consumed. Consumed %zu of %zu", consumed, data.size());
        return ResponseCode::SYSTEM_ERROR;
    }

    finish(token, inArgs.hidl_data(), signature, hidl_vec<uint8_t>(), &result);
    if (result.resultCode != ResponseCode::NO_ERROR) {
        ALOGW("Error in finish: %d", int32_t(result.resultCode));
        return translateResultToLegacyResult(result.resultCode);
    }
    if (out) {
        outBuffer.write(&result.data[0], result.data.size());
    }

    if (out) {
        auto buf = outBuffer.str();
        out->resize(buf.size());
        memcpy(&(*out)[0], buf.data(), out->size());
    }

    return ResponseCode::NO_ERROR;
}

KeyStoreServiceReturnCode KeyStoreService::upgradeKeyBlob(const String16& name, uid_t uid,
                                                          const AuthorizationSet& params,
                                                          Blob* blob) {
    // Read the blob rather than assuming the caller provided the right name/uid/blob triplet.
    String8 name8(name);
    ResponseCode responseCode = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
    if (responseCode != ResponseCode::NO_ERROR) {
        return responseCode;
    }
    ALOGI("upgradeKeyBlob %s %d", name8.string(), uid);

    auto hidlKey = blob2hidlVec(*blob);
    auto& dev = mKeyStore->getDevice(*blob);

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

        auto filename = mKeyStore->getBlobFileNameIfExists(name8, uid, ::TYPE_KEYMASTER_10);
        if (!filename.isOk()) {
            ALOGI("trying to upgrade a non existing blob");
            return;
        }
        error = mKeyStore->del(filename.value().string(), ::TYPE_ANY, get_user_id(uid));
        if (!error.isOk()) {
            ALOGI("upgradeKeyBlob keystore->del failed %d", (int)error);
            return;
        }

        Blob newBlob(&upgradedKeyBlob[0], upgradedKeyBlob.size(), nullptr /* info */,
                     0 /* infoLength */, ::TYPE_KEYMASTER_10);
        newBlob.setFallback(blob->isFallback());
        newBlob.setEncrypted(blob->isEncrypted());
        newBlob.setSuperEncrypted(blob->isSuperEncrypted());
        newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption());

        error = mKeyStore->put(filename.value().string(), &newBlob, get_user_id(uid));
        if (!error.isOk()) {
            ALOGI("upgradeKeyBlob keystore->put failed %d", (int)error);
            return;
        }

        // Re-read blob for caller.  We can't use newBlob because writing it modified it.
        error = mKeyStore->getKeyForName(blob, name8, uid, TYPE_KEYMASTER_10);
    };

    KeyStoreServiceReturnCode rc =
        KS_HANDLE_HIDL_ERROR(dev->upgradeKey(hidlKey, params.hidl_data(), hidlCb));
    if (!rc.isOk()) {
        return rc;
    }

    return error;
}

}  // namespace keystore
