/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    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 implements the CHIP Connection object that maintains a UDP connection.
 *      TODO This class should be extended to support TCP as well...
 *
 */

#include "SessionManager.h"

#include <inttypes.h>
#include <string.h>

#include "transport/TraceMessage.h"
#include <app/util/basic-types.h>
#include <credentials/GroupDataProvider.h>
#include <inttypes.h>
#include <lib/core/CHIPKeyIds.h>
#include <lib/core/Global.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <protocols/Protocols.h>
#include <protocols/secure_channel/Constants.h>
#include <tracing/macros.h>
#include <transport/GroupPeerMessageCounter.h>
#include <transport/GroupSession.h>
#include <transport/SecureMessageCodec.h>
#include <transport/TracingStructs.h>
#include <transport/TransportMgr.h>

namespace chip {

using System::PacketBufferHandle;
using Transport::GroupPeerTable;
using Transport::PeerAddress;
using Transport::SecureSession;

namespace {
Global<GroupPeerTable> gGroupPeerTable;

// Helper function that strips off the interface ID from a peer address that is
// not an IPv6 link-local address.  For any other address type we should rely on
// the device's routing table to route messages sent.  Forcing messages down a
// specific interface might fail with "no route to host".
void CorrectPeerAddressInterfaceID(Transport::PeerAddress & peerAddress)
{
    if (peerAddress.GetIPAddress().IsIPv6LinkLocal())
    {
        return;
    }
    peerAddress.SetInterface(Inet::InterfaceId::Null());
}

} // namespace

uint32_t EncryptedPacketBufferHandle::GetMessageCounter() const
{
    PacketHeader header;
    uint16_t headerSize = 0;
    CHIP_ERROR err      = header.Decode((*this)->Start(), (*this)->DataLength(), &headerSize);

    if (err == CHIP_NO_ERROR)
    {
        return header.GetMessageCounter();
    }

    ChipLogError(Inet, "Failed to decode EncryptedPacketBufferHandle header with error: %" CHIP_ERROR_FORMAT, err.Format());

    return 0;
}

SessionManager::SessionManager() : mState(State::kNotReady) {}

SessionManager::~SessionManager()
{
    this->Shutdown();
}

CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
                                Transport::MessageCounterManagerInterface * messageCounterManager,
                                chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
                                Crypto::SessionKeystore & sessionKeystore)
{
    VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(storageDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorOnFailure(fabricTable->AddFabricDelegate(this));

    mState                 = State::kInitialized;
    mSystemLayer           = systemLayer;
    mTransportMgr          = transportMgr;
    mMessageCounterManager = messageCounterManager;
    mFabricTable           = fabricTable;
    mSessionKeystore       = &sessionKeystore;

    mSecureSessions.Init();

    mGlobalUnencryptedMessageCounter.Init();

    ReturnErrorOnFailure(mGroupClientCounter.Init(storageDelegate));

    mTransportMgr->SetSessionManager(this);

    return CHIP_NO_ERROR;
}

void SessionManager::Shutdown()
{
    if (mFabricTable != nullptr)
    {
        mFabricTable->RemoveFabricDelegate(this);
        mFabricTable = nullptr;
    }

    // Ensure that we don't create new sessions as we iterate our session table.
    mState = State::kNotReady;

    mSecureSessions.ForEachSession([&](auto session) {
        session->MarkForEviction();
        return Loop::Continue;
    });

    mMessageCounterManager = nullptr;

    mSystemLayer  = nullptr;
    mTransportMgr = nullptr;
    mCB           = nullptr;
}

/**
 * @brief Notification that a fabric was removed.
 *        This function doesn't call ExpireAllSessionsForFabric
 *        since the CASE session might still be open to send a response
 *        on the removed fabric.
 */
void SessionManager::FabricRemoved(FabricIndex fabricIndex)
{
    gGroupPeerTable->FabricRemoved(fabricIndex);
}

CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
                                          System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
{
    MATTER_TRACE_SCOPE("PrepareMessage", "SessionManager");

    PacketHeader packetHeader;
    bool isControlMsg = IsControlMessage(payloadHeader);
    if (isControlMsg)
    {
        packetHeader.SetSecureSessionControlMsg(true);
    }

#if CHIP_PROGRESS_LOGGING
    NodeId destination;
    FabricIndex fabricIndex;
#endif // CHIP_PROGRESS_LOGGING

    PeerAddress destination_address;

    switch (sessionHandle->GetSessionType())
    {
    case Transport::Session::SessionType::kGroupOutgoing: {
        auto groupSession = sessionHandle->AsOutgoingGroupSession();
        auto * groups     = Credentials::GetGroupDataProvider();
        VerifyOrReturnError(nullptr != groups, CHIP_ERROR_INTERNAL);

        const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
        VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

        packetHeader.SetDestinationGroupId(groupSession->GetGroupId());
        packetHeader.SetMessageCounter(mGroupClientCounter.GetCounter(isControlMsg));
        mGroupClientCounter.IncrementCounter(isControlMsg);
        packetHeader.SetSessionType(Header::SessionType::kGroupSession);
        NodeId sourceNodeId = fabric->GetNodeId();
        packetHeader.SetSourceNodeId(sourceNodeId);

        if (!packetHeader.IsValidGroupMsg())
        {
            return CHIP_ERROR_INTERNAL;
        }

        destination_address = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());

        // Trace before any encryption
        MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kGroupMessage, &payloadHeader, &packetHeader,
                                chip::ByteSpan(message->Start(), message->TotalLength()));

        CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());

        Crypto::SymmetricKeyContext * keyContext =
            groups->GetKeyContext(groupSession->GetFabricIndex(), groupSession->GetGroupId());
        VerifyOrReturnError(nullptr != keyContext, CHIP_ERROR_INTERNAL);

        packetHeader.SetSessionId(keyContext->GetKeyHash());
        CryptoContext::NonceStorage nonce;
        CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), sourceNodeId);
        CHIP_ERROR err = SecureMessageCodec::Encrypt(CryptoContext(keyContext), nonce, payloadHeader, packetHeader, message);
        keyContext->Release();
        ReturnErrorOnFailure(err);

