/*
 * Copyright (c) 2019, 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 "credstore"

#include <chrono>

#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>

#include <cppbor.h>
#include <cppbor_parse.h>

#include <android/hardware/identity/support/IdentityCredentialSupport.h>

#include "CredentialData.h"
#include "Util.h"

namespace android {
namespace security {
namespace identity {

using std::optional;

string CredentialData::calculateCredentialFileName(const string& dataPath, uid_t ownerUid,
                                                   const string& name) {
    return android::base::StringPrintf(
        "%s/%d-%s", dataPath.c_str(), (int)ownerUid,
        android::hardware::identity::support::encodeHex(name).c_str());
}

CredentialData::CredentialData(const string& dataPath, uid_t ownerUid, const string& name)
    : dataPath_(dataPath), ownerUid_(ownerUid), name_(name), secureUserId_(0) {
    fileName_ = calculateCredentialFileName(dataPath_, ownerUid_, name_);
}

void CredentialData::setSecureUserId(int64_t secureUserId) {
    secureUserId_ = secureUserId;
}

void CredentialData::setCredentialData(const vector<uint8_t>& credentialData) {
    credentialData_ = credentialData;
}

void CredentialData::setAttestationCertificate(const vector<uint8_t>& attestationCertificate) {
    attestationCertificate_ = attestationCertificate;
}

void CredentialData::addSecureAccessControlProfile(
    const SecureAccessControlProfile& secureAccessControlProfile) {
    secureAccessControlProfiles_.push_back(secureAccessControlProfile);
}

void CredentialData::addEntryData(const string& namespaceName, const string& entryName,
                                  const EntryData& data) {
    idToEncryptedChunks_[namespaceName + ":" + entryName] = data;
}

bool CredentialData::saveToDisk() const {
    cppbor::Map map;

    map.add("secureUserId", secureUserId_);

    map.add("credentialData", credentialData_);

    map.add("attestationCertificate", attestationCertificate_);

    cppbor::Array sacpArray;
    for (const SecureAccessControlProfile& sacp : secureAccessControlProfiles_) {
        cppbor::Array array;
        array.add(sacp.id);
        array.add(sacp.readerCertificate.encodedCertificate);
        array.add(sacp.userAuthenticationRequired);
        array.add(sacp.timeoutMillis);
        array.add(sacp.secureUserId);
        vector<uint8_t> mac = sacp.mac;
        array.add(mac);
        sacpArray.add(std::move(array));
    }
    map.add("secureAccessControlProfiles", std::move(sacpArray));

    cppbor::Map encryptedBlobsMap;
    for (auto const& [nsAndName, entryData] : idToEncryptedChunks_) {
        cppbor::Array encryptedChunkArray;
        for (const vector<uint8_t>& encryptedChunk : entryData.encryptedChunks) {
            encryptedChunkArray.add(encryptedChunk);
        }
        cppbor::Array entryDataArray;
        entryDataArray.add(entryData.size);
        cppbor::Array idsArray;
        for (int32_t id : entryData.accessControlProfileIds) {
            idsArray.add(id);
        }
        entryDataArray.add(std::move(idsArray));
        entryDataArray.add(std::move(encryptedChunkArray));
        encryptedBlobsMap.add(nsAndName, std::move(entryDataArray));
    }
    map.add("entryData", std::move(encryptedBlobsMap));
    map.add("authKeyCount", keyCount_);
    map.add("maxUsesPerAuthKey", maxUsesPerKey_);
    map.add("minValidTimeMillis", minValidTimeMillis_);

    cppbor::Array authKeyDatasArray;
    for (const AuthKeyData& data : authKeyDatas_) {
        cppbor::Array array;
        // Fields 0-6 was in the original version in Android 11
        array.add(data.certificate);
        array.add(data.keyBlob);
        array.add(data.staticAuthenticationData);
        array.add(data.pendingCertificate);
        array.add(data.pendingKeyBlob);
        array.add(data.useCount);
        // Field 7 was added in Android 12
        array.add(data.expirationDateMillisSinceEpoch);
        authKeyDatasArray.add(std::move(array));
    }
    map.add("authKeyData", std::move(authKeyDatasArray));

    vector<uint8_t> credentialData = map.encode();

    return fileSetContents(fileName_, credentialData);
}

optional<SecureAccessControlProfile> parseSacp(const cppbor::Item& item) {
    const cppbor::Array* array = item.asArray();
    if (array == nullptr || array->size() < 6) {
        LOG(ERROR) << "The SACP CBOR is not an array with at least six elements (size="
                   << (array != nullptr ? array->size() : -1) << ")";
        return {};
    }
    const cppbor::Int* itemId = ((*array)[0])->asInt();
    const cppbor::Bstr* itemReaderCertificate = ((*array)[1])->asBstr();
    const cppbor::Simple* simple = ((*array)[2])->asSimple();
    const cppbor::Bool* itemUserAuthenticationRequired =
        (simple != nullptr ? (simple->asBool()) : nullptr);
    const cppbor::Int* itemTimeoutMillis = ((*array)[3])->asInt();
    const cppbor::Int* itesecureUserId_ = ((*array)[4])->asInt();
    const cppbor::Bstr* itemMac = ((*array)[5])->asBstr();
    if (itemId == nullptr || itemReaderCertificate == nullptr ||
        itemUserAuthenticationRequired == nullptr || itemTimeoutMillis == nullptr ||
        itesecureUserId_ == nullptr || itemMac == nullptr) {
        LOG(ERROR) << "One or more items SACP array in CBOR is of wrong type";
        return {};
    }
    SecureAccessControlProfile sacp;
    sacp.id = itemId->value();
    sacp.readerCertificate.encodedCertificate = itemReaderCertificate->value();
    sacp.userAuthenticationRequired = itemUserAuthenticationRequired->value();
    sacp.timeoutMillis = itemTimeoutMillis->value();
    sacp.secureUserId = itesecureUserId_->value();
    sacp.mac = itemMac->value();
    return sacp;
}

optional<AuthKeyData> parseAuthKeyData(const cppbor::Item& item) {
    const cppbor::Array* array = item.asArray();
    if (array == nullptr || array->size() < 6) {
        LOG(ERROR) << "The AuthKeyData CBOR is not an array with at least six elements";
        return {};
    }
    const cppbor::Bstr* itemCertificate = ((*array)[0])->asBstr();
    const cppbor::Bstr* itemKeyBlob = ((*array)[1])->asBstr();
    const cppbor::Bstr* itemStaticAuthenticationData = ((*array)[2])->asBstr();
    const cppbor::Bstr* itemPendingCertificate = ((*array)[3])->asBstr();
    const cppbor::Bstr* itemPendingKeyBlob = ((*array)[4])->asBstr();
    const cppbor::Int* itemUseCount = ((*array)[5])->asInt();
    if (itemCertificate == nullptr || itemKeyBlob == nullptr ||
        itemStaticAuthenticationData == nullptr || itemPendingCertificate == nullptr ||
        itemPendingKeyBlob == nullptr || itemUseCount == nullptr) {
        LOG(ERROR) << "One or more items in AuthKeyData array in CBOR is of wrong type";
        return {};
    }
    // expirationDateMillisSinceEpoch was added as the 7th element for Android 12. If not
    // present, default to longest possible expiration date.
    int64_t expirationDateMillisSinceEpoch = INT64_MAX;
    if (array->size() >= 7) {
        const cppbor::Int* itemExpirationDateMillisSinceEpoch = ((*array)[6])->asInt();
        expirationDateMillisSinceEpoch = itemExpirationDateMillisSinceEpoch->value();
    }
    AuthKeyData authKeyData;
    authKeyData.certificate = itemCertificate->value();
    authKeyData.keyBlob = itemKeyBlob->value();
    authKeyData.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
    authKeyData.staticAuthenticationData = itemStaticAuthenticationData->value();
    authKeyData.pendingCertificate = itemPendingCertificate->value();
    authKeyData.pendingKeyBlob = itemPendingKeyBlob->value();
    authKeyData.useCount = itemUseCount->value();
    return authKeyData;
}

vector<int32_t> parseAccessControlProfileIds(const cppbor::Item& item) {
    const cppbor::Array* array = item.asArray();
    if (array == nullptr) {
        LOG(ERROR) << "The accessControlProfileIds member is not an array";
        return {};
    }

    vector<int32_t> accessControlProfileIds;
    for (size_t n = 0; n < array->size(); n++) {
        const cppbor::Int* itemInt = ((*array)[n])->asInt();
        if (itemInt == nullptr) {
            LOG(ERROR) << "An item in the accessControlProfileIds array is not a bstr";
            return {};
        }
        accessControlProfileIds.push_back(itemInt->value());
    }
    return accessControlProfileIds;
}

optional<vector<vector<uint8_t>>> parseEncryptedChunks(const cppbor::Item& item) {
    const cppbor::Array* array = item.asArray();
    if (array == nullptr) {
        LOG(ERROR) << "The encryptedChunks member is not an array";
        return {};
    }

    vector<vector<uint8_t>> encryptedChunks;
    for (size_t n = 0; n < array->size(); n++) {
        const cppbor::Bstr* itemBstr = ((*array)[n])->asBstr();
        if (itemBstr == nullptr) {
            LOG(ERROR) << "An item in the encryptedChunks array is not a bstr";
            return {};
        }
        encryptedChunks.push_back(itemBstr->value());
    }
    return encryptedChunks;
}

bool CredentialData::loadFromDisk() {
    // Reset all data.
    credentialData_.clear();
    attestationCertificate_.clear();
    secureAccessControlProfiles_.clear();
    idToEncryptedChunks_.clear();
    authKeyDatas_.clear();
    keyCount_ = 0;
    maxUsesPerKey_ = 1;
    minValidTimeMillis_ = 0;

    optional<vector<uint8_t>> data = fileGetContents(fileName_);
    if (!data) {
        LOG(ERROR) << "Error loading data";
        return false;
    }

    auto [item, _ /* newPos */, message] = cppbor::parse(data.value());
    if (item == nullptr) {
        LOG(ERROR) << "Data loaded from " << fileName_ << " is not valid CBOR: " << message;
        return false;
    }

    const cppbor::Map* map = item->asMap();
    if (map == nullptr) {
        LOG(ERROR) << "Top-level item is not a map";
        return false;
    }

    for (size_t n = 0; n < map->size(); n++) {
        auto& [keyItem, valueItem] = (*map)[n];
        const cppbor::Tstr* tstr = keyItem->asTstr();
        if (tstr == nullptr) {
            LOG(ERROR) << "Key item in top-level map is not a tstr";
            return false;
        }
        const string& key = tstr->value();

        if (key == "secureUserId") {
            const cppbor::Int* number = valueItem->asInt();
            if (number == nullptr) {
                LOG(ERROR) << "Value for secureUserId is not a number";
                return false;
            }
            secureUserId_ = number->value();
        } else if (key == "credentialData") {
            const cppbor::Bstr* valueBstr = valueItem->asBstr();
            if (valueBstr == nullptr) {
                LOG(ERROR) << "Value for credentialData is not a bstr";
                return false;
            }
            credentialData_ = valueBstr->value();
        } else if (key == "attestationCertificate") {
            const cppbor::Bstr* valueBstr = valueItem->asBstr();
            if (valueBstr == nullptr) {
                LOG(ERROR) << "Value for attestationCertificate is not a bstr";
                return false;
            }
            attestationCertificate_ = valueBstr->value();
        } else if (key == "secureAccessControlProfiles") {
            const cppbor::Array* array = valueItem->asArray();
            if (array == nullptr) {
                LOG(ERROR) << "Value for attestationCertificate is not an array";
                return false;
            }
            for (size_t m = 0; m < array->size(); m++) {
                const std::unique_ptr<cppbor::Item>& item = (*array)[m];
                optional<SecureAccessControlProfile> sacp = parseSacp(*item);
                if (!sacp) {
                    LOG(ERROR) << "Error parsing SecureAccessControlProfile";
                    return false;
                }
                secureAccessControlProfiles_.push_back(sacp.value());
            }

        } else if (key == "entryData") {
            const cppbor::Map* map = valueItem->asMap();
            if (map == nullptr) {
                LOG(ERROR) << "Value for encryptedChunks is not an map";
                return false;
            }
            for (size_t m = 0; m < map->size(); m++) {
                auto& [ecKeyItem, ecValueItem] = (*map)[m];
                const cppbor::Tstr* ecTstr = ecKeyItem->asTstr();
                if (ecTstr == nullptr) {
                    LOG(ERROR) << "Key item in encryptedChunks map is not a tstr";
                    return false;
                }
                const string& ecId = ecTstr->value();

                const cppbor::Array* ecEntryArrayItem = ecValueItem->asArray();
                if (ecEntryArrayItem == nullptr || ecEntryArrayItem->size() < 3) {
                    LOG(ERROR) << "Value item in encryptedChunks map is an array with at least two "
                                  "elements";
                    return false;
                }
                const cppbor::Int* ecEntrySizeItem = (*ecEntryArrayItem)[0]->asInt();
                if (ecEntrySizeItem == nullptr) {
                    LOG(ERROR) << "Entry size not a number";
                    return false;
                }
                uint64_t entrySize = ecEntrySizeItem->value();

                optional<vector<int32_t>> accessControlProfileIds =
                    parseAccessControlProfileIds(*(*ecEntryArrayItem)[1]);
                if (!accessControlProfileIds) {
                    LOG(ERROR) << "Error parsing access control profile ids";
                    return false;
                }

                optional<vector<vector<uint8_t>>> encryptedChunks =
                    parseEncryptedChunks(*(*ecEntryArrayItem)[2]);
                if (!encryptedChunks) {
                    LOG(ERROR) << "Error parsing encrypted chunks";
                    return false;
                }

                EntryData data;
                data.size = entrySize;
                data.accessControlProfileIds = accessControlProfileIds.value();
                data.encryptedChunks = encryptedChunks.value();
                idToEncryptedChunks_[ecId] = data;
            }

        } else if (key == "authKeyData") {
            const cppbor::Array* array = valueItem->asArray();
            if (array == nullptr) {
                LOG(ERROR) << "Value for authData is not an array";
                return false;
            }
            for (size_t m = 0; m < array->size(); m++) {
                const std::unique_ptr<cppbor::Item>& item = (*array)[m];
                optional<AuthKeyData> authKeyData = parseAuthKeyData(*item);
                if (!authKeyData) {
                    LOG(ERROR) << "Error parsing AuthKeyData";
                    return false;
                }
                authKeyDatas_.push_back(authKeyData.value());
            }

        } else if (key == "authKeyCount") {
            const cppbor::Int* number = valueItem->asInt();
            if (number == nullptr) {
                LOG(ERROR) << "Value for authKeyCount is not a number";
                return false;
            }
            keyCount_ = number->value();

        } else if (key == "maxUsesPerAuthKey") {
            const cppbor::Int* number = valueItem->asInt();
            if (number == nullptr) {
                LOG(ERROR) << "Value for maxUsesPerAuthKey is not a number";
                return false;
            }
            maxUsesPerKey_ = number->value();

        } else if (key == "minValidTimeMillis") {
            const cppbor::Int* number = valueItem->asInt();
            if (number == nullptr) {
                LOG(ERROR) << "Value for minValidTimeMillis is not a number";
                return false;
            }
            minValidTimeMillis_ = number->value();
        }
    }

    if (credentialData_.size() == 0) {
        LOG(ERROR) << "Missing credentialData";
        return false;
    }

    if (attestationCertificate_.size() == 0) {
        LOG(ERROR) << "Missing attestationCertificate";
        return false;
    }

    if (size_t(keyCount_) != authKeyDatas_.size()) {
        LOG(ERROR) << "keyCount_=" << keyCount_
                   << " != authKeyDatas_.size()=" << authKeyDatas_.size();
        return false;
    }

    return true;
}

