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

#include <dirent.h>
#include <fcntl.h>

#include <openssl/bio.h>

#include <utils/String16.h>
#include <utils/String8.h>

#include <android-base/scopeguard.h>
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <android/security/keystore/IKeystoreService.h>
#include <log/log_event_list.h>

#include <private/android_logger.h>

#include "keystore_utils.h"
#include "permissions.h"
#include <keystore/keystore_hidl_support.h>

#include "keymaster_worker.h"

namespace keystore {

const char* KeyStore::kOldMasterKey = ".masterkey";
const char* KeyStore::kMetaDataFile = ".metadata";

const android::String16 KeyStore::kRsaKeyType("RSA");
const android::String16 KeyStore::kEcKeyType("EC");

using android::String8;

KeyStore::KeyStore(const KeymasterDevices& kmDevices,
                   SecurityLevel minimalAllowedSecurityLevelForNewKeys)
    : mAllowNewFallback(minimalAllowedSecurityLevelForNewKeys == SecurityLevel::SOFTWARE),
      mConfirmationManager(new ConfirmationManager(this)) {
    memset(&mMetaData, '\0', sizeof(mMetaData));

    static_assert(std::tuple_size<std::decay_t<decltype(kmDevices)>>::value ==
                      std::tuple_size<decltype(mKmDevices)>::value,
                  "KmasterDevices and KeymasterWorkers must have the same size");
    for (size_t i = 0; i < kmDevices.size(); ++i) {
        if (kmDevices[SecurityLevel(i)]) {
            mKmDevices[SecurityLevel(i)] = std::make_shared<KeymasterWorker>(
                kmDevices[SecurityLevel(i)], this, SecurityLevel(i));
        }
    }
}

KeyStore::~KeyStore() {
}

ResponseCode KeyStore::initialize() {
    readMetaData();
    if (upgradeKeystore()) {
        writeMetaData();
    }

    return ResponseCode::NO_ERROR;
}

ResponseCode KeyStore::initializeUser(const android::String8& pw, uid_t userId) {
    auto userState = mUserStateDB.getUserState(userId);
    return userState->initialize(pw);
}

ResponseCode KeyStore::copyMasterKey(uid_t srcUser, uid_t dstUser) {
    auto userState = mUserStateDB.getUserState(dstUser);
    auto initState = mUserStateDB.getUserState(srcUser);
    return userState->copyMasterKey(&initState);
}

ResponseCode KeyStore::writeMasterKey(const android::String8& pw, uid_t userId) {
    auto userState = mUserStateDB.getUserState(userId);
    return userState->writeMasterKey(pw);
}

ResponseCode KeyStore::readMasterKey(const android::String8& pw, uid_t userId) {
    auto userState = mUserStateDB.getUserState(userId);
    return userState->readMasterKey(pw);
}

LockedKeyBlobEntry KeyStore::getLockedBlobEntryIfNotExists(const std::string& alias, uid_t uid) {
    KeyBlobEntry kbe(alias, mUserStateDB.getUserStateByUid(uid)->getUserDirName(), uid);
    auto result = LockedKeyBlobEntry::get(std::move(kbe));
    if (result->hasKeyBlob()) return {};
    return result;
}

std::optional<KeyBlobEntry> KeyStore::getBlobEntryIfExists(const std::string& alias, uid_t uid) {
    KeyBlobEntry kbe(alias, mUserStateDB.getUserStateByUid(uid)->getUserDirName(), uid);
    if (kbe.hasKeyBlob()) return kbe;

    // If this is one of the legacy UID->UID mappings, use it.
    uid_t euid = get_keystore_euid(uid);
    if (euid != uid) {
        kbe = KeyBlobEntry(alias, mUserStateDB.getUserStateByUid(euid)->getUserDirName(), euid);
        if (kbe.hasKeyBlob()) return kbe;
    }

    // They might be using a granted key.
    auto grant = mGrants.get(uid, alias);
    if (grant) {
        kbe = grant->entry_;
        if (kbe.hasKeyBlob()) return kbe;
    }
    return {};
}
LockedKeyBlobEntry KeyStore::getLockedBlobEntryIfExists(const std::string& alias, uid_t uid) {
    auto blobentry = getBlobEntryIfExists(alias, uid);
    if (!blobentry) return {};
    LockedKeyBlobEntry lockedentry = LockedKeyBlobEntry::get(std::move(*blobentry));
    if (!lockedentry || !lockedentry->hasKeyBlob()) return {};
    return lockedentry;
}

void KeyStore::resetUser(uid_t userId, bool keepUnenryptedEntries) {
    android::String8 prefix("");
    android::Vector<android::String16> aliases;

    auto userState = mUserStateDB.getUserState(userId);
    std::string userDirName = userState->getUserDirName();
    auto encryptionKey = userState->getEncryptionKey();
    auto state = userState->getState();
    // userState is a proxy that holds a lock which may be required by a worker.
    // LockedKeyBlobEntry::list has a fence that waits until all workers have finished which may
    // not happen if a user state lock is held. The following line relinquishes the lock.
    userState = {};

    ResponseCode rc;
    std::list<LockedKeyBlobEntry> matches;

    // must not be called by a keymaster worker. List waits for workers to relinquish all access
    // to blob entries
    std::tie(rc, matches) = LockedKeyBlobEntry::list(userDirName);
    if (rc != ResponseCode::NO_ERROR) {
        return;
    }

    for (LockedKeyBlobEntry& lockedEntry : matches) {
        bool shouldDelete = true;

        if (keepUnenryptedEntries) {
            Blob blob;
            Blob charBlob;
            ResponseCode rc;

            std::tie(rc, blob, charBlob) = lockedEntry.readBlobs(encryptionKey, state);

            switch (rc) {
            case ResponseCode::SYSTEM_ERROR:
            case ResponseCode::VALUE_CORRUPTED:
                // If we can't read blobs, delete them.
                shouldDelete = true;
                break;

            case ResponseCode::NO_ERROR:
            case ResponseCode::LOCKED:
                // Delete encrypted blobs but keep unencrypted blobs and super-encrypted blobs.  We
                // need to keep super-encrypted blobs so we can report that the user is
                // unauthenticated if a caller tries to use them, rather than reporting that they
                // don't exist.
                shouldDelete = blob.isEncrypted();
                break;

            default:
                ALOGE("Got unexpected return code %d from readBlobs", rc);
                // This shouldn't happen.  To be on the safe side, delete it.
                shouldDelete = true;
                break;
            }
        }
        if (shouldDelete) {
            del(lockedEntry);
        }
    }

    userState = mUserStateDB.getUserState(userId);
    if (!userState->deleteMasterKey()) {
        ALOGE("Failed to delete user %d's master key", userId);
    }
    if (!keepUnenryptedEntries) {
        if (!userState->reset()) {
            ALOGE("Failed to remove user %d's directory", userId);
        }
    }
}

bool KeyStore::isEmpty(uid_t userId) const {
    std::string userDirName;
    {
        // userState holds a lock which must be relinquished before list is called. This scope
        // prevents deadlocks.
        auto userState = mUserStateDB.getUserState(userId);
        if (!userState) {
            return true;
        }
        userDirName = userState->getUserDirName();
    }

    ResponseCode rc;
    std::list<LockedKeyBlobEntry> matches;

    // must not be called by a keymaster worker. List waits for workers to relinquish all access
    // to blob entries
    std::tie(rc, matches) = LockedKeyBlobEntry::list(userDirName);

    return rc == ResponseCode::SYSTEM_ERROR || matches.size() == 0;
}

void KeyStore::lock(uid_t userId) {
    auto userState = mUserStateDB.getUserState(userId);
    userState->zeroizeMasterKeysInMemory();
    userState->setState(STATE_LOCKED);
}

static void maybeLogKeyIntegrityViolation(const LockedKeyBlobEntry& lockedEntry,
                                          const BlobType type) {
    if (!__android_log_security() || (type != TYPE_KEY_PAIR && type != TYPE_KEYMASTER_10)) return;
    log_key_integrity_violation(lockedEntry->alias().c_str(), lockedEntry->uid());
}

std::tuple<ResponseCode, Blob, Blob> KeyStore::get(const LockedKeyBlobEntry& blobfile) {
    std::tuple<ResponseCode, Blob, Blob> result;

    uid_t userId = get_user_id(blobfile->uid());
    Blob& keyBlob = std::get<1>(result);
    ResponseCode& rc = std::get<0>(result);

    auto userState = mUserStateDB.getUserState(userId);
    BlobType type = BlobType::TYPE_ANY;
    auto logOnScopeExit = android::base::make_scope_guard([&] {
        if (rc == ResponseCode::VALUE_CORRUPTED) {
            maybeLogKeyIntegrityViolation(blobfile, type);
        }
    });

    result = blobfile.readBlobs(userState->getEncryptionKey(), userState->getState());
    if (rc != ResponseCode::NO_ERROR) {
        return result;
    }

    // update the type for logging (see scope_guard above)
    type = keyBlob.getType();

    const uint8_t version = keyBlob.getVersion();
    if (version < CURRENT_BLOB_VERSION) {
        /* If we upgrade the key, we need to write it to disk again. Then
         * it must be read it again since the blob is encrypted each time
         * it's written.
         */
        if (upgradeBlob(&keyBlob, version)) {
            if ((rc = this->put(blobfile, keyBlob, {})) != ResponseCode::NO_ERROR ||
                (result = blobfile.readBlobs(userState->getEncryptionKey(), userState->getState()),
                 rc) != ResponseCode::NO_ERROR) {
                return result;
            }
        }
    }

    return result;
}

ResponseCode KeyStore::put(const LockedKeyBlobEntry& blobfile, Blob keyBlob,
                           Blob characteristicsBlob) {
    auto userState = mUserStateDB.getUserStateByUid(blobfile->uid());
    return blobfile.writeBlobs(std::move(keyBlob), std::move(characteristicsBlob),
                               userState->getEncryptionKey(), userState->getState());
}

ResponseCode KeyStore::del(const LockedKeyBlobEntry& blobfile) {
    Blob keyBlob;
    Blob charactaristicsBlob;
    ResponseCode rc;
    uid_t uid = blobfile->uid();
    std::string alias = blobfile->alias();

    std::tie(rc, keyBlob, charactaristicsBlob) = get(blobfile);

    // after getting the blob from the file system we scrub the filesystem.
    mGrants.removeAllGrantsToKey(uid, alias);
    auto result = blobfile.deleteBlobs();

    if (rc != ResponseCode::NO_ERROR) {
        LOG(ERROR) << "get keyblob failed " << int(rc);
        return rc;
    }

    // if we got the blob successfully, we try and delete it from the keymaster device
    auto dev = getDevice(keyBlob);

    if (keyBlob.getType() == ::TYPE_KEYMASTER_10) {
        dev->deleteKey(blob2hidlVec(keyBlob), [dev, alias, uid](Return<ErrorCode> rc) {
            auto ret = KS_HANDLE_HIDL_ERROR(dev, rc);
            // A device doesn't have to implement delete_key.
            bool success = ret == ErrorCode::OK || ret == ErrorCode::UNIMPLEMENTED;
            if (__android_log_security()) {
                android_log_event_list(SEC_TAG_KEY_DESTROYED)
                    << int32_t(success) << alias << int32_t(uid) << LOG_ID_SECURITY;
            }
            if (!success) {
                LOG(ERROR) << "Keymaster delete for key " << alias << " of uid " << uid
                           << " failed";
            }
        });
    }

    return result;
}

std::string KeyStore::addGrant(const LockedKeyBlobEntry& blobfile, uid_t granteeUid) {
    return mGrants.put(granteeUid, blobfile);
}

bool KeyStore::removeGrant(const LockedKeyBlobEntry& blobfile, const uid_t granteeUid) {
    return mGrants.removeByFileAlias(granteeUid, blobfile);
}
void KeyStore::removeAllGrantsToUid(const uid_t granteeUid) {
    mGrants.removeAllGrantsToUid(granteeUid);
}

bool KeyStore::isHardwareBacked(const android::String16& keyType) const {
    // if strongbox device is present TEE must also be present and of sufficiently high version
    // to support all keys in hardware
    if (getDevice(SecurityLevel::STRONGBOX)) return true;
    if (!getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)) {
        ALOGW("can't get keymaster device");
        return false;
    }

