/*
 *    Copyright (c) 2022 Project CHIP Authors
 *    All rights reserved.
 *
 *    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.
 */

/**
 *    @file
 *      This file defines the CHIP CASE Session object that provides
 *      APIs for constructing a secure session using a certificate from the device's
 *      operational credentials.
 */

#include <protocols/secure_channel/SimpleSessionResumptionStorage.h>

#include <lib/support/Base64.h>
#include <lib/support/SafeInt.h>

namespace chip {

constexpr TLV::Tag SimpleSessionResumptionStorage::kFabricIndexTag;
constexpr TLV::Tag SimpleSessionResumptionStorage::kPeerNodeIdTag;
constexpr TLV::Tag SimpleSessionResumptionStorage::kResumptionIdTag;
constexpr TLV::Tag SimpleSessionResumptionStorage::kSharedSecretTag;
constexpr TLV::Tag SimpleSessionResumptionStorage::kCATTag;

const char * SimpleSessionResumptionStorage::StorageKey(DefaultStorageKeyAllocator & keyAlloc, const ScopedNodeId & node)
{
    return keyAlloc.FabricSession(node.GetFabricIndex(), node.GetNodeId());
}

const char * SimpleSessionResumptionStorage::StorageKey(DefaultStorageKeyAllocator & keyAlloc, ConstResumptionIdView resumptionId)
{
    char resumptionIdBase64[BASE64_ENCODED_LEN(resumptionId.size()) + 1];
    auto len                = Base64Encode(resumptionId.data(), resumptionId.size(), resumptionIdBase64);
    resumptionIdBase64[len] = '\0';
    return keyAlloc.SessionResumption(resumptionIdBase64);
}

CHIP_ERROR SimpleSessionResumptionStorage::SaveIndex(const SessionIndex & index)
{
    std::array<uint8_t, MaxIndexSize()> buf;
    TLV::TLVWriter writer;
    writer.Init(buf);

    TLV::TLVType arrayType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Array, arrayType));

    for (size_t i = 0; i < index.mSize; ++i)
    {
        TLV::TLVType innerType;
        ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, innerType));
        ReturnErrorOnFailure(writer.Put(kFabricIndexTag, index.mNodes[i].GetFabricIndex()));
        ReturnErrorOnFailure(writer.Put(kPeerNodeIdTag, index.mNodes[i].GetNodeId()));
        ReturnErrorOnFailure(writer.EndContainer(innerType));
    }

    ReturnErrorOnFailure(writer.EndContainer(arrayType));

    const auto len = writer.GetLengthWritten();
    VerifyOrReturnError(CanCastTo<uint16_t>(len), CHIP_ERROR_BUFFER_TOO_SMALL);

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(keyAlloc.SessionResumptionIndex(), buf.data(), static_cast<uint16_t>(len)));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::LoadIndex(SessionIndex & index)
{
    std::array<uint8_t, MaxIndexSize()> buf;
    uint16_t len = static_cast<uint16_t>(buf.size());

    DefaultStorageKeyAllocator keyAlloc;
    if (mStorage->SyncGetKeyValue(keyAlloc.SessionResumptionIndex(), buf.data(), len) != CHIP_NO_ERROR)
    {
        index.mSize = 0;
        return CHIP_NO_ERROR;
    }

    TLV::ContiguousBufferTLVReader reader;
    reader.Init(buf.data(), len);

    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
    TLV::TLVType arrayType;
    ReturnErrorOnFailure(reader.EnterContainer(arrayType));

    size_t count = 0;
    CHIP_ERROR err;
    while ((err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag())) == CHIP_NO_ERROR)
    {
        if (count >= ArraySize(index.mNodes))
        {
            return CHIP_ERROR_NO_MEMORY;
        }

        TLV::TLVType containerType;
        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        FabricIndex fabricIndex;
        ReturnErrorOnFailure(reader.Next(kFabricIndexTag));
        ReturnErrorOnFailure(reader.Get(fabricIndex));

        NodeId peerNodeId;
        ReturnErrorOnFailure(reader.Next(kPeerNodeIdTag));
        ReturnErrorOnFailure(reader.Get(peerNodeId));

        index.mNodes[count++] = ScopedNodeId(peerNodeId, fabricIndex);

        ReturnErrorOnFailure(reader.ExitContainer(containerType));
    }

    if (err != CHIP_END_OF_TLV)
    {
        return err;
    }

    ReturnErrorOnFailure(reader.ExitContainer(arrayType));
    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    index.mSize = count;

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::SaveLink(ConstResumptionIdView resumptionId, const ScopedNodeId & node)
{
    // Save a link from resumptionId to node, in key: /g/s/<resumptionId>
    std::array<uint8_t, MaxScopedNodeIdSize()> buf;
    TLV::TLVWriter writer;
    writer.Init(buf);

    TLV::TLVType outerType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));
    ReturnErrorOnFailure(writer.Put(kFabricIndexTag, node.GetFabricIndex()));
    ReturnErrorOnFailure(writer.Put(kPeerNodeIdTag, node.GetNodeId()));
    ReturnErrorOnFailure(writer.EndContainer(outerType));

    const auto len = writer.GetLengthWritten();
    VerifyOrDie(CanCastTo<uint16_t>(len));

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(StorageKey(keyAlloc, resumptionId), buf.data(), static_cast<uint16_t>(len)));
    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::LoadLink(ConstResumptionIdView resumptionId, ScopedNodeId & node)
{
    std::array<uint8_t, MaxScopedNodeIdSize()> buf;
    uint16_t len = static_cast<uint16_t>(buf.size());

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncGetKeyValue(StorageKey(keyAlloc, resumptionId), buf.data(), len));

    TLV::ContiguousBufferTLVReader reader;
    reader.Init(buf.data(), len);

    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
    TLV::TLVType containerType;
    ReturnErrorOnFailure(reader.EnterContainer(containerType));

    FabricIndex fabricIndex;
    ReturnErrorOnFailure(reader.Next(kFabricIndexTag));
    ReturnErrorOnFailure(reader.Get(fabricIndex));

    NodeId peerNodeId;
    ReturnErrorOnFailure(reader.Next(kPeerNodeIdTag));
    ReturnErrorOnFailure(reader.Get(peerNodeId));

    ReturnErrorOnFailure(reader.ExitContainer(containerType));
    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    node = ScopedNodeId(peerNodeId, fabricIndex);

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::DeleteLink(ConstResumptionIdView resumptionId)
{
    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncDeleteKeyValue(StorageKey(keyAlloc, resumptionId)));
    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::SaveState(const ScopedNodeId & node, ConstResumptionIdView resumptionId,
                                                     const Crypto::P256ECDHDerivedSecret & sharedSecret, const CATValues & peerCATs)
{
    // Save session state into key: /f/<fabricIndex>/s/<nodeId>
    std::array<uint8_t, MaxStateSize()> buf;
    TLV::TLVWriter writer;
    writer.Init(buf);

    TLV::TLVType outerType;
    ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType));

    ReturnErrorOnFailure(writer.Put(kResumptionIdTag, resumptionId));

    ReturnErrorOnFailure(writer.Put(kSharedSecretTag, ByteSpan(sharedSecret.ConstBytes(), sharedSecret.Length())));

    CATValues::Serialized cat;
    peerCATs.Serialize(cat);
    ReturnErrorOnFailure(writer.Put(kCATTag, ByteSpan(cat)));

    ReturnErrorOnFailure(writer.EndContainer(outerType));

    const auto len = writer.GetLengthWritten();
    VerifyOrDie(CanCastTo<uint16_t>(len));

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncSetKeyValue(StorageKey(keyAlloc, node), buf.data(), static_cast<uint16_t>(len)));
    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::LoadState(const ScopedNodeId & node, ResumptionIdStorage & resumptionId,
                                                     Crypto::P256ECDHDerivedSecret & sharedSecret, CATValues & peerCATs)
{
    std::array<uint8_t, MaxStateSize()> buf;
    uint16_t len = static_cast<uint16_t>(buf.size());

    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncGetKeyValue(StorageKey(keyAlloc, node), buf.data(), len));

    TLV::ContiguousBufferTLVReader reader;
    reader.Init(buf.data(), len);

    ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
    TLV::TLVType containerType;
    ReturnErrorOnFailure(reader.EnterContainer(containerType));

    ByteSpan resumptionIdSpan;
    ReturnErrorOnFailure(reader.Next(kResumptionIdTag));
    ReturnErrorOnFailure(reader.Get(resumptionIdSpan));
    VerifyOrReturnError(resumptionIdSpan.size() == resumptionId.size(), CHIP_ERROR_KEY_NOT_FOUND);
    std::copy(resumptionIdSpan.begin(), resumptionIdSpan.end(), resumptionId.begin());

    ByteSpan sharedSecretSpan;
    ReturnErrorOnFailure(reader.Next(kSharedSecretTag));
    ReturnErrorOnFailure(reader.Get(sharedSecretSpan));
    VerifyOrReturnError(sharedSecretSpan.size() <= sharedSecret.Capacity(), CHIP_ERROR_BUFFER_TOO_SMALL);
    ::memcpy(sharedSecret.Bytes(), sharedSecretSpan.data(), sharedSecretSpan.size());
    sharedSecret.SetLength(sharedSecretSpan.size());

    ByteSpan catSpan;
    ReturnErrorOnFailure(reader.Next(kCATTag));
    ReturnErrorOnFailure(reader.Get(catSpan));
    CATValues::Serialized cat;
    VerifyOrReturnError(sizeof(cat) == catSpan.size(), CHIP_ERROR_INVALID_TLV_ELEMENT);
    ::memcpy(cat, catSpan.data(), catSpan.size());
    peerCATs.Deserialize(cat);

    ReturnErrorOnFailure(reader.ExitContainer(containerType));
    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    return CHIP_NO_ERROR;
}

CHIP_ERROR SimpleSessionResumptionStorage::DeleteState(const ScopedNodeId & node)
{
    DefaultStorageKeyAllocator keyAlloc;
    ReturnErrorOnFailure(mStorage->SyncDeleteKeyValue(StorageKey(keyAlloc, node)));
    return CHIP_NO_ERROR;
}

} // namespace chip