const vector<uint8_t>& CredentialData::getCredentialData() const {
    return credentialData_;
}

int64_t CredentialData::getSecureUserId() {
    return secureUserId_;
}

const vector<uint8_t>& CredentialData::getAttestationCertificate() const {
    return attestationCertificate_;
}

const vector<SecureAccessControlProfile>& CredentialData::getSecureAccessControlProfiles() const {
    return secureAccessControlProfiles_;
}

bool CredentialData::hasEntryData(const string& namespaceName, const string& entryName) const {
    string id = namespaceName + ":" + entryName;
    auto iter = idToEncryptedChunks_.find(id);
    if (iter == idToEncryptedChunks_.end()) {
        return false;
    }
    return true;
}

optional<EntryData> CredentialData::getEntryData(const string& namespaceName,
                                                 const string& entryName) const {
    string id = namespaceName + ":" + entryName;
    auto iter = idToEncryptedChunks_.find(id);
    if (iter == idToEncryptedChunks_.end()) {
        return {};
    }
    return iter->second;
}

bool CredentialData::deleteCredential() {
    if (unlink(fileName_.c_str()) != 0) {
        PLOG(ERROR) << "Error deleting " << fileName_;
        return false;
    }
    return true;
}

optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ownerUid,
                                                const string& name) {
    struct stat statbuf;
    string filename = calculateCredentialFileName(dataPath, ownerUid, name);
    if (stat(filename.c_str(), &statbuf) != 0) {
        if (errno == ENOENT) {
            return false;
        }
        PLOG(ERROR) << "Error getting information about " << filename;
        return {};
    }
    return true;
}