#if CHIP_PROGRESS_LOGGING
        destination = NodeIdFromGroupId(groupSession->GetGroupId());
        fabricIndex = groupSession->GetFabricIndex();
#endif // CHIP_PROGRESS_LOGGING
    }
    break;
    case Transport::Session::SessionType::kSecure: {
        SecureSession * session = sessionHandle->AsSecureSession();
        if (session == nullptr)
        {
            return CHIP_ERROR_NOT_CONNECTED;
        }

        MessageCounter & counter = session->GetSessionMessageCounter().GetLocalMessageCounter();
        uint32_t messageCounter;
        ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
        packetHeader
            .SetMessageCounter(messageCounter)         //
            .SetSessionId(session->GetPeerSessionId()) //
            .SetSessionType(Header::SessionType::kUnicastSession);

        destination_address = session->GetPeerAddress();

        // Trace before any encryption
        MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kSecureSession, &payloadHeader, &packetHeader,
                                chip::ByteSpan(message->Start(), message->TotalLength()));
        CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());

        CryptoContext::NonceStorage nonce;
        NodeId sourceNodeId = session->GetLocalScopedNodeId().GetNodeId();
        CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, sourceNodeId);

        ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), nonce, payloadHeader, packetHeader, message));

#if CHIP_PROGRESS_LOGGING
        destination = session->GetPeerNodeId();
        fabricIndex = session->GetFabricIndex();
#endif // CHIP_PROGRESS_LOGGING
    }
    break;
    case Transport::Session::SessionType::kUnauthenticated: {
        MessageCounter & counter = mGlobalUnencryptedMessageCounter;
        uint32_t messageCounter;
        ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
        packetHeader.SetMessageCounter(messageCounter);
        Transport::UnauthenticatedSession * session = sessionHandle->AsUnauthenticatedSession();
        switch (session->GetSessionRole())
        {
        case Transport::UnauthenticatedSession::SessionRole::kInitiator:
            packetHeader.SetSourceNodeId(session->GetEphemeralInitiatorNodeID());
            break;
        case Transport::UnauthenticatedSession::SessionRole::kResponder:
            packetHeader.SetDestinationNodeId(session->GetEphemeralInitiatorNodeID());
            break;
        }

        auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
        destination_address  = unauthenticated->GetPeerAddress();

        // Trace after all headers are settled.
        MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
                                chip::ByteSpan(message->Start(), message->TotalLength()));
        CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());

        ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));

#if CHIP_PROGRESS_LOGGING
        destination = kUndefinedNodeId;
        fabricIndex = kUndefinedFabricIndex;
