/**
 *
 *    Copyright (c) 2023 Project CHIP Authors
 *
 *    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.
 */

#include "ICDMonitoringTable.h"

#include <crypto/RandUtils.h>

namespace chip {

enum class Fields : uint8_t
{
    kCheckInNodeID    = 1,
    kMonitoredSubject = 2,
    kAesKeyHandle     = 3,
    kHmacKeyHandle    = 4,
    kClientType       = 5,
};

CHIP_ERROR ICDMonitoringEntry::UpdateKey(StorageKeyName & skey)
{
    VerifyOrReturnError(kUndefinedFabricIndex != this->fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);
    skey = DefaultStorageKeyAllocator::ICDManagementTableEntry(this->fabricIndex, index);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ICDMonitoringEntry::Serialize(TLV::TLVWriter & writer) const
{
    TLV::TLVType outer;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
    ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kCheckInNodeID), checkInNodeID));
    ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kMonitoredSubject), monitoredSubject));

    ByteSpan aesKeybuf(aesKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>());
    ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kAesKeyHandle), aesKeybuf));

    ByteSpan hmacKeybuf(hmacKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>());
    ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kHmacKeyHandle), hmacKeybuf));

    ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kClientType), clientType));

    ReturnErrorOnFailure(writer.EndContainer(outer));
    return CHIP_NO_ERROR;
}

CHIP_ERROR ICDMonitoringEntry::Deserialize(TLV::TLVReader & reader)
{

    CHIP_ERROR err = CHIP_NO_ERROR;
    TLV::TLVType outer;

    ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
    VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE);
    ReturnErrorOnFailure(reader.EnterContainer(outer));
    while ((err = reader.Next()) == CHIP_NO_ERROR)
    {
        if (TLV::IsContextTag(reader.GetTag()))
        {
            switch (TLV::TagNumFromTag(reader.GetTag()))
            {
            case to_underlying(Fields::kCheckInNodeID):
                ReturnErrorOnFailure(reader.Get(checkInNodeID));
                break;
            case to_underlying(Fields::kMonitoredSubject):
                ReturnErrorOnFailure(reader.Get(monitoredSubject));
                break;
            case to_underlying(Fields::kAesKeyHandle): {
                ByteSpan buf;
                ReturnErrorOnFailure(reader.Get(buf));
                // Since we are storing either the raw key or a key ID, we must
                // simply copy the data as is in the keyHandle.
                // Calling SetKey here would create another keyHandle in storage and will cause
                // key leaks in some implementations.
                memcpy(aesKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), buf.data(),
                       sizeof(Crypto::Symmetric128BitsKeyByteArray));
                keyHandleValid = true;
            }
            break;
            case to_underlying(Fields::kHmacKeyHandle): {
                ByteSpan buf;
                CHIP_ERROR error = reader.Get(buf);

                if (error != CHIP_NO_ERROR)
                {
                    // If retreiving the hmac key handle failed, we need to set an invalid key handle
                    // even if the AesKeyHandle is valid.
                    keyHandleValid = false;
                    return error;
                }

                // Since we are storing either the raw key or a key ID, we must
                // simply copy the data as is in the keyHandle.
                // Calling SetKey here would create another keyHandle in storage and will cause
                // key leaks in some implementations.
                memcpy(hmacKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(), buf.data(),
                       sizeof(Crypto::Symmetric128BitsKeyByteArray));
            }
            break;
            case to_underlying(Fields::kClientType):
                ReturnErrorOnFailure(reader.Get(clientType));
                break;
            default:
                break;
            }
        }
    }

    VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
    ReturnErrorOnFailure(reader.ExitContainer(outer));
    return CHIP_NO_ERROR;
}

void ICDMonitoringEntry::Clear()
{
    this->checkInNodeID    = kUndefinedNodeId;
    this->monitoredSubject = kUndefinedNodeId;
    this->keyHandleValid   = false;
    this->clientType       = app::Clusters::IcdManagement::ClientTypeEnum::kPermanent;
}