// ---

void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
                                                    int64_t minValidTimeMillis) {
    keyCount_ = keyCount;
    maxUsesPerKey_ = maxUsesPerKey;
    minValidTimeMillis_ = minValidTimeMillis;

    // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
    // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
    // and |pendingCertificate| fields. Those will be filled out when the
    // getAuthKeysNeedingCertification() is called.
    //
    // If shrinking, we'll just delete the AuthKeyData structs at the end. There's nothing
    // else to do, the HAL doesn't need to know we're nuking these authentication keys.
    //
    // Therefore, in either case it's as simple as just resizing the vector.
    authKeyDatas_.resize(keyCount_);
}

const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
    return authKeyDatas_;
}

tuple<int /* keyCount */, int /*maxUsersPerKey */, int64_t /* minValidTimeMillis */>
CredentialData::getAvailableAuthenticationKeys() const {
    return std::make_tuple(keyCount_, maxUsesPerKey_, minValidTimeMillis_);
}

AuthKeyData* CredentialData::findAuthKey_(bool allowUsingExhaustedKeys,
                                          bool allowUsingExpiredKeys) {
    AuthKeyData* candidate = nullptr;

    int64_t nowMilliSeconds =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) * 1000;

    int n = 0;
    for (AuthKeyData& data : authKeyDatas_) {
        if (nowMilliSeconds > data.expirationDateMillisSinceEpoch) {
            if (!allowUsingExpiredKeys) {
                continue;
            }
        }
        if (data.certificate.size() != 0) {
            // Not expired, include in normal check
            if (candidate == nullptr || data.useCount < candidate->useCount) {
                candidate = &data;
            }
        }
        n++;
    }

    if (candidate == nullptr) {
        return nullptr;
    }

    if (candidate->useCount >= maxUsesPerKey_ && !allowUsingExhaustedKeys) {
        return nullptr;
    }

    return candidate;
}