#endif // CHIP_PROGRESS_LOGGING
    }
    break;
    default:
        return CHIP_ERROR_INTERNAL;
    }

#if CHIP_PROGRESS_LOGGING
    CompressedFabricId compressedFabricId = kUndefinedCompressedFabricId;

    if (fabricIndex != kUndefinedFabricIndex && mFabricTable != nullptr)
    {
        auto fabricInfo = mFabricTable->FindFabricWithIndex(fabricIndex);
        if (fabricInfo)
        {
            compressedFabricId = fabricInfo->GetCompressedFabricId();
        }
    }

    auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID());
    auto * msgTypeName  = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType());

    //
    // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20
    //
    char ackBuf[20];
    ackBuf[0] = '\0';
    if (payloadHeader.GetAckMessageCounter().HasValue())
    {
        snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value());
    }

    char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
    destination_address.ToString(addressStr);

    // Work around pigweed not allowing more than 14 format args in a log
    // message when using tokenized logs.
    char typeStr[4 + 1 + 2 + 1];
    snprintf(typeStr, sizeof(typeStr), "%04X:%02X", payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType());

    //
    // Legend that can be used to decode this log line can be found in messaging/README.md
    //
    ChipLogProgress(ExchangeManager,
                    "<<< [E:" ChipLogFormatExchangeId " S:%u M:" ChipLogFormatMessageCounter
                    "%s] (%s) Msg TX to %u:" ChipLogFormatX64 " [%04X] [%s] --- Type %s (%s:%s)",
                    ChipLogValueExchangeIdFromSentHeader(payloadHeader), sessionHandle->SessionIdForLogging(),
                    packetHeader.GetMessageCounter(), ackBuf, Transport::GetSessionTypeString(sessionHandle), fabricIndex,
                    ChipLogValueX64(destination), static_cast<uint16_t>(compressedFabricId), addressStr, typeStr, protocolName,
                    msgTypeName);
#endif

    ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
    preparedMessage = EncryptedPacketBufferHandle::MarkEncrypted(std::move(message));

    return CHIP_NO_ERROR;
}

CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHandle,
                                               const EncryptedPacketBufferHandle & preparedMessage)
{
    VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(!preparedMessage.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);

    Transport::PeerAddress multicastAddress; // Only used for the group case
    const Transport::PeerAddress * destination;

    switch (sessionHandle->GetSessionType())
    {
    case Transport::Session::SessionType::kGroupOutgoing: {
        auto groupSession = sessionHandle->AsOutgoingGroupSession();

        const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
        VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

        multicastAddress = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());
        destination      = &multicastAddress;
    }
    break;
    case Transport::Session::SessionType::kSecure: {
        // Find an active connection to the specified peer node
        SecureSession * secure = sessionHandle->AsSecureSession();

        // This marks any connection where we send data to as 'active'
        secure->MarkActive();

        destination = &secure->GetPeerAddress();
    }
    break;
    case Transport::Session::SessionType::kUnauthenticated: {
        auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
        unauthenticated->MarkActive();
        destination = &unauthenticated->GetPeerAddress();
    }
    break;
    default:
        return CHIP_ERROR_INTERNAL;
    }

    PacketBufferHandle msgBuf = preparedMessage.CastToWritable();
    VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);