    auto version = getDevice(SecurityLevel::TRUSTED_ENVIRONMENT)->halVersion();
    if (keyType == kRsaKeyType) return true;  // All versions support RSA
    return keyType == kEcKeyType && version.supportsEc;
}

std::tuple<ResponseCode, Blob, Blob, LockedKeyBlobEntry>
KeyStore::getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type) {
    std::tuple<ResponseCode, Blob, Blob, LockedKeyBlobEntry> result;
    auto& [rc, keyBlob, charBlob, lockedEntry] = result;

    lockedEntry = getLockedBlobEntryIfExists(keyName.string(), uid);

    if (!lockedEntry) return rc = ResponseCode::KEY_NOT_FOUND, std::move(result);

    std::tie(rc, keyBlob, charBlob) = get(lockedEntry);

    if (rc == ResponseCode::NO_ERROR) {
        if (keyBlob.getType() != type) return rc = ResponseCode::KEY_NOT_FOUND, std::move(result);
    }
    return result;
}

bool KeyStore::upgradeBlob(Blob* blob, const uint8_t oldVersion) {
    bool updated = false;
    uint8_t version = oldVersion;

    if (!blob || !(*blob)) return false;

    /* From V0 -> V1: All old types were unknown */
    if (version == 0) {
        ALOGE("Failed to upgrade key blob. Ancient blob version 0 is no longer supported");

        return false;
    }

    /* From V1 -> V2: All old keys were encrypted */
    if (version == 1) {
        ALOGV("upgrading to version 2");

        blob->setEncrypted(true);
        version = 2;
        updated = true;
    }

    /*
     * If we've updated, set the key blob to the right version
     * and write it.
     */
    if (updated) {
        blob->setVersion(version);
    }

    return updated;
}

