/*
 * 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 <atomic>
#include <sstream>

#include <android-base/scopeguard.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
#include <cutils/multiuser.h>
#include <log/log_event_list.h>

#include <private/android_filesystem_config.h>
#include <private/android_logger.h>

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

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

#include <hardware/hw_auth_token.h>

namespace keystore {

using namespace android;

namespace {

using ::android::binder::Status;
using android::security::keymaster::ExportResult;
using android::security::keymaster::KeymasterArguments;
using android::security::keymaster::KeymasterBlob;
using android::security::keymaster::KeymasterCertificateChain;
using android::security::keymaster::operationFailed;
using android::security::keymaster::OperationResult;
using ConfirmationResponseCode = android::hardware::confirmationui::V1_0::ResponseCode;
using ::android::security::keystore::IKeystoreOperationResultCallback;
using ::android::security::keystore::IKeystoreResponseCallback;
using ::android::security::keystore::KeystoreResponse;

constexpr double kIdRotationPeriod = 30 * 24 * 60 * 60; /* Thirty days, in seconds */
const char* kTimestampFilePath = "timestamp";
const int ID_ATTESTATION_REQUEST_GENERIC_INFO = 1 << 0;
const int ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID = 1 << 1;

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(),
                        [&](const KeyParameter& param) { return param.tag == tag; });
}

#define AIDL_RETURN(rc) (*_aidl_return = KeyStoreServiceReturnCode(rc).getErrorCode(), Status::ok())
#define KEYSTORE_SERVICE_LOCK std::lock_guard<std::mutex> keystore_lock(keystoreServiceMutex_)

std::pair<KeyStoreServiceReturnCode, bool> hadFactoryResetSinceIdRotation() {
    struct stat sbuf;
    if (stat(kTimestampFilePath, &sbuf) == 0) {
        double diff_secs = difftime(time(nullptr), 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};
}

using ::android::security::KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE;

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 must not be longer than
     * KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE, error out if gather_attestation_application_id
     * returned such an invalid vector.
     */
    if (asn1_attestation_id.size() > KEY_ATTESTATION_APPLICATION_ID_MAX_SIZE) {
        ALOGE("BUG: Gathered Attestation Application ID is too big (%d)",
              static_cast<int32_t>(asn1_attestation_id.size()));
        return ErrorCode::CANNOT_ATTEST_IDS;
    }

    params->push_back(TAG_ATTESTATION_APPLICATION_ID, asn1_attestation_id);

    return ResponseCode::NO_ERROR;
}

}  // anonymous namespace

Status KeyStoreService::getState(int32_t userId, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_GET_STATE)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }
    *aidl_return = mKeyStore->getState(userId);
    return Status::ok();
}

Status KeyStoreService::get(const String16& name, int32_t uid, ::std::vector<uint8_t>* item) {
    KEYSTORE_SERVICE_LOCK;
    uid_t targetUid = getEffectiveUid(uid);
    if (!checkBinderPermission(P_GET, targetUid)) {
        // see keystore/keystore.h
        return Status::fromServiceSpecificError(
            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
    }

    String8 name8(name);
    ResponseCode rc;
    Blob keyBlob;
    Blob charBlob;
    LockedKeyBlobEntry lockedEntry;

    std::tie(rc, keyBlob, charBlob, lockedEntry) =
        mKeyStore->getKeyForName(name8, targetUid, TYPE_GENERIC);
    if (rc != ResponseCode::NO_ERROR) {
        *item = ::std::vector<uint8_t>();
        // Return empty array if key is not found
        // TODO: consider having returned value nullable or parse exception on the client.
        return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
    }
    auto resultBlob = blob2hidlVec(keyBlob);
    // The static_cast here is needed to prevent a move, forcing a deep copy.
    if (item) *item = static_cast<const hidl_vec<uint8_t>&>(blob2hidlVec(keyBlob));
    return Status::ok();
}

Status KeyStoreService::insert(const String16& name, const ::std::vector<uint8_t>& item,
                               int targetUid, int32_t flags, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    targetUid = getEffectiveUid(targetUid);
    KeyStoreServiceReturnCode result =
        checkBinderPermissionAndKeystoreState(P_INSERT, targetUid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!result.isOk()) {
        *aidl_return = result.getErrorCode();
        return Status::ok();
    }

    String8 name8(name);
    auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), targetUid);

    if (!lockedEntry) {
        ALOGE("failed to grab lock on blob entry %u_%s", targetUid, name8.string());
        *aidl_return = static_cast<int32_t>(ResponseCode::KEY_ALREADY_EXISTS);
        return Status::ok();
    }

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

    *aidl_return = static_cast<int32_t>(mKeyStore->put(lockedEntry, keyBlob, {}));
    return Status::ok();
}