#if CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
    if (sessionHandle->GetSessionType() == Transport::Session::SessionType::kGroupOutgoing)
    {
        chip::Inet::InterfaceIterator interfaceIt;
        chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
        chip::Inet::IPAddress addr;
        bool interfaceFound = false;

        while (interfaceIt.Next())
        {
            char name[chip::Inet::InterfaceId::kMaxIfNameLength];
            interfaceIt.GetInterfaceName(name, chip::Inet::InterfaceId::kMaxIfNameLength);
            if (interfaceIt.SupportsMulticast() && interfaceIt.IsUp())
            {
                interfaceId = interfaceIt.GetInterfaceId();
                if (CHIP_NO_ERROR == interfaceId.GetLinkLocalAddr(&addr))
                {
                    ChipLogDetail(Inet, "Interface %s has a link local address", name);

                    interfaceFound             = true;
                    PacketBufferHandle tempBuf = msgBuf.CloneData();
                    VerifyOrReturnError(!tempBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
                    VerifyOrReturnError(!tempBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);

                    destination = &(multicastAddress.SetInterface(interfaceId));
                    if (mTransportMgr != nullptr)
                    {
                        if (CHIP_NO_ERROR != mTransportMgr->SendMessage(*destination, std::move(tempBuf)))
                        {
                            ChipLogError(Inet, "Failed to send Multicast message on interface %s", name);
                        }
                        else
                        {
                            ChipLogDetail(Inet, "Successfully send Multicast message on interface %s", name);
                        }
                    }
                }
            }
        }

        if (!interfaceFound)
        {
            ChipLogError(Inet, "No valid Interface found.. Sending to the default one.. ");
        }
        else
        {
            // Always return No error, because we expect some interface to fails and others to always succeed (e.g. lo interface)
            return CHIP_NO_ERROR;
        }
    }

#endif // CHIP_SYSTEM_CONFIG_MULTICAST_HOMING

    if (mTransportMgr != nullptr)
    {
        CHIP_ERROR err = mTransportMgr->SendMessage(*destination, std::move(msgBuf));
#if CHIP_ERROR_LOGGING
        if (err != CHIP_NO_ERROR)
        {
            char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
            destination->ToString(addressStr);
            ChipLogError(Inet, "SendMessage() to %s failed: %" CHIP_ERROR_FORMAT, addressStr, err.Format());
        }
#endif // CHIP_ERROR_LOGGING
        return err;
    }

    ChipLogError(Inet, "The transport manager is not initialized. Unable to send the message");
    return CHIP_ERROR_INCORRECT_STATE;
}

void SessionManager::ExpireAllSessions(const ScopedNodeId & node)
{
    ChipLogDetail(Inet, "Expiring all sessions for node " ChipLogFormatScopedNodeId "!!", ChipLogValueScopedNodeId(node));

    ForEachMatchingSession(node, [](auto * session) { session->MarkForEviction(); });
}

void SessionManager::ExpireAllSessionsForFabric(FabricIndex fabricIndex)
{
    ChipLogDetail(Inet, "Expiring all sessions for fabric 0x%x!!", static_cast<unsigned>(fabricIndex));

    ForEachMatchingSession(fabricIndex, [](auto * session) { session->MarkForEviction(); });
}

CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node)
{
    ChipLogDetail(Inet, "Expiring all sessions to peer " ChipLogFormatScopedNodeId " that are on the same logical fabric!!",
                  ChipLogValueScopedNodeId(node));

    return ForEachMatchingSessionOnLogicalFabric(node, [](auto * session) { session->MarkForEviction(); });
}

CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex)
{
    ChipLogDetail(Inet, "Expiring all sessions on the same logical fabric as fabric 0x%x!!", static_cast<unsigned>(fabricIndex));

    return ForEachMatchingSessionOnLogicalFabric(fabricIndex, [](auto * session) { session->MarkForEviction(); });
}

void SessionManager::ExpireAllPASESessions()
{
    ChipLogDetail(Inet, "Expiring all PASE sessions");
    mSecureSessions.ForEachSession([&](auto session) {
        if (session->GetSecureSessionType() == Transport::SecureSession::Type::kPASE)
        {
            session->MarkForEviction();
        }
        return Loop::Continue;
    });
}

void SessionManager::MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type)
{
    mSecureSessions.ForEachSession([&node, &type](auto session) {
        if (session->IsActiveSession() && session->GetPeer() == node &&
            (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
        {
            session->MarkAsDefunct();
        }
        return Loop::Continue;
    });
}

void SessionManager::UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr)
{
    mSecureSessions.ForEachSession([&node, &addr](auto session) {
        // Arguably we should only be updating active and defunct sessions, but there is no harm
        // in updating evicted sessions.
        if (session->GetPeer() == node && Transport::SecureSession::Type::kCASE == session->GetSecureSessionType())
        {
            session->SetPeerAddress(addr);
        }
        return Loop::Continue;
    });
}

Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType,
                                                        const ScopedNodeId & sessionEvictionHint)
{
    VerifyOrReturnValue(mState == State::kInitialized, NullOptional);
    return mSecureSessions.CreateNewSecureSession(secureSessionType, sessionEvictionHint);
}

