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

#ifndef KEYSTORE_KEYSTORE_H_
#define KEYSTORE_KEYSTORE_H_

#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include <keymasterV4_0/Keymaster.h>
#include <utils/Vector.h>

#include <keystore/keymaster_types.h>

#include "auth_token_table.h"
#include "blob.h"
#include "confirmation_manager.h"
#include "grant_store.h"
#include "keymaster_worker.h"
#include "keystore_keymaster_enforcement.h"
#include "operation.h"
#include "user_state.h"

#include <array>
#include <optional>
#include <tuple>

namespace keystore {

using ::android::sp;
using keymaster::support::Keymaster;

template <typename T, size_t count> class Devices : public std::array<T, count> {
  public:
    T& operator[](SecurityLevel secLevel) {
        static_assert(uint32_t(SecurityLevel::SOFTWARE) == 0 &&
                          uint32_t(SecurityLevel::TRUSTED_ENVIRONMENT) == 1 &&
                          uint32_t(SecurityLevel::STRONGBOX) == 2,
                      "Numeric values of security levels have changed");
        return std::array<T, count>::at(static_cast<uint32_t>(secLevel));
    }
    T operator[](SecurityLevel secLevel) const {
        if (static_cast<uint32_t>(secLevel) > static_cast<uint32_t>(SecurityLevel::STRONGBOX)) {
            LOG(ERROR) << "Invalid security level requested";
            return {};
        }
        return (*const_cast<Devices*>(this))[secLevel];
    }
};

}  // namespace keystore

namespace std {
template <typename T, size_t count> struct tuple_size<keystore::Devices<T, count>> {
  public:
    static constexpr size_t value = std::tuple_size<std::array<T, count>>::value;
};
}  // namespace std

namespace keystore {

using KeymasterWorkers = Devices<std::shared_ptr<KeymasterWorker>, 3>;
using KeymasterDevices = Devices<sp<Keymaster>, 3>;

class KeyStore : public ::android::IBinder::DeathRecipient {
  public:
    KeyStore(const KeymasterDevices& kmDevices,
             SecurityLevel minimalAllowedSecurityLevelForNewKeys);
    ~KeyStore();

    std::shared_ptr<KeymasterWorker> getDevice(SecurityLevel securityLevel) const {
        return mKmDevices[securityLevel];
    }

    std::shared_ptr<KeymasterWorker> getFallbackDevice() const {
        // we only return the fallback device if the creation of new fallback key blobs is
        // allowed. (also see getDevice below)
        if (mAllowNewFallback) {
            return mKmDevices[SecurityLevel::SOFTWARE];
        } else {
            return nullptr;
        }
    }

    std::shared_ptr<KeymasterWorker> getDevice(const Blob& blob) {
        return mKmDevices[blob.getSecurityLevel()];
    }

    ResponseCode initialize();

    State getState(uid_t userId) { return mUserStateDB.getUserState(userId)->getState(); }

    ResponseCode initializeUser(const android::String8& pw, uid_t userId);

    ResponseCode copyMasterKey(uid_t srcUser, uid_t dstUser);
    ResponseCode writeMasterKey(const android::String8& pw, uid_t userId);
    ResponseCode readMasterKey(const android::String8& pw, uid_t userId);

    LockedKeyBlobEntry getLockedBlobEntryIfNotExists(const std::string& alias, uid_t uid);
    std::optional<KeyBlobEntry> getBlobEntryIfExists(const std::string& alias, uid_t uid);
    LockedKeyBlobEntry getLockedBlobEntryIfExists(const std::string& alias, uid_t uid);
    /*
     * Delete entries owned by userId. If keepUnencryptedEntries is true
     * then only encrypted entries will be removed, otherwise all entries will
     * be removed.
     */
    void resetUser(uid_t userId, bool keepUnenryptedEntries);
    bool isEmpty(uid_t userId) const;

    void lock(uid_t userId);

    std::tuple<ResponseCode, Blob, Blob> get(const LockedKeyBlobEntry& blobfile);
    ResponseCode put(const LockedKeyBlobEntry& blobfile, Blob keyBlob, Blob characteristicsBlob);
    ResponseCode del(const LockedKeyBlobEntry& blobfile);

    std::string addGrant(const LockedKeyBlobEntry& blobfile, uid_t granteeUid);
    bool removeGrant(const LockedKeyBlobEntry& blobfile, const uid_t granteeUid);
    void removeAllGrantsToUid(const uid_t granteeUid);

    ResponseCode importKey(const uint8_t* key, size_t keyLen, const LockedKeyBlobEntry& blobfile,
                           uid_t userId, int32_t flags);

    bool isHardwareBacked(const android::String16& keyType) const;

    std::tuple<ResponseCode, Blob, Blob, LockedKeyBlobEntry>
    getKeyForName(const android::String8& keyName, const uid_t uid, const BlobType type);

    void binderDied(const ::android::wp<IBinder>& who) override;

    UserStateDB& getUserStateDB() { return mUserStateDB; }
    AuthTokenTable& getAuthTokenTable() { return mAuthTokenTable; }
    KeystoreKeymasterEnforcement& getEnforcementPolicy() { return mEnforcementPolicy; }
    ConfirmationManager& getConfirmationManager() { return *mConfirmationManager; }

  private:
    static const char* kOldMasterKey;
    static const char* kMetaDataFile;
    static const android::String16 kRsaKeyType;
    static const android::String16 kEcKeyType;

    KeymasterWorkers mKmDevices;

    bool mAllowNewFallback;

    UserStateDB mUserStateDB;
    AuthTokenTable mAuthTokenTable;
    KeystoreKeymasterEnforcement mEnforcementPolicy;
    sp<ConfirmationManager> mConfirmationManager;

    ::keystore::GrantStore mGrants;

    typedef struct { uint32_t version; } keystore_metadata_t;

    keystore_metadata_t mMetaData;

    /**
     * Upgrade the key from the current version to whatever is newest.
     */
    bool upgradeBlob(Blob* blob, const uint8_t oldVersion);

    void readMetaData();
    void writeMetaData();

    bool upgradeKeystore();
};

}  // namespace keystore

#endif  // KEYSTORE_KEYSTORE_H_