Status KeyStoreService::del(const String16& name, int targetUid, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_DELETE, targetUid)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }
    String8 name8(name);
    ALOGI("del %s %d", name8.string(), targetUid);
    auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid);
    if (!lockedEntry) {
        *aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
        return Status::ok();
    }

    ResponseCode result = mKeyStore->del(lockedEntry);

    *aidl_return = static_cast<int32_t>(result);
    return Status::ok();
}

Status KeyStoreService::exist(const String16& name, int targetUid, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_EXIST, targetUid)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    LockedKeyBlobEntry lockedEntry =
        mKeyStore->getLockedBlobEntryIfExists(String8(name).string(), targetUid);
    *aidl_return =
        static_cast<int32_t>(lockedEntry ? ResponseCode::NO_ERROR : ResponseCode::KEY_NOT_FOUND);
    return Status::ok();
}

Status KeyStoreService::list(const String16& prefix, int32_t targetUid,
                             ::std::vector<::android::String16>* matches) {
    KEYSTORE_SERVICE_LOCK;
    targetUid = getEffectiveUid(targetUid);
    if (!checkBinderPermission(P_LIST, targetUid)) {
        return Status::fromServiceSpecificError(
            static_cast<int32_t>(ResponseCode::PERMISSION_DENIED));
    }
    const String8 prefix8(prefix);
    const std::string stdPrefix(prefix8.string());

    ResponseCode rc;
    std::list<LockedKeyBlobEntry> internal_matches;
    auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName();

    std::tie(rc, internal_matches) =
        LockedKeyBlobEntry::list(userDirName, [&](uid_t uid, const std::string& alias) {
            std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end());
            return uid == static_cast<uid_t>(targetUid) &&
                   std::mismatch(stdPrefix.begin(), stdPrefix.end(), alias.begin(), alias.end())
                           .first == stdPrefix.end();
        });

    if (rc != ResponseCode::NO_ERROR) {
        return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
    }

    for (LockedKeyBlobEntry& entry : internal_matches) {
        matches->push_back(String16(entry->alias().substr(prefix8.size()).c_str()));
    }
    return Status::ok();
}

/*
 * This method will return the uids of all auth bound keys for the calling user.
 * This is intended to be used for alerting the user about which apps will be affected
 * if the password/pin is removed. Only allowed to be called by system.
 * The output is bound by the initial size of uidsOut to be compatible with Java.
 */
Status KeyStoreService::listUidsOfAuthBoundKeys(std::vector<std::string>* uidsOut,
                                                int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    const int32_t callingUid = IPCThreadState::self()->getCallingUid();
    const int32_t userId = get_user_id(callingUid);
    const int32_t appId = get_app_id(callingUid);
    if (appId != AID_SYSTEM) {
        ALOGE("Permission listUidsOfAuthBoundKeys denied for aid %d", appId);
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    const String8 prefix8("");
    auto userState = mKeyStore->getUserStateDB().getUserState(userId);
    const std::string userDirName = userState->getUserDirName();
    auto encryptionKey = userState->getEncryptionKey();
    auto state = userState->getState();
    // unlock the user state
    userState = {};

    ResponseCode rc;
    std::list<LockedKeyBlobEntry> internal_matches;
    std::tie(rc, internal_matches) =
        LockedKeyBlobEntry::list(userDirName, [&](uid_t, const std::string&) {
            // Need to filter on auth bound state, so just return true.
            return true;
        });
    if (rc != ResponseCode::NO_ERROR) {
        ALOGE("Error listing blob entries for user %d", userId);
        return Status::fromServiceSpecificError(static_cast<int32_t>(rc));
    }

    for (LockedKeyBlobEntry& entry : internal_matches) {
        // Need to store uids as a list of strings because integer list output
        // parameters is not supported in aidl-cpp.
        std::string entryUid = std::to_string(entry->uid());
        if (std::find(uidsOut->begin(), uidsOut->end(), entryUid) != uidsOut->end()) {
            // uid already in list, skip
            continue;
        }

        auto [rc, blob, charBlob] = entry.readBlobs(encryptionKey, state);
        if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::LOCKED) {
            ALOGE("Error reading blob for key %s", entry->alias().c_str());
            continue;
        }

        if (blob && blob.isEncrypted()) {
            uidsOut->push_back(entryUid);
        } else if (charBlob) {
            auto [success, hwEnforced, swEnforced] = charBlob.getKeyCharacteristics();
            if (!success) {
                ALOGE("Error reading blob characteristics for key %s", entry->alias().c_str());
                continue;
            }
            if (hwEnforced.Contains(TAG_USER_SECURE_ID) ||
                swEnforced.Contains(TAG_USER_SECURE_ID)) {
                uidsOut->push_back(entryUid);
            }
        }
    }
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

Status KeyStoreService::reset(int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_RESET)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    mKeyStore->resetUser(get_user_id(callingUid), false);
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

Status KeyStoreService::onUserPasswordChanged(int32_t userId, const String16& password,
                                              int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_PASSWORD)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

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

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

Status KeyStoreService::onUserAdded(int32_t userId, int32_t parentId, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_USER_CHANGED)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    // 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.
        *aidl_return = static_cast<int32_t>(mKeyStore->copyMasterKey(parentId, userId));
        return Status::ok();
    } else {
        *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
        return Status::ok();
    }
}

