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

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), [alias, uid](Return<ErrorCode> rc) {
            auto ret = KS_HANDLE_HIDL_ERROR(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;
}

struct BIO_Delete {
    void operator()(BIO* p) const { BIO_free(p); }
};
typedef std::unique_ptr<BIO, BIO_Delete> Unique_BIO;

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