CHIP_ERROR SessionManager::InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
                                                        uint16_t peerSessionId, FabricIndex fabric,
                                                        const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role)
{
    NodeId localNodeId              = kUndefinedNodeId;
    Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
        chip::Transport::SecureSession::Type::kPASE, localSessionId, localNodeId, peerNodeId, CATValues{}, peerSessionId, fabric,
        GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
    VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
    SecureSession * secureSession = session.Value()->AsSecureSession();
    secureSession->SetPeerAddress(peerAddress);

    size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
    ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
    ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
        *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
    secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
    sessionHolder.Grab(session.Value());
    return CHIP_NO_ERROR;
}

CHIP_ERROR SessionManager::InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId,
                                                        uint16_t peerSessionId, NodeId localNodeId, NodeId peerNodeId,
                                                        FabricIndex fabric, const Transport::PeerAddress & peerAddress,
                                                        CryptoContext::SessionRole role, const CATValues & cats)
{
    Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
        chip::Transport::SecureSession::Type::kCASE, localSessionId, localNodeId, peerNodeId, cats, peerSessionId, fabric,
        GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
    VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
    SecureSession * secureSession = session.Value()->AsSecureSession();
    secureSession->SetPeerAddress(peerAddress);

    size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
    ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
    ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
        *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
    secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
    sessionHolder.Grab(session.Value());
    return CHIP_NO_ERROR;
}

void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
    PacketHeader partialPacketHeader;

    CHIP_ERROR err = partialPacketHeader.DecodeFixed(msg);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Inet, "Failed to decode packet header: %" CHIP_ERROR_FORMAT, err.Format());
        return;
    }

    if (partialPacketHeader.IsEncrypted())
    {
        if (partialPacketHeader.IsGroupSession())
        {
            SecureGroupMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
        }
        else
        {
            SecureUnicastMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
        }
    }
    else
    {
        UnauthenticatedMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
    }
}

void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader,
                                                    const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
    MATTER_TRACE_SCOPE("Unauthenticated Message Dispatch", "SessionManager");

    // Drop unsecured messages with privacy enabled.
    if (partialPacketHeader.HasPrivacyFlag())
    {
        ChipLogError(Inet, "Dropping unauthenticated message with privacy flag set");
        return;
    }

    PacketHeader packetHeader;
    ReturnOnFailure(packetHeader.DecodeAndConsume(msg));

    Optional<NodeId> source      = packetHeader.GetSourceNodeId();
    Optional<NodeId> destination = packetHeader.GetDestinationNodeId();

    if ((source.HasValue() && destination.HasValue()) || (!source.HasValue() && !destination.HasValue()))
    {
        ChipLogProgress(Inet,
                        "Received malformed unsecure packet with source 0x" ChipLogFormatX64 " destination 0x" ChipLogFormatX64,
                        ChipLogValueX64(source.ValueOr(kUndefinedNodeId)), ChipLogValueX64(destination.ValueOr(kUndefinedNodeId)));
        return; // ephemeral node id is only assigned to the initiator, there should be one and only one node id exists.
    }

    Optional<SessionHandle> optionalSession;
    if (source.HasValue())
    {
        // Assume peer is the initiator, we are the responder.
        optionalSession = mUnauthenticatedSessions.FindOrAllocateResponder(source.Value(), GetDefaultMRPConfig());
        if (!optionalSession.HasValue())
        {
            ChipLogError(Inet, "UnauthenticatedSession exhausted");
            return;
        }
    }
    else
    {
        // Assume peer is the responder, we are the initiator.
        optionalSession = mUnauthenticatedSessions.FindInitiator(destination.Value());
        if (!optionalSession.HasValue())
        {
            ChipLogProgress(Inet, "Received unknown unsecure packet for initiator 0x" ChipLogFormatX64,
                            ChipLogValueX64(destination.Value()));
            return;
        }
    }

    const SessionHandle & session                        = optionalSession.Value();
    Transport::UnauthenticatedSession * unsecuredSession = session->AsUnauthenticatedSession();
    Transport::PeerAddress mutablePeerAddress            = peerAddress;
    CorrectPeerAddressInterfaceID(mutablePeerAddress);
    unsecuredSession->SetPeerAddress(mutablePeerAddress);
    SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;

    unsecuredSession->MarkActiveRx();

    PayloadHeader payloadHeader;
    ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));

    // Verify message counter
    CHIP_ERROR err = unsecuredSession->GetPeerMessageCounter().VerifyUnencrypted(packetHeader.GetMessageCounter());
    if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
    {
        ChipLogDetail(Inet,
                      "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
                      " on exchange " ChipLogFormatExchangeId,
                      packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
        isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
        err         = CHIP_NO_ERROR;
    }
    else
    {
        // VerifyUnencrypted always returns one of CHIP_NO_ERROR or
        // CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED.
        unsecuredSession->GetPeerMessageCounter().CommitUnencrypted(packetHeader.GetMessageCounter());
    }
    if (mCB != nullptr)
    {
        MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
                                    unsecuredSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));

        CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength());
        mCB->OnMessageReceived(packetHeader, payloadHeader, session, isDuplicate, std::move(msg));
    }
    else
    {
        ChipLogError(Inet, "Received UNSECURED message was not processed.");
    }
}