Status KeyStoreService::onUserRemoved(int32_t userId, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_USER_CHANGED)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    mKeyStore->resetUser(userId, false);
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

Status KeyStoreService::lock(int32_t userId, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_LOCK)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    State state = mKeyStore->getState(userId);
    if (state != ::STATE_NO_ERROR) {
        ALOGD("calling lock in state: %d", state);
        *aidl_return = static_cast<int32_t>(ResponseCode(state));
        return Status::ok();
    }

    mKeyStore->getEnforcementPolicy().set_device_locked(true, userId);
    mKeyStore->lock(userId);
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

Status KeyStoreService::unlock(int32_t userId, const String16& pw, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_UNLOCK)) {
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }

    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;
        }
        *aidl_return = static_cast<int32_t>(ResponseCode(state));
        return Status::ok();
    }

    mKeyStore->getEnforcementPolicy().set_device_locked(false, userId);
    const String8 password8(pw);
    // read master key, decrypt with password, initialize mMasterKey*.
    *aidl_return = static_cast<int32_t>(mKeyStore->readMasterKey(password8, userId));
    return Status::ok();
}

Status KeyStoreService::isEmpty(int32_t userId, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkBinderPermission(P_IS_EMPTY)) {
        *aidl_return = static_cast<int32_t>(false);
        return Status::ok();
    }

    *aidl_return = static_cast<int32_t>(mKeyStore->isEmpty(userId));
    return Status::ok();
}

Status KeyStoreService::grant(const String16& name, int32_t granteeUid,
                              ::android::String16* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    auto result =
        checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
    if (!result.isOk()) {
        *aidl_return = String16();
        return Status::ok();
    }

    String8 name8(name);
    auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid);
    if (!lockedEntry) {
        *aidl_return = String16();
        return Status::ok();
    }

    *aidl_return = String16(mKeyStore->addGrant(lockedEntry, granteeUid).c_str());
    return Status::ok();
}

Status KeyStoreService::ungrant(const String16& name, int32_t granteeUid, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    KeyStoreServiceReturnCode result =
        checkBinderPermissionAndKeystoreState(P_GRANT, /*targetUid=*/-1, /*checkUnlocked=*/false);
    if (!result.isOk()) {
        *aidl_return = result.getErrorCode();
        return Status::ok();
    }

    String8 name8(name);

    auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), callingUid);
    if (!lockedEntry) {
        *aidl_return = static_cast<int32_t>(ResponseCode::KEY_NOT_FOUND);
    }

    *aidl_return = mKeyStore->removeGrant(lockedEntry, granteeUid);
    return Status::ok();
}

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

    auto lockedEntry = mKeyStore->getLockedBlobEntryIfExists(name8.string(), targetUid);
    if (!lockedEntry) {
        ALOGW("could not access key with alias %s for getmtime", name8.string());
        *time = -1L;
        return Status::ok();
    }

    std::string filename = lockedEntry->getKeyBlobPath();

    int fd = TEMP_FAILURE_RETRY(open(filename.c_str(), O_NOFOLLOW, O_RDONLY));
    if (fd < 0) {
        ALOGW("could not open %s for getmtime", filename.c_str());
        *time = -1L;
        return Status::ok();
    }

    struct stat s;
    int ret = fstat(fd, &s);
    close(fd);
    if (ret == -1) {
        ALOGW("could not stat %s for getmtime", filename.c_str());
        *time = -1L;
        return Status::ok();
    }

    *time = static_cast<int64_t>(s.st_mtime);
    return Status::ok();
}

