/*
 *
 *    Copyright (c) 2021 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.
 */

/**
 *    @file
 *      This file implements the CHIP message counter messages in secure channel protocol.
 *
 */

#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/core/CHIPKeyIds.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/Flags.h>
#include <protocols/Protocols.h>
#include <protocols/secure_channel/Constants.h>
#include <protocols/secure_channel/MessageCounterManager.h>

namespace chip {
namespace secure_channel {

constexpr System::Clock::Timeout MessageCounterManager::kSyncTimeout;

CHIP_ERROR MessageCounterManager::Init(Messaging::ExchangeManager * exchangeMgr)
{
    VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE);
    mExchangeMgr = exchangeMgr;

    ReturnErrorOnFailure(
        mExchangeMgr->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq, this));

    return CHIP_NO_ERROR;
}

void MessageCounterManager::Shutdown()
{
    if (mExchangeMgr != nullptr)
    {
        mExchangeMgr->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq);
        mExchangeMgr->CloseAllContextsForDelegate(this);
        mExchangeMgr = nullptr;
    }
}

CHIP_ERROR MessageCounterManager::StartSync(const SessionHandle & session, Transport::SecureSession * state)
{
    // Initiate message counter synchronization if no message counter synchronization is in progress.
    Transport::PeerMessageCounter & counter = state->GetSessionMessageCounter().GetPeerMessageCounter();
    if (!counter.IsSynchronizing() && !counter.IsSynchronized())
    {
        ReturnErrorOnFailure(SendMsgCounterSyncReq(session, state));
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR MessageCounterManager::QueueReceivedMessageAndStartSync(const PacketHeader & packetHeader, const SessionHandle & session,
                                                                   Transport::SecureSession * state,
                                                                   const Transport::PeerAddress & peerAddress,
                                                                   System::PacketBufferHandle && msgBuf)
{
    // Queue the message to be reprocessed when sync completes.
    ReturnErrorOnFailure(AddToReceiveTable(packetHeader, peerAddress, std::move(msgBuf)));
    ReturnErrorOnFailure(StartSync(session, state));

    // After the message that triggers message counter synchronization is stored, and a message counter
    // synchronization exchange is initiated, we need to return immediately and re-process the original message
    // when the synchronization is completed.

    return CHIP_NO_ERROR;
}

CHIP_ERROR MessageCounterManager::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
{
    // MessageCounterManager do not use an extra context to handle messages
    newDelegate = this;
    return CHIP_NO_ERROR;
}

CHIP_ERROR MessageCounterManager::OnMessageReceived(Messaging::ExchangeContext * exchangeContext,
                                                    const PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf)
{
    if (payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq))
    {
        return HandleMsgCounterSyncReq(exchangeContext, std::move(msgBuf));
    }
    if (payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncRsp))
    {
        return HandleMsgCounterSyncResp(exchangeContext, std::move(msgBuf));
    }
    return CHIP_NO_ERROR;
}

void MessageCounterManager::OnResponseTimeout(Messaging::ExchangeContext * exchangeContext)
{
    if (exchangeContext->HasSessionHandle())
    {
        exchangeContext->GetSessionHandle()->AsSecureSession()->GetSessionMessageCounter().GetPeerMessageCounter().SyncFailed();
    }
    else
    {
        ChipLogError(SecureChannel, "MCSP Timeout! On a already released session.");
    }
}

CHIP_ERROR MessageCounterManager::AddToReceiveTable(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
                                                    System::PacketBufferHandle && msgBuf)
{
    ReturnErrorOnFailure(packetHeader.EncodeBeforeData(msgBuf));

    for (ReceiveTableEntry & entry : mReceiveTable)
    {
        if (entry.msgBuf.IsNull())
        {
            entry.peerAddress = peerAddress;
            entry.msgBuf      = std::move(msgBuf);

            return CHIP_NO_ERROR;
        }
    }

    ChipLogError(SecureChannel, "MCSP ReceiveTable Already Full");
    return CHIP_ERROR_NO_MEMORY;
}

/**
 *  Reprocess all pending messages that were encrypted with application
 *  group key and were addressed to the specified node id.
 *
 *  @param[in] peerNodeId    Node ID of the destination node.
 *
 */
void MessageCounterManager::ProcessPendingMessages(NodeId peerNodeId)
{
    auto * sessionManager = mExchangeMgr->GetSessionManager();

    // Find all receive entries matching peerNodeId.  Note that everything in
    // this table was using an application group key; that's why it was added.
    for (ReceiveTableEntry & entry : mReceiveTable)
    {
        if (!entry.msgBuf.IsNull())
        {
            PacketHeader packetHeader;
            uint16_t headerSize = 0;

            if (packetHeader.Decode((entry.msgBuf)->Start(), (entry.msgBuf)->DataLength(), &headerSize) != CHIP_NO_ERROR)
            {
                ChipLogError(SecureChannel, "MessageCounterManager::ProcessPendingMessages: Failed to decode PacketHeader");
                entry.msgBuf = nullptr;
                continue;
            }

            if (packetHeader.GetSourceNodeId().HasValue() && packetHeader.GetSourceNodeId().Value() == peerNodeId)
            {
                // Reprocess message.
                sessionManager->OnMessageReceived(entry.peerAddress, std::move(entry.msgBuf));

                // Explicitly free any buffer owned by this handle.
                entry.msgBuf = nullptr;
            }
        }
    }
}