void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader,
                                                  const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
    MATTER_TRACE_SCOPE("Secure Unicast Message Dispatch", "SessionManager");

    CHIP_ERROR err = CHIP_NO_ERROR;

    Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(partialPacketHeader.GetSessionId());

    PayloadHeader payloadHeader;

    // Drop secure unicast messages with privacy enabled.
    if (partialPacketHeader.HasPrivacyFlag())
    {
        ChipLogError(Inet, "Dropping secure unicast message with privacy flag set");
        return;
    }

    PacketHeader packetHeader;
    ReturnOnFailure(packetHeader.DecodeAndConsume(msg));

    SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;

    if (msg.IsNull())
    {
        ChipLogError(Inet, "Secure transport received Unicast NULL packet, discarding");
        return;
    }

    if (!session.HasValue())
    {
        ChipLogError(Inet, "Data received on an unknown session (LSID=%d). Dropping it!", packetHeader.GetSessionId());
        return;
    }

    Transport::SecureSession * secureSession = session.Value()->AsSecureSession();

    // We need to allow through messages even on sessions that are pending
    // evictions, because for some cases (UpdateNOC, RemoveFabric, etc) there
    // can be a single exchange alive on the session waiting for a MRP ack, and
    // we need to make sure to send the ack through.  The exchange manager is
    // responsible for ensuring that such messages do not lead to new exchange
    // creation.
    if (!secureSession->IsDefunct() && !secureSession->IsActiveSession() && !secureSession->IsPendingEviction())
    {
        ChipLogError(Inet, "Secure transport received message on a session in an invalid state (state = '%s')",
                     secureSession->GetStateStr());
        return;
    }

    // Decrypt and verify the message before message counter verification or any further processing.
    CryptoContext::NonceStorage nonce;
    // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use
    // and the key is short-lived and always different for each PASE session.
    CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(),
                              secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId()
                                                                                                  : kUndefinedNodeId);
    if (SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), nonce, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR)
    {
        ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding");
        return;
    }

    err =
        secureSession->GetSessionMessageCounter().GetPeerMessageCounter().VerifyEncryptedUnicast(packetHeader.GetMessageCounter());
    if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
    {
        ChipLogDetail(Inet,
                      "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
                      " on exchange " ChipLogFormatExchangeId,
                      packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
        isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
        err         = CHIP_NO_ERROR;
    }
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
        return;
    }

    secureSession->MarkActiveRx();

    if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck())
    {
        // If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU
        // cycles on further message processing.
        return;
    }

    if (isDuplicate == SessionMessageDelegate::DuplicateMessage::No)
    {
        secureSession->GetSessionMessageCounter().GetPeerMessageCounter().CommitEncryptedUnicast(packetHeader.GetMessageCounter());
    }

    Transport::PeerAddress mutablePeerAddress = peerAddress;
    CorrectPeerAddressInterfaceID(mutablePeerAddress);
    if (secureSession->GetPeerAddress() != mutablePeerAddress)
    {
        secureSession->SetPeerAddress(mutablePeerAddress);
    }

    if (mCB != nullptr)
    {
        MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kSecureUnicast, &payloadHeader, &packetHeader,
                                    secureSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
        CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength());
        mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), isDuplicate, std::move(msg));
    }
    else
    {
        ChipLogError(Inet, "Received SECURED message was not processed.");
    }
}