Status KeyStoreService::is_hardware_backed(const String16& keyType, int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    *aidl_return = static_cast<int32_t>(mKeyStore->isHardwareBacked(keyType) ? 1 : 0);
    return Status::ok();
}

Status KeyStoreService::clear_uid(int64_t targetUid64, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    uid_t targetUid = getEffectiveUid(targetUid64);
    if (!checkBinderPermissionSelfOrSystem(P_CLEAR_UID, targetUid)) {
        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }
    ALOGI("clear_uid %" PRId64, targetUid64);

    mKeyStore->removeAllGrantsToUid(targetUid);

    ResponseCode rc;
    std::list<LockedKeyBlobEntry> entries;
    auto userDirName = mKeyStore->getUserStateDB().getUserStateByUid(targetUid)->getUserDirName();

    // list has a fence making sure no workers are modifying blob files before iterating the
    // data base. All returned entries are locked.
    std::tie(rc, entries) = LockedKeyBlobEntry::list(
        userDirName, [&](uid_t uid, const std::string&) -> bool { return uid == targetUid; });

    if (rc != ResponseCode::NO_ERROR) {
        return AIDL_RETURN(rc);
    }

    for (LockedKeyBlobEntry& lockedEntry : entries) {
        if (get_app_id(targetUid) == AID_SYSTEM) {
            Blob keyBlob;
            Blob charBlob;
            std::tie(rc, keyBlob, charBlob) = mKeyStore->get(lockedEntry);
            if (rc == ResponseCode::NO_ERROR && keyBlob.isCriticalToDeviceEncryption()) {
                // Do not clear keys critical to device encryption under system uid.
                continue;
            }
        }
        mKeyStore->del(lockedEntry);
    }
    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::addRngEntropy(
    const ::android::sp<::android::security::keystore::IKeystoreResponseCallback>& cb,
    const ::std::vector<uint8_t>& entropy, int32_t flags, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    auto device = mKeyStore->getDevice(flagsToSecurityLevel(flags));
    if (!device) {
        return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
    }

    device->addRngEntropy(entropy, [device, cb](Return<ErrorCode> rc) {
        cb->onFinished(KeyStoreServiceReturnCode(KS_HANDLE_HIDL_ERROR(device, rc)));
    });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::generateKey(
    const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
    const String16& name, const KeymasterArguments& params, const ::std::vector<uint8_t>& entropy,
    int uid, int flags, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    // TODO(jbires): remove this getCallingUid call upon implementation of b/25646100
    uid_t originalUid = IPCThreadState::self()->getCallingUid();
    uid = getEffectiveUid(uid);
    auto logOnScopeExit = android::base::make_scope_guard([&] {
        if (__android_log_security()) {
            android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED)
                << int32_t(*_aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
                << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
        }
    });
    KeyStoreServiceReturnCode rc =
        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!rc.isOk()) {
        return AIDL_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 AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }

    if (containsTag(params.getParameters(), Tag::INCLUDE_UNIQUE_ID)) {
        // TODO(jbires): remove uid checking upon implementation of b/25646100
        if (!checkBinderPermission(P_GEN_UNIQUE_ID) ||
            originalUid != IPCThreadState::self()->getCallingUid()) {
            return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
        }
    }

    SecurityLevel securityLevel = flagsToSecurityLevel(flags);
    auto dev = mKeyStore->getDevice(securityLevel);
    if (!dev) {
        return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
    }

    String8 name8(name);
    auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid);
    if (!lockedEntry) {
        return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
    }

    logOnScopeExit.Disable();

    dev->generateKey(
        std::move(lockedEntry), params.getParameters(), entropy, flags,
        [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
            if (__android_log_security()) {
                android_log_event_list(SEC_TAG_AUTH_KEY_GENERATED)
                    << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
            }
            cb->onFinished(rc,
                           android::security::keymaster::KeyCharacteristics(keyCharacteristics));
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::getKeyCharacteristics(
    const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
    const String16& name, const ::android::security::keymaster::KeymasterBlob& clientId,
    const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
    int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;

    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 AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }

    String8 name8(name);

    ResponseCode rc;
    Blob keyBlob;
    Blob charBlob;
    LockedKeyBlobEntry lockedEntry;

    std::tie(rc, keyBlob, charBlob, lockedEntry) =
        mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);

    if (rc != ResponseCode::NO_ERROR) {
        return AIDL_RETURN(rc);
    }

    auto dev = mKeyStore->getDevice(keyBlob);
    if (!dev) {
        return AIDL_RETURN(ResponseCode::SYSTEM_ERROR);
    }

    // If the charBlob is up to date, it simply moves the argument blobs to the returned blobs
    // and extracts the characteristics on the way. Otherwise it updates the cache file with data
    // from keymaster. It may also upgrade the key blob.
    dev->getKeyCharacteristics(
        std::move(lockedEntry), clientId.getData(), appData.getData(), std::move(keyBlob),
        std::move(charBlob),
        [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
            cb->onFinished(rc,
                           android::security::keymaster::KeyCharacteristics(keyCharacteristics));
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::importKey(
    const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
    const String16& name, const KeymasterArguments& params, int32_t format,
    const ::std::vector<uint8_t>& keyData, int uid, int flags, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    uid = getEffectiveUid(uid);
    auto logOnScopeExit = android::base::make_scope_guard([&] {
        if (__android_log_security()) {
            android_log_event_list(SEC_TAG_KEY_IMPORTED)
                << int32_t(*_aidl_return == static_cast<int32_t>(ResponseCode::NO_ERROR))
                << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
        }
    });
    KeyStoreServiceReturnCode rc =
        checkBinderPermissionAndKeystoreState(P_INSERT, uid, flags & KEYSTORE_FLAG_ENCRYPTED);
    if (!rc.isOk()) {
        LOG(ERROR) << "permissission denied";
        return AIDL_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 AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }

    SecurityLevel securityLevel = flagsToSecurityLevel(flags);
    auto dev = mKeyStore->getDevice(securityLevel);
    if (!dev) {
        LOG(ERROR) << "importKey - cound not get keymaster device";
        return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
    }

    String8 name8(name);
    auto lockedEntry = mKeyStore->getLockedBlobEntryIfNotExists(name8.string(), uid);
    if (!lockedEntry) {
        LOG(ERROR) << "importKey - key: " << name8.string() << " " << int(uid)
                   << " already exists.";
        return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
    }

    logOnScopeExit.Disable();

    dev->importKey(
        std::move(lockedEntry), params.getParameters(), KeyFormat(format), keyData, flags,
        [cb, uid, name](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
            if (__android_log_security()) {
                android_log_event_list(SEC_TAG_KEY_IMPORTED)
                    << rc.isOk() << String8(name) << int32_t(uid) << LOG_ID_SECURITY;
            }
            cb->onFinished(rc,
                           android::security::keymaster::KeyCharacteristics(keyCharacteristics));
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::exportKey(
    const ::android::sp<::android::security::keystore::IKeystoreExportKeyCallback>& cb,
    const String16& name, int32_t format,
    const ::android::security::keymaster::KeymasterBlob& clientId,
    const ::android::security::keymaster::KeymasterBlob& appData, int32_t uid,
    int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;

    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);
        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }

    String8 name8(name);

    KeyStoreServiceReturnCode rc;
    Blob keyBlob;
    Blob charBlob;
    LockedKeyBlobEntry lockedEntry;

    std::tie(rc, keyBlob, charBlob, lockedEntry) =
        mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);
    if (!rc.isOk()) {
        return AIDL_RETURN(rc);
    }

    auto dev = mKeyStore->getDevice(keyBlob);

    dev->exportKey(std::move(lockedEntry), KeyFormat(format), clientId.getData(), appData.getData(),
                   std::move(keyBlob), std::move(charBlob),
                   [cb](ExportResult exportResult) { cb->onFinished(exportResult); });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::begin(const sp<IKeystoreOperationResultCallback>& cb,
                              const sp<IBinder>& appToken, const String16& name, int32_t purpose,
                              bool pruneable, const KeymasterArguments& params,
                              const ::std::vector<uint8_t>& entropy, int32_t uid,
                              int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    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);
        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }
    if (!pruneable && get_app_id(callingUid) != AID_SYSTEM) {
        ALOGE("Non-system uid %d trying to start non-pruneable operation", callingUid);
        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }
    if (!checkAllowedOperationParams(params.getParameters())) {
        return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
    }

    String8 name8(name);
    Blob keyBlob;
    Blob charBlob;
    LockedKeyBlobEntry lockedEntry;
    ResponseCode rc;

    std::tie(rc, keyBlob, charBlob, lockedEntry) =
        mKeyStore->getKeyForName(name8, targetUid, TYPE_KEYMASTER_10);

    if (rc == ResponseCode::LOCKED && keyBlob.isSuperEncrypted()) {
        return AIDL_RETURN(ErrorCode::KEY_USER_NOT_AUTHENTICATED);
    }
    if (rc != ResponseCode::NO_ERROR) return AIDL_RETURN(rc);

    auto dev = mKeyStore->getDevice(keyBlob);
    AuthorizationSet opParams = params.getParameters();

    dev->begin(std::move(lockedEntry), appToken, std::move(keyBlob), std::move(charBlob), pruneable,
               static_cast<KeyPurpose>(purpose), std::move(opParams), entropy,
               [this, cb, dev](OperationResult result_) {
                   if (result_.resultCode.isOk() ||
                       result_.resultCode == ResponseCode::OP_AUTH_NEEDED) {
                       addOperationDevice(result_.token, dev);
                   }
                   cb->onFinished(result_);
               });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::update(const ::android::sp<IKeystoreOperationResultCallback>& cb,
                               const ::android::sp<::android::IBinder>& token,
                               const ::android::security::keymaster::KeymasterArguments& params,
                               const ::std::vector<uint8_t>& input, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkAllowedOperationParams(params.getParameters())) {
        return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
    }

    auto dev = getOperationDevice(token);
    if (!dev) {
        return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
    }

    dev->update(token, params.getParameters(), input, [this, cb, token](OperationResult result_) {
        if (!result_.resultCode.isOk()) {
            removeOperationDevice(token);
        }
        cb->onFinished(result_);
    });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::finish(const ::android::sp<IKeystoreOperationResultCallback>& cb,
                               const ::android::sp<::android::IBinder>& token,
                               const ::android::security::keymaster::KeymasterArguments& params,
                               const ::std::vector<uint8_t>& signature,
                               const ::std::vector<uint8_t>& entropy, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    if (!checkAllowedOperationParams(params.getParameters())) {
        return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
    }

    auto dev = getOperationDevice(token);
    if (!dev) {
        return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
    }

    dev->finish(token, params.getParameters(), {}, signature, entropy,
                [this, cb, token](OperationResult result_) {
                    if (!result_.resultCode.isOk()) {
                        removeOperationDevice(token);
                    }
                    cb->onFinished(result_);
                });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::abort(const ::android::sp<IKeystoreResponseCallback>& cb,
                              const ::android::sp<::android::IBinder>& token,
                              int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    auto dev = getOperationDevice(token);
    if (!dev) {
        return AIDL_RETURN(ErrorCode::INVALID_OPERATION_HANDLE);
    }

    dev->abort(token, [cb](KeyStoreServiceReturnCode rc) { cb->onFinished(rc); });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::addAuthToken(const ::std::vector<uint8_t>& authTokenAsVector,
                                     int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;

    // 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());
        *aidl_return = static_cast<int32_t>(ResponseCode::PERMISSION_DENIED);
        return Status::ok();
    }
    if (authTokenAsVector.size() != sizeof(hw_auth_token_t)) {
        *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
        return Status::ok();
    }

    hw_auth_token_t authToken;
    memcpy(reinterpret_cast<void*>(&authToken), authTokenAsVector.data(), sizeof(hw_auth_token_t));
    if (authToken.version != 0) {
        *aidl_return = KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT).getErrorCode();
        return Status::ok();
    }

    mKeyStore->getAuthTokenTable().AddAuthenticationToken(
        hidlVec2AuthToken(hidl_vec<uint8_t>(authTokenAsVector)));
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

int isDeviceIdAttestationRequested(const KeymasterArguments& params) {
    const hardware::hidl_vec<KeyParameter>& paramsVec = params.getParameters();
    int result = 0;
    for (size_t i = 0; i < paramsVec.size(); ++i) {
        switch (paramsVec[i].tag) {
        case Tag::ATTESTATION_ID_BRAND:
        case Tag::ATTESTATION_ID_DEVICE:
        case Tag::ATTESTATION_ID_MANUFACTURER:
        case Tag::ATTESTATION_ID_MODEL:
        case Tag::ATTESTATION_ID_PRODUCT:
            result |= ID_ATTESTATION_REQUEST_GENERIC_INFO;
            break;
        case Tag::ATTESTATION_ID_IMEI:
        case Tag::ATTESTATION_ID_MEID:
        case Tag::ATTESTATION_ID_SERIAL:
            result |= ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
            break;
        default:
            continue;
        }
    }
    return result;
}

Status KeyStoreService::attestKey(
    const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
    const String16& name, const KeymasterArguments& params, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL
    if (!checkAllowedOperationParams(params.getParameters())) {
        return AIDL_RETURN(ErrorCode::INVALID_ARGUMENT);
    }

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

    int needsIdAttestation = isDeviceIdAttestationRequested(params);
    bool needsUniqueIdAttestation = needsIdAttestation & ID_ATTESTATION_REQUEST_UNIQUE_DEVICE_ID;
    bool isPrimaryUserSystemUid = (callingUid == AID_SYSTEM);
    bool isSomeUserSystemUid = (get_app_id(callingUid) == AID_SYSTEM);
    // Allow system context from any user to request attestation with basic device information,
    // while only allow system context from user 0 (device owner) to request attestation with
    // unique device ID.
    if ((needsIdAttestation && !isSomeUserSystemUid) ||
        (needsUniqueIdAttestation && !isPrimaryUserSystemUid)) {
        return AIDL_RETURN(KeyStoreServiceReturnCode(ErrorCode::INVALID_ARGUMENT));
    }

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

    String8 name8(name);
    Blob keyBlob;
    Blob charBlob;
    LockedKeyBlobEntry lockedEntry;

    std::tie(rc, keyBlob, charBlob, lockedEntry) =
        mKeyStore->getKeyForName(name8, callingUid, TYPE_KEYMASTER_10);

    auto dev = mKeyStore->getDevice(keyBlob);
    auto hidlKey = blob2hidlVec(keyBlob);
    dev->attestKey(
        std::move(hidlKey), mutableParams.hidl_data(),
        [dev, cb](Return<void> rc,
                  std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
            auto& [ret, certChain] = hidlResult;
            if (!rc.isOk()) {
                cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
            } else if (ret != ErrorCode::OK) {
                dev->logIfKeymasterVendorError(ret);
                cb->onFinished(KeyStoreServiceReturnCode(ret), {});
            } else {
                cb->onFinished(KeyStoreServiceReturnCode(ret),
                               KeymasterCertificateChain(std::move(certChain)));
            }
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

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

Status KeyStoreService::attestDeviceIds(
    const ::android::sp<::android::security::keystore::IKeystoreCertificateChainCallback>& cb,
    const KeymasterArguments& params, int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    // check null output if method signature is updated and return ErrorCode::OUTPUT_PARAMETER_NULL

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

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

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

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

    // Generate temporary key.
    auto dev = mKeyStore->getDevice(SecurityLevel::TRUSTED_ENVIRONMENT);

    if (!dev) {
        return AIDL_RETURN(ResponseCode::SYSTEM_ERROR);
    }


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

    std::promise<KeyStoreServiceReturnCode> resultPromise;
    auto resultFuture = resultPromise.get_future();

    dev->generateKey(
        keyCharacteristics.hidl_data(),
        [cb, dev, CAPTURE_MOVE(mutableParams)](
            Return<void> rc,
            std::tuple<ErrorCode, ::std::vector<uint8_t>, KeyCharacteristics>&& hidlResult) {
            auto& [ret, hidlKeyBlob_, dummyCharacteristics] = hidlResult;
            auto hidlKeyBlob = std::move(hidlKeyBlob_);
            if (!rc.isOk()) {
                cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
                return;
            }
            if (ret != ErrorCode::OK) {
                dev->logIfKeymasterVendorError(ret);
                cb->onFinished(KeyStoreServiceReturnCode(ret), {});
                return;
            }
            dev->attestKey(
                hidlKeyBlob, mutableParams.hidl_data(),
                [cb, dev,
                 hidlKeyBlob](Return<void> rc,
                              std::tuple<ErrorCode, hidl_vec<hidl_vec<uint8_t>>>&& hidlResult) {
                    auto& [ret, certChain] = hidlResult;
                    // schedule temp key for deletion
                    dev->deleteKey(std::move(hidlKeyBlob), [dev](Return<ErrorCode> rc) {
                        // log error but don't return an error
                        KS_HANDLE_HIDL_ERROR(dev, rc);
                    });
                    if (!rc.isOk()) {
                        cb->onFinished(KeyStoreServiceReturnCode(ResponseCode::SYSTEM_ERROR), {});
                        return;
                    }
                    if (ret == ErrorCode::OK) {
                        cb->onFinished(
                            KeyStoreServiceReturnCode(ret),
                            ::android::security::keymaster::KeymasterCertificateChain(certChain));
                    } else {
                        dev->logIfKeymasterVendorError(ret);
                        cb->onFinished(KeyStoreServiceReturnCode(ret), {});
                    }
                });
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::onDeviceOffBody(int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    // TODO(tuckeris): add permission check.  This should be callable from ClockworkHome only.
    mKeyStore->getAuthTokenTable().onDeviceOffBody();
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);
    return Status::ok();
}

Status KeyStoreService::importWrappedKey(
    const ::android::sp<::android::security::keystore::IKeystoreKeyCharacteristicsCallback>& cb,
    const ::android::String16& wrappedKeyAlias, const ::std::vector<uint8_t>& wrappedKey,
    const ::android::String16& wrappingKeyAlias, const ::std::vector<uint8_t>& maskingKey,
    const KeymasterArguments& params, int64_t rootSid, int64_t fingerprintSid,
    int32_t* _aidl_return) {
    KEYSTORE_SERVICE_LOCK;

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

    if (!checkBinderPermission(P_INSERT, callingUid)) {
        return AIDL_RETURN(ResponseCode::PERMISSION_DENIED);
    }

    String8 wrappingKeyName8(wrappingKeyAlias);

    KeyStoreServiceReturnCode rc;
    Blob wrappingKeyBlob;
    Blob wrappingCharBlob;
    LockedKeyBlobEntry wrappingLockedEntry;

    std::tie(rc, wrappingKeyBlob, wrappingCharBlob, wrappingLockedEntry) =
        mKeyStore->getKeyForName(wrappingKeyName8, callingUid, TYPE_KEYMASTER_10);
    if (!rc.isOk()) {
        return AIDL_RETURN(rc);
    }

    String8 wrappedKeyName8(wrappedKeyAlias);
    auto wrappedLockedEntry =
        mKeyStore->getLockedBlobEntryIfNotExists(wrappedKeyName8.string(), callingUid);
    if (!wrappedLockedEntry) {
        return AIDL_RETURN(ResponseCode::KEY_ALREADY_EXISTS);
    }

    SecurityLevel securityLevel = wrappingKeyBlob.getSecurityLevel();
    auto dev = mKeyStore->getDevice(securityLevel);
    if (!dev) {
        return AIDL_RETURN(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
    }

    dev->importWrappedKey(
        std::move(wrappingLockedEntry), std::move(wrappedLockedEntry), wrappedKey, maskingKey,
        params.getParameters(), std::move(wrappingKeyBlob), std::move(wrappingCharBlob), rootSid,
        fingerprintSid, [cb](KeyStoreServiceReturnCode rc, KeyCharacteristics keyCharacteristics) {
            cb->onFinished(rc,
                           ::android::security::keymaster::KeyCharacteristics(keyCharacteristics));
        });

    return AIDL_RETURN(ResponseCode::NO_ERROR);
}

Status KeyStoreService::presentConfirmationPrompt(const sp<IBinder>& listener,
                                                  const String16& promptText,
                                                  const ::std::vector<uint8_t>& extraData,
                                                  const String16& locale, int32_t uiOptionsAsFlags,
                                                  int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    return mKeyStore->getConfirmationManager().presentConfirmationPrompt(
        listener, promptText, extraData, locale, uiOptionsAsFlags, aidl_return);
}

Status KeyStoreService::cancelConfirmationPrompt(const sp<IBinder>& listener,
                                                 int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    return mKeyStore->getConfirmationManager().cancelConfirmationPrompt(listener, aidl_return);
}

Status KeyStoreService::isConfirmationPromptSupported(bool* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    return mKeyStore->getConfirmationManager().isConfirmationPromptSupported(aidl_return);
}

/**
 * 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 KeyParameters 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::RESET_SINCE_ID_ROTATION:
            return false;
        default:
            break;
        }
    }
    return true;
}

Status KeyStoreService::onKeyguardVisibilityChanged(bool isShowing, int32_t userId,
                                                    int32_t* aidl_return) {
    KEYSTORE_SERVICE_LOCK;
    mKeyStore->getEnforcementPolicy().set_device_locked(isShowing, userId);
    *aidl_return = static_cast<int32_t>(ResponseCode::NO_ERROR);

    return Status::ok();
}

}  // namespace keystore