const AuthKeyData* CredentialData::selectAuthKey(bool allowUsingExhaustedKeys,
                                                 bool allowUsingExpiredKeys,
                                                 bool incrementUsageCount) {
    AuthKeyData* candidate;

    // First try to find a un-expired key..
    candidate = findAuthKey_(allowUsingExhaustedKeys, false);
    if (candidate == nullptr) {
        // That didn't work, there are no un-expired keys and we don't allow using expired keys.
        if (!allowUsingExpiredKeys) {
            return nullptr;
        }

        // See if there's an expired key then...
        candidate = findAuthKey_(allowUsingExhaustedKeys, true);
        if (candidate == nullptr) {
            return nullptr;
        }
    }

    if (incrementUsageCount) {
        candidate->useCount += 1;
    }
    return candidate;
}

optional<vector<vector<uint8_t>>>
CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder) {

    vector<vector<uint8_t>> keysNeedingCert;

    int64_t nowMilliSeconds =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) * 1000;

    for (AuthKeyData& data : authKeyDatas_) {
        bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
        int64_t expirationDateAdjusted = data.expirationDateMillisSinceEpoch - minValidTimeMillis_;
        bool keyBeyondAdjustedExpirationDate = (nowMilliSeconds > expirationDateAdjusted);
        bool newKeyNeeded =
            (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondAdjustedExpirationDate;
        bool certificationPending = (data.pendingCertificate.size() > 0);
        if (newKeyNeeded && !certificationPending) {
            vector<uint8_t> signingKeyBlob;
            Certificate signingKeyCertificate;
            if (!halBinder->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate)
                     .isOk()) {
                LOG(ERROR) << "Error generating signing key-pair";
                return {};
            }
            data.pendingCertificate = signingKeyCertificate.encodedCertificate;
            data.pendingKeyBlob = signingKeyBlob;
            certificationPending = true;
        }

        if (certificationPending) {
            keysNeedingCert.push_back(data.pendingCertificate);
        }
    }
    return keysNeedingCert;
}

bool CredentialData::storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
                                                   int64_t expirationDateMillisSinceEpoch,
                                                   const vector<uint8_t>& staticAuthData) {
    for (AuthKeyData& data : authKeyDatas_) {
        if (data.pendingCertificate == authenticationKey) {
            data.certificate = data.pendingCertificate;
            data.keyBlob = data.pendingKeyBlob;
            data.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
            data.staticAuthenticationData = staticAuthData;
            data.pendingCertificate.clear();
            data.pendingKeyBlob.clear();
            data.useCount = 0;
            return true;
        }
    }
    return false;
}

}  // namespace identity
}  // namespace security
}  // namespace android