/**
 * Helper function to implement a single attempt to decrypt a groupcast message
 * using the given group key and privacy setting.
 *
 * @param[in] partialPacketHeader The partial packet header with non-obfuscated message fields (result of calling DecodeFixed).
 * @param[out] packetHeaderCopy A copy of the packet header, to be filled with privacy decrypted fields
 * @param[out] payloadHeader The payload header of the decrypted message
 * @param[in] applyPrivacy Whether to apply privacy deobfuscation
 * @param[out] msgCopy A copy of the message, to be filled with the decrypted message
 * @param[in] mac The MAC of the message
 * @param[in] groupContext The group context to use for decryption key material
 *
 * @return true if the message was decrypted successfully
 * @return false if the message could not be decrypted
 */
static bool GroupKeyDecryptAttempt(const PacketHeader & partialPacketHeader, PacketHeader & packetHeaderCopy,
                                   PayloadHeader & payloadHeader, bool applyPrivacy, System::PacketBufferHandle & msgCopy,
                                   const MessageAuthenticationCode & mac,
                                   const Credentials::GroupDataProvider::GroupSession & groupContext)
{
    bool decrypted = false;
    CryptoContext context(groupContext.keyContext);

    if (applyPrivacy)
    {
        // Perform privacy deobfuscation, if applicable.
        uint8_t * privacyHeader = partialPacketHeader.PrivacyHeader(msgCopy->Start());
        size_t privacyLength    = partialPacketHeader.PrivacyHeaderLength();
        if (CHIP_NO_ERROR != context.PrivacyDecrypt(privacyHeader, privacyLength, privacyHeader, partialPacketHeader, mac))
        {
            return false;
        }
    }

    if (packetHeaderCopy.DecodeAndConsume(msgCopy) != CHIP_NO_ERROR)
    {
        ChipLogError(Inet, "Failed to decode Groupcast packet header. Discarding.");
        return false;
    }

    // Optimization to reduce number of decryption attempts
    GroupId groupId = packetHeaderCopy.GetDestinationGroupId().Value();
    if (groupId != groupContext.group_id)
    {
        return false;
    }

    CryptoContext::NonceStorage nonce;
    CryptoContext::BuildNonce(nonce, packetHeaderCopy.GetSecurityFlags(), packetHeaderCopy.GetMessageCounter(),
                              packetHeaderCopy.GetSourceNodeId().Value());
    decrypted = (CHIP_NO_ERROR == SecureMessageCodec::Decrypt(context, nonce, payloadHeader, packetHeaderCopy, msgCopy));

    return decrypted;
}

void SessionManager::SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader,
                                                const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
    MATTER_TRACE_SCOPE("Group Message Dispatch", "SessionManager");

    PayloadHeader payloadHeader;
    PacketHeader packetHeaderCopy; /// Packet header decoded per group key, with privacy decrypted fields
    System::PacketBufferHandle msgCopy;
    Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider();
    VerifyOrReturn(nullptr != groups);
    CHIP_ERROR err = CHIP_NO_ERROR;

    if (!partialPacketHeader.HasDestinationGroupId())
    {
        return; // malformed packet
    }

    // Check if Message Header is valid first
    if (!(partialPacketHeader.IsValidMCSPMsg() || partialPacketHeader.IsValidGroupMsg()))
    {
        ChipLogError(Inet, "Invalid condition found in packet header");
        return;
    }

    // Trial decryption with GroupDataProvider
    Credentials::GroupDataProvider::GroupSession groupContext;
    auto iter = groups->IterateGroupSessions(partialPacketHeader.GetSessionId());
    if (iter == nullptr)
    {
        ChipLogError(Inet, "Failed to retrieve Groups iterator. Discarding everything");
        return;
    }

    // Extract MIC from the end of the message.
    uint8_t * data     = msg->Start();
    uint16_t len       = msg->DataLength();
    uint16_t footerLen = partialPacketHeader.MICTagLength();
    VerifyOrReturn(footerLen <= len);

    uint16_t taglen = 0;
    MessageAuthenticationCode mac;
    ReturnOnFailure(mac.Decode(partialPacketHeader, &data[len - footerLen], footerLen, &taglen));
    VerifyOrReturn(taglen == footerLen);

    bool decrypted = false;
    while (!decrypted && iter->Next(groupContext))
    {
        CryptoContext context(groupContext.keyContext);
        msgCopy = msg.CloneData();
        if (msgCopy.IsNull())
        {
            ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
            return;
        }

        bool privacy = partialPacketHeader.HasPrivacyFlag();
        decrypted =
            GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, privacy, msgCopy, mac, groupContext);