CHIP_ERROR MessageCounterManager::SendMsgCounterSyncReq(const SessionHandle & session, Transport::SecureSession * state)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    Messaging::ExchangeContext * exchangeContext = nullptr;
    System::PacketBufferHandle msgBuf;
    Messaging::SendFlags sendFlags;

    exchangeContext = mExchangeMgr->NewContext(session, this);
    VerifyOrExit(exchangeContext != nullptr, err = CHIP_ERROR_NO_MEMORY);

    msgBuf = MessagePacketBuffer::New(kChallengeSize);
    VerifyOrExit(!msgBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);

    // Generate a 64-bit random number to uniquely identify the request.
    SuccessOrExit(err = Crypto::DRBG_get_bytes(msgBuf->Start(), kChallengeSize));

    msgBuf->SetDataLength(kChallengeSize);

    // Store generated Challenge value to message counter context to resolve synchronization response.
    state->GetSessionMessageCounter().GetPeerMessageCounter().SyncStarting(FixedByteSpan<kChallengeSize>(msgBuf->Start()));

    sendFlags.Set(Messaging::SendMessageFlags::kNoAutoRequestAck).Set(Messaging::SendMessageFlags::kExpectResponse);

    // Arm a timer to enforce that a MsgCounterSyncRsp is received before kSyncTimeout.
    exchangeContext->SetResponseTimeout(kSyncTimeout);

    // Send the message counter synchronization request in a Secure Channel Protocol::MsgCounterSyncReq message.
    SuccessOrExit(
        err = exchangeContext->SendMessage(Protocols::SecureChannel::MsgType::MsgCounterSyncReq, std::move(msgBuf), sendFlags));

exit:
    if (err != CHIP_NO_ERROR)
    {
        if (exchangeContext != nullptr)
        {
            exchangeContext->Close();
        }
        state->GetSessionMessageCounter().GetPeerMessageCounter().SyncFailed();
        ChipLogError(SecureChannel, "Failed to send message counter synchronization request with error:%" CHIP_ERROR_FORMAT,
                     err.Format());
    }

    return err;
}

CHIP_ERROR MessageCounterManager::SendMsgCounterSyncResp(Messaging::ExchangeContext * exchangeContext,
                                                         FixedByteSpan<kChallengeSize> challenge)
{
    System::PacketBufferHandle msgBuf;
    VerifyOrDie(exchangeContext->HasSessionHandle());

    VerifyOrReturnError(exchangeContext->GetSessionHandle()->IsGroupSession(), CHIP_ERROR_INVALID_ARGUMENT);

    // NOTE: not currently implemented. When implementing, the following should be done:
    //    - allocate a new buffer: MessagePacketBuffer::New
    //    - setup payload and place the local message counter + challange in it
    //    - exchangeContext->SendMessage(Protocols::SecureChannel::MsgType::MsgCounterSyncRsp, ...)
    //
    // You can view the history of this file for a partial implementation that got
    // removed due to it using non-group sessions.

    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR MessageCounterManager::HandleMsgCounterSyncReq(Messaging::ExchangeContext * exchangeContext,
                                                          System::PacketBufferHandle && msgBuf)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    uint8_t * req = msgBuf->Start();
    size_t reqlen = msgBuf->DataLength();

    ChipLogDetail(SecureChannel, "Received MsgCounterSyncReq request");

    VerifyOrExit(req != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
    VerifyOrExit(reqlen == kChallengeSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

    // Respond with MsgCounterSyncResp
    err = SendMsgCounterSyncResp(exchangeContext, FixedByteSpan<kChallengeSize>(req));

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SecureChannel, "Failed to handle MsgCounterSyncReq message with error:%" CHIP_ERROR_FORMAT, err.Format());
    }

    return err;
}

CHIP_ERROR MessageCounterManager::HandleMsgCounterSyncResp(Messaging::ExchangeContext * exchangeContext,
                                                           System::PacketBufferHandle && msgBuf)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    uint32_t syncCounter = 0;

    const uint8_t * resp = msgBuf->Start();
    size_t resplen       = msgBuf->DataLength();

    ChipLogDetail(SecureChannel, "Received MsgCounterSyncResp response");

    VerifyOrDie(exchangeContext->HasSessionHandle());

    VerifyOrExit(msgBuf->DataLength() == kSyncRespMsgSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

    VerifyOrExit(resp != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
    VerifyOrExit(resplen == kSyncRespMsgSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);

    syncCounter = chip::Encoding::LittleEndian::Read32(resp);
    VerifyOrExit(syncCounter != 0, err = CHIP_ERROR_READ_FAILED);

    // Verify that the response field matches the expected Challenge field for the exchange.
    err =
        exchangeContext->GetSessionHandle()->AsSecureSession()->GetSessionMessageCounter().GetPeerMessageCounter().VerifyChallenge(
            syncCounter, FixedByteSpan<kChallengeSize>(resp));
    SuccessOrExit(err);

    // Process all queued incoming messages after message counter synchronization is completed.
    ProcessPendingMessages(exchangeContext->GetSessionHandle()->AsSecureSession()->GetPeerNodeId());

exit:
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(SecureChannel, "Failed to handle MsgCounterSyncResp message with error:%" CHIP_ERROR_FORMAT, err.Format());
    }

    return err;
}

} // namespace secure_channel
} // namespace chip