CHIP_ERROR ICDMonitoringEntry::SetKey(ByteSpan keyData)
{
    VerifyOrReturnError(keyData.size() == sizeof(Crypto::Symmetric128BitsKeyByteArray), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(symmetricKeystore != nullptr, CHIP_ERROR_INTERNAL);
    VerifyOrReturnError(!keyHandleValid, CHIP_ERROR_INTERNAL);

    Crypto::Symmetric128BitsKeyByteArray keyMaterial;
    memcpy(keyMaterial, keyData.data(), sizeof(Crypto::Symmetric128BitsKeyByteArray));

    // TODO - Add function to set PSA key lifetime
    ReturnErrorOnFailure(symmetricKeystore->CreateKey(keyMaterial, aesKeyHandle));
    CHIP_ERROR error = symmetricKeystore->CreateKey(keyMaterial, hmacKeyHandle);

    if (error == CHIP_NO_ERROR)
    {
        // If the creation of the HmacKeyHandle succeeds, both key handles are valid
        keyHandleValid = true;
    }
    else
    {
        // Creation of the HmacKeyHandle failed, we need to delete the AesKeyHandle to avoid a key leak
        symmetricKeystore->DestroyKey(this->aesKeyHandle);
    }

    return error;
}

CHIP_ERROR ICDMonitoringEntry::DeleteKey()
{
    VerifyOrReturnError(symmetricKeystore != nullptr, CHIP_ERROR_INTERNAL);
    symmetricKeystore->DestroyKey(this->aesKeyHandle);
    symmetricKeystore->DestroyKey(this->hmacKeyHandle);
    keyHandleValid = false;
    return CHIP_NO_ERROR;
}

bool ICDMonitoringEntry::IsKeyEquivalent(ByteSpan keyData)
{
    VerifyOrReturnValue(keyData.size() == Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES, false);
    VerifyOrReturnValue(symmetricKeystore != nullptr, false);
    VerifyOrReturnValue(keyHandleValid, false);

    ICDMonitoringEntry tempEntry(symmetricKeystore);

    VerifyOrReturnValue(tempEntry.SetKey(keyData) == CHIP_NO_ERROR, false);

    // Challenge
    uint8_t mic[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES]  = { 0 };
    uint8_t aead[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES] = { 0 };

    CHIP_ERROR err;

    uint64_t data = Crypto::GetRandU64(), validation, encrypted;
    validation    = data;

    err = Crypto::AES_CCM_encrypt(reinterpret_cast<uint8_t *>(&data), sizeof(data), nullptr, 0, tempEntry.aesKeyHandle, aead,
                                  Crypto::CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES, reinterpret_cast<uint8_t *>(&encrypted), mic,
                                  Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES);

    data = 0;
    if (err == CHIP_NO_ERROR)
    {
        err = Crypto::AES_CCM_decrypt(reinterpret_cast<uint8_t *>(&encrypted), sizeof(encrypted), nullptr, 0, mic,
                                      Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, aesKeyHandle, aead,
                                      Crypto::CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES, reinterpret_cast<uint8_t *>(&data));
    }
    tempEntry.DeleteKey();

    if (err != CHIP_NO_ERROR)
    {
        return false;
    }

    return (data == validation) ? true : false;
}

ICDMonitoringEntry & ICDMonitoringEntry::operator=(const ICDMonitoringEntry & icdMonitoringEntry)
{
    if (this == &icdMonitoringEntry)
    {
        return *this;
    }

    fabricIndex       = icdMonitoringEntry.fabricIndex;
    checkInNodeID     = icdMonitoringEntry.checkInNodeID;
    monitoredSubject  = icdMonitoringEntry.monitoredSubject;
    clientType        = icdMonitoringEntry.clientType;
    index             = icdMonitoringEntry.index;
    keyHandleValid    = icdMonitoringEntry.keyHandleValid;
    symmetricKeystore = icdMonitoringEntry.symmetricKeystore;
    memcpy(aesKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(),
           icdMonitoringEntry.aesKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>(),
           sizeof(Crypto::Symmetric128BitsKeyByteArray));
    memcpy(hmacKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(),
           icdMonitoringEntry.hmacKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>(),
           sizeof(Crypto::Symmetric128BitsKeyByteArray));

    return *this;
}

CHIP_ERROR ICDMonitoringTable::Get(uint16_t index, ICDMonitoringEntry & entry) const
{
    entry.fabricIndex = this->mFabric;
    entry.index       = index;
    ReturnErrorOnFailure(entry.Load(this->mStorage));
    entry.fabricIndex = this->mFabric;
    return CHIP_NO_ERROR;
}

CHIP_ERROR ICDMonitoringTable::Find(NodeId id, ICDMonitoringEntry & entry)
{
    uint16_t index = 0;
    while (index < this->Limit())
    {
        ReturnErrorOnFailure(this->Get(index++, entry));
        if (id == entry.checkInNodeID)
        {
            return CHIP_NO_ERROR;
        }
    }
    entry.index = index;
    return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR ICDMonitoringTable::Set(uint16_t index, const ICDMonitoringEntry & entry)
{
    VerifyOrReturnError(index < this->Limit(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(kUndefinedNodeId != entry.checkInNodeID, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(kUndefinedNodeId != entry.monitoredSubject, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(entry.keyHandleValid, CHIP_ERROR_INVALID_ARGUMENT);

    ICDMonitoringEntry e(this->mFabric, index);
    e.checkInNodeID    = entry.checkInNodeID;
    e.monitoredSubject = entry.monitoredSubject;
    e.clientType       = entry.clientType;
    e.index            = index;

    memcpy(e.aesKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(),
           entry.aesKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>(), sizeof(Crypto::Symmetric128BitsKeyByteArray));
    memcpy(e.hmacKeyHandle.AsMutable<Crypto::Symmetric128BitsKeyByteArray>(),
           entry.hmacKeyHandle.As<Crypto::Symmetric128BitsKeyByteArray>(), sizeof(Crypto::Symmetric128BitsKeyByteArray));

    return e.Save(this->mStorage);
}

CHIP_ERROR ICDMonitoringTable::Remove(uint16_t index)
{
    ICDMonitoringEntry entry(mSymmetricKeystore, this->mFabric);

    // Retrieve entry and delete the keyHandle first as to not
    // cause any key leaks.
    this->Get(index, entry);
    ReturnErrorOnFailure(entry.DeleteKey());

    // Shift remaining entries down one position
    while (CHIP_NO_ERROR == this->Get(static_cast<uint16_t>(index + 1), entry))
    {
        ReturnErrorOnFailure(this->Set(index++, entry));
    }

    // Remove last entry
    entry.fabricIndex = this->mFabric;
    entry.index       = index;

    // entry.Delete() doesn't delete the key from the AES128KeyHandle
    return entry.Delete(this->mStorage);
}

CHIP_ERROR ICDMonitoringTable::RemoveAll()
{
    ICDMonitoringEntry entry(mSymmetricKeystore, this->mFabric);
    uint16_t index = 0;
    while (index < this->Limit())
    {
        CHIP_ERROR err = this->Get(index++, entry);
        if (CHIP_ERROR_NOT_FOUND == err)
        {
            break;
        }
        ReturnErrorOnFailure(err);
        entry.fabricIndex = this->mFabric;
        ReturnErrorOnFailure(entry.DeleteKey());
        ReturnErrorOnFailure(entry.Delete(this->mStorage));
    }
    return CHIP_NO_ERROR;
}

bool ICDMonitoringTable::IsEmpty()
{
    ICDMonitoringEntry entry(mSymmetricKeystore, this->mFabric);
    return (this->Get(0, entry) == CHIP_ERROR_NOT_FOUND);
}

uint16_t ICDMonitoringTable::Limit() const
{
    return mLimit;
}

} // namespace chip