#if CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
        if (privacy && !decrypted)
        {
            // Try processing the P=1 message again without privacy as a work-around for invalid early-SVE2 nodes.
            msgCopy = msg.CloneData();
            if (msgCopy.IsNull())
            {
                ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
                return;
            }
            decrypted =
                GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, false, msgCopy, mac, groupContext);
        }
#endif // CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
    }
    iter->Release();

    if (!decrypted)
    {
        ChipLogError(Inet, "Failed to decrypt group message. Discarding everything");
        return;
    }
    msg = std::move(msgCopy);

    // MCSP check
    if (packetHeaderCopy.IsValidMCSPMsg())
    {
        // TODO: When MCSP Msg, create Secure Session instead of a Group session

        // TODO
        // if (packetHeaderCopy.GetDestinationNodeId().Value() == ThisDeviceNodeID)
        // {
        //     MCSP processing..
        // }

        return;
    }

    // Group Messages should never send an Ack
    if (payloadHeader.NeedsAck())
    {
        ChipLogError(Inet, "Unexpected ACK requested for group message");
        return;
    }

    // Handle Group message counter here spec 4.7.3
    // spec 4.5.1.2 for msg counter
    Transport::PeerMessageCounter * counter = nullptr;

    if (CHIP_NO_ERROR ==
        gGroupPeerTable->FindOrAddPeer(groupContext.fabric_index, packetHeaderCopy.GetSourceNodeId().Value(),
                                       packetHeaderCopy.IsSecureSessionControlMsg(), counter))
    {

        if (Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst == groupContext.security_policy)
        {
            err = counter->VerifyOrTrustFirstGroup(packetHeaderCopy.GetMessageCounter());
        }
        else
        {

            // TODO support cache and sync with MCSP. Issue  #11689
            ChipLogError(Inet, "Received Group Msg with key policy Cache and Sync, but MCSP is not implemented");
            return;

            // cache and sync
            // err = counter->VerifyGroup(packetHeaderCopy.GetMessageCounter());
        }

        if (err != CHIP_NO_ERROR)
        {
            // Exit now, since Group Messages don't have acks or responses of any kind.
            ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
            return;
        }
    }
    else
    {
        ChipLogError(Inet,
                     "Group Counter Tables full or invalid NodeId/FabricIndex after decryption of message, dropping everything");
        return;
    }

    counter->CommitGroup(packetHeaderCopy.GetMessageCounter());

    if (mCB != nullptr)
    {
        // TODO : When MCSP is done, clean up session creation logic
        Transport::IncomingGroupSession groupSession(groupContext.group_id, groupContext.fabric_index,
                                                     packetHeaderCopy.GetSourceNodeId().Value());

        MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kGroupMessage, &payloadHeader, &packetHeaderCopy,
                                    &groupSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));

        CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeaderCopy, &groupSession, peerAddress, msg->Start(), msg->TotalLength());
        mCB->OnMessageReceived(packetHeaderCopy, payloadHeader, SessionHandle(groupSession),
                               SessionMessageDelegate::DuplicateMessage::No, std::move(msg));
    }
    else
    {
        ChipLogError(Inet, "Received GROUP message was not processed.");
    }
}

Optional<SessionHandle> SessionManager::FindSecureSessionForNode(ScopedNodeId peerNodeId,
                                                                 const Optional<Transport::SecureSession::Type> & type)
{
    SecureSession * found = nullptr;

    mSecureSessions.ForEachSession([&peerNodeId, &type, &found](auto session) {
        if (session->IsActiveSession() && session->GetPeer() == peerNodeId &&
            (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
        {
            //
            // Select the active session with the most recent activity to return back to the caller.
            //
            if ((found == nullptr) || (found->GetLastActivityTime() < session->GetLastActivityTime()))
            {
                found = session;
            }
        }

        return Loop::Continue;
    });

    return found != nullptr ? MakeOptional<SessionHandle>(*found) : Optional<SessionHandle>::Missing();
}

/**
 * Provides a means to get diagnostic information such as number of sessions.
 */
[[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda)
{
    mSecureSessions.ForEachSession([&](auto session) {
        SessionHandle handle(*session);
        lambda(context, handle);
        return Loop::Continue;
    });
    return CHIP_NO_ERROR;
}

} // namespace chip