void KeyStore::readMetaData() {
    int in = TEMP_FAILURE_RETRY(open(kMetaDataFile, O_RDONLY));
    if (in < 0) {
        return;
    }
    size_t fileLength = readFully(in, (uint8_t*)&mMetaData, sizeof(mMetaData));
    if (fileLength != sizeof(mMetaData)) {
        ALOGI("Metadata file is %zd bytes (%zd experted); upgrade?", fileLength, sizeof(mMetaData));
    }
    close(in);
}

void KeyStore::writeMetaData() {
    const char* tmpFileName = ".metadata.tmp";
    int out =
        TEMP_FAILURE_RETRY(open(tmpFileName, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    if (out < 0) {
        ALOGE("couldn't write metadata file: %s", strerror(errno));
        return;
    }
    size_t fileLength = writeFully(out, (uint8_t*)&mMetaData, sizeof(mMetaData));
    if (fileLength != sizeof(mMetaData)) {
        ALOGI("Could only write %zd bytes to metadata file (%zd expected)", fileLength,
              sizeof(mMetaData));
    }
    close(out);
    rename(tmpFileName, kMetaDataFile);
}

bool KeyStore::upgradeKeystore() {
    bool upgraded = false;

    if (mMetaData.version == 0) {
        auto userState = getUserStateDB().getUserStateByUid(0);

        // Initialize first so the directory is made.
        userState->initialize();

        // Migrate the old .masterkey file to user 0.
        if (access(kOldMasterKey, R_OK) == 0) {
            if (rename(kOldMasterKey, userState->getMasterKeyFileName().c_str()) < 0) {
                ALOGE("couldn't migrate old masterkey: %s", strerror(errno));
                return false;
            }
        }

        // Initialize again in case we had a key.
        userState->initialize();

        // Try to migrate existing keys.
        DIR* dir = opendir(".");
        if (!dir) {
            // Give up now; maybe we can upgrade later.
            ALOGE("couldn't open keystore's directory; something is wrong");
            return false;
        }

        struct dirent* file;
        while ((file = readdir(dir)) != nullptr) {
            // We only care about files.
            if (file->d_type != DT_REG) {
                continue;
            }

            // Skip anything that starts with a "."
            if (file->d_name[0] == '.') {
                continue;
            }

            // Find the current file's user.
            char* end;
            unsigned long thisUid = strtoul(file->d_name, &end, 10);
            if (end[0] != '_' || end[1] == 0) {
                continue;
            }
            auto otherUser = getUserStateDB().getUserStateByUid(thisUid);
            if (otherUser->getUserId() != 0) {
                unlinkat(dirfd(dir), file->d_name, 0);
            }

            // Rename the file into user directory.
            DIR* otherdir = opendir(otherUser->getUserDirName().c_str());
            if (otherdir == nullptr) {
                ALOGW("couldn't open user directory for rename");
                continue;
            }
            if (renameat(dirfd(dir), file->d_name, dirfd(otherdir), file->d_name) < 0) {
                ALOGW("couldn't rename blob: %s: %s", file->d_name, strerror(errno));
            }
            closedir(otherdir);
        }
        closedir(dir);

        mMetaData.version = 1;
        upgraded = true;
    }

    return upgraded;
}

void KeyStore::binderDied(const ::android::wp<IBinder>& who) {
    for (unsigned i = 0; i < mKmDevices.size(); ++i) {
        if (mKmDevices[SecurityLevel(i)]) mKmDevices[SecurityLevel(i)]->binderDied(who);
    }
    getConfirmationManager().binderDied(who);
}

}  // namespace keystore
