Matter SDK Coverage Report
Current view: top level - transport - SessionManager.cpp (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 77.7 % 638 496
Test Date: 2026-08-08 07:40:09 Functions: 65.2 % 46 30

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5              :  *    All rights reserved.
       6              :  *
       7              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8              :  *    you may not use this file except in compliance with the License.
       9              :  *    You may obtain a copy of the License at
      10              :  *
      11              :  *        http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  *    Unless required by applicable law or agreed to in writing, software
      14              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  *    See the License for the specific language governing permissions and
      17              :  *    limitations under the License.
      18              :  */
      19              : 
      20              : /**
      21              :  *    @file
      22              :  *      This file implements the CHIP Connection object that maintains a UDP connection.
      23              :  *      TODO This class should be extended to support TCP as well...
      24              :  *
      25              :  */
      26              : 
      27              : #include "SessionManager.h"
      28              : 
      29              : #include <inttypes.h>
      30              : #include <string.h>
      31              : 
      32              : #include "transport/TraceMessage.h"
      33              : #include <app/util/basic-types.h>
      34              : #include <credentials/GroupDataProvider.h>
      35              : #include <inttypes.h>
      36              : #include <lib/core/CHIPKeyIds.h>
      37              : #include <lib/core/Global.h>
      38              : #include <lib/support/AutoRelease.h>
      39              : #include <lib/support/CodeUtils.h>
      40              : #include <lib/support/SafeInt.h>
      41              : #include <lib/support/logging/CHIPLogging.h>
      42              : #include <platform/CHIPDeviceLayer.h>
      43              : #include <protocols/Protocols.h>
      44              : #include <protocols/secure_channel/Constants.h>
      45              : #include <tracing/macros.h>
      46              : #include <transport/GroupPeerMessageCounter.h>
      47              : #include <transport/GroupSession.h>
      48              : #include <transport/SecureMessageCodec.h>
      49              : #include <transport/TracingStructs.h>
      50              : #include <transport/TransportMgr.h>
      51              : #include <transport/raw/GroupcastTesting.h>
      52              : 
      53              : namespace chip {
      54              : 
      55              : using System::PacketBufferHandle;
      56              : using Transport::GroupPeerTable;
      57              : using Transport::PeerAddress;
      58              : using Transport::SecureSession;
      59              : 
      60              : namespace {
      61              : Global<GroupPeerTable> gGroupPeerTable;
      62              : 
      63              : // Helper function that strips off the interface ID from a peer address that is
      64              : // not an IPv6 link-local address.  For any other address type we should rely on
      65              : // the device's routing table to route messages sent.  Forcing messages down a
      66              : // specific interface might fail with "no route to host".
      67        15086 : void CorrectPeerAddressInterfaceID(Transport::PeerAddress & peerAddress)
      68              : {
      69        15086 :     if (peerAddress.GetIPAddress().IsIPv6LinkLocal())
      70              :     {
      71            0 :         return;
      72              :     }
      73        15086 :     peerAddress.SetInterface(Inet::InterfaceId::Null());
      74              : }
      75              : 
      76              : } // namespace
      77              : 
      78        25546 : uint32_t EncryptedPacketBufferHandle::GetMessageCounter() const
      79              : {
      80        25546 :     PacketHeader header;
      81        25546 :     uint16_t headerSize = 0;
      82        25546 :     CHIP_ERROR err      = header.Decode((*this)->Start(), (*this)->DataLength(), &headerSize);
      83              : 
      84        51092 :     if (err == CHIP_NO_ERROR)
      85              :     {
      86        25546 :         return header.GetMessageCounter();
      87              :     }
      88              : 
      89            0 :     ChipLogError(Inet, "Failed to decode EncryptedPacketBufferHandle header with error: %" CHIP_ERROR_FORMAT, err.Format());
      90              : 
      91            0 :     return 0;
      92              : }
      93              : 
      94          702 : SessionManager::SessionManager() : mState(State::kNotReady) {}
      95              : 
      96          702 : SessionManager::~SessionManager()
      97              : {
      98          702 :     this->Shutdown();
      99          702 : }
     100              : 
     101          492 : CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
     102              :                                 Transport::MessageCounterManagerInterface * messageCounterManager,
     103              :                                 chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
     104              :                                 Crypto::SessionKeystore & sessionKeystore)
     105              : {
     106          492 :     VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
     107          492 :     VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     108          492 :     VerifyOrReturnError(storageDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     109          492 :     VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     110          492 :     ReturnErrorOnFailure(fabricTable->AddFabricDelegate(this));
     111              : 
     112          492 :     mState                 = State::kInitialized;
     113          492 :     mSystemLayer           = systemLayer;
     114          492 :     mTransportMgr          = transportMgr;
     115          492 :     mMessageCounterManager = messageCounterManager;
     116          492 :     mFabricTable           = fabricTable;
     117          492 :     mSessionKeystore       = &sessionKeystore;
     118              : 
     119          492 :     mSecureSessions.Init();
     120              : 
     121          492 :     mGlobalUnencryptedMessageCounter.Init();
     122              : 
     123          492 :     ReturnErrorOnFailure(mGroupClientCounter.Init(storageDelegate));
     124              : 
     125          492 :     mTransportMgr->SetSessionManager(this);
     126              : 
     127              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     128          492 :     mConnCompleteCb = nullptr;
     129          492 :     mConnClosedCb   = nullptr;
     130              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     131              : 
     132              :     // Ensure MessageStats struct is at default state on Init
     133          492 :     mMessageStats = MessageStats();
     134              : 
     135          492 :     return CHIP_NO_ERROR;
     136              : }
     137              : 
     138         1193 : void SessionManager::Shutdown()
     139              : {
     140         1193 :     if (mFabricTable != nullptr)
     141              :     {
     142          492 :         mFabricTable->RemoveFabricDelegate(this);
     143          492 :         mFabricTable = nullptr;
     144              :     }
     145              : 
     146              :     // Ensure that we don't create new sessions as we iterate our session table.
     147         1193 :     mState = State::kNotReady;
     148              : 
     149              :     // Just in case some consumer forgot to do it, expire all our secure
     150              :     // sessions.  Note that this stands a good chance of crashing with a
     151              :     // null-deref if there are in fact any secure sessions left, since they will
     152              :     // try to notify their exchanges, which will then try to operate on
     153              :     // partially-shut-down objects.
     154         1193 :     ExpireAllSecureSessions();
     155              : 
     156              :     // We don't have a safe way to check or affect the state of our
     157              :     // mUnauthenticatedSessions.  We can only hope they got shut down properly.
     158              : 
     159         1193 :     mMessageCounterManager = nullptr;
     160              : 
     161         1193 :     mSystemLayer  = nullptr;
     162         1193 :     mTransportMgr = nullptr;
     163         1193 :     mCB           = nullptr;
     164         1193 : }
     165              : 
     166              : /**
     167              :  * @brief Notification that a fabric was removed.
     168              :  *        This function doesn't call ExpireAllSessionsForFabric
     169              :  *        since the CASE session might still be open to send a response
     170              :  *        on the removed fabric.
     171              :  */
     172            7 : void SessionManager::FabricRemoved(FabricIndex fabricIndex)
     173              : {
     174            7 :     TEMPORARY_RETURN_IGNORED gGroupPeerTable->FabricRemoved(fabricIndex);
     175            7 : }
     176              : 
     177        15185 : CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
     178              :                                           System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
     179              : {
     180              :     MATTER_TRACE_SCOPE("PrepareMessage", "SessionManager");
     181              : 
     182        15185 :     VerifyOrReturnError(!message->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     183              : 
     184        15184 :     bool headerEncoded = false;
     185        15184 :     PacketHeader packetHeader;
     186        15184 :     bool isControlMsg = IsControlMessage(payloadHeader);
     187        15184 :     if (isControlMsg)
     188              :     {
     189            0 :         packetHeader.SetSecureSessionControlMsg(true);
     190              :     }
     191              : 
     192        15184 :     if (sessionHandle->AllowsLargePayload())
     193              :     {
     194            0 :         VerifyOrReturnError(message->TotalLength() <= kMaxLargeAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     195              :     }
     196              :     else
     197              :     {
     198        15184 :         VerifyOrReturnError(message->TotalLength() <= kMaxAppMessageLen, CHIP_ERROR_MESSAGE_TOO_LONG);
     199              :     }
     200              : 
     201              : #if CHIP_PROGRESS_LOGGING
     202              :     NodeId destination;
     203              :     FabricIndex fabricIndex;
     204              : #endif // CHIP_PROGRESS_LOGGING
     205              : 
     206        15183 :     NodeId sourceNodeId = kUndefinedNodeId;
     207        15183 :     PeerAddress destination_address;
     208              : 
     209        15183 :     switch (sessionHandle->GetSessionType())
     210              :     {
     211            5 :     case Transport::Session::SessionType::kGroupOutgoing: {
     212            5 :         auto groupSession = sessionHandle->AsOutgoingGroupSession();
     213            5 :         auto * groups     = Credentials::GetGroupDataProvider();
     214            5 :         VerifyOrReturnError(nullptr != groups, CHIP_ERROR_INTERNAL);
     215              : 
     216            5 :         const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
     217            5 :         VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     218              : 
     219            5 :         packetHeader.SetDestinationGroupId(groupSession->GetGroupId());
     220            5 :         packetHeader.SetMessageCounter(mGroupClientCounter.GetCounter(isControlMsg));
     221            5 :         TEMPORARY_RETURN_IGNORED mGroupClientCounter.IncrementCounter(isControlMsg);
     222            5 :         packetHeader.SetSessionType(Header::SessionType::kGroupSession);
     223            5 :         packetHeader.SetFlags(Header::SecFlagValues::kPrivacyFlag);
     224            5 :         sourceNodeId = fabric->GetNodeId();
     225            5 :         packetHeader.SetSourceNodeId(sourceNodeId);
     226              : 
     227            5 :         if (!packetHeader.IsValidGroupMsg())
     228              :         {
     229            0 :             return CHIP_ERROR_INTERNAL;
     230              :         }
     231              : 
     232            5 :         Credentials::GroupDataProvider::GroupInfo info;
     233            5 :         ReturnErrorOnFailure(groups->GetGroupInfo(groupSession->GetFabricIndex(), groupSession->GetGroupId(), info));
     234            5 :         destination_address = (info.UsePerGroupAddress())
     235            5 :             ? Transport::PeerAddress::BuildMatterPerGroupMulticastAddress(fabric->GetFabricId(), groupSession->GetGroupId())
     236            5 :             : Transport::PeerAddress::BuildMatterIanaMulticastAddress();
     237              : 
     238              :         Crypto::SymmetricKeyContext * keyContext =
     239            5 :             groups->GetKeyContext(groupSession->GetFabricIndex(), groupSession->GetGroupId());
     240            5 :         VerifyOrReturnError(nullptr != keyContext, CHIP_ERROR_INTERNAL);
     241            5 :         AutoRelease<Crypto::SymmetricKeyContext> keyContextOwner(keyContext);
     242              : 
     243            5 :         packetHeader.SetSessionId(keyContext->GetKeyHash());
     244            5 :         CryptoContext cryptoContext(keyContext);
     245              : 
     246              :         // Trace before any encryption
     247              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kGroupMessage, &payloadHeader, &packetHeader,
     248              :                                 chip::ByteSpan(message->Start(), message->TotalLength()),
     249              :                                 /* messageTotalSize = */
     250              :                                 (packetHeader.EncodeSizeBytes() + payloadHeader.EncodeSizeBytes() + message->TotalLength() +
     251              :                                  packetHeader.MICTagLength()));
     252            5 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     253              : 
     254              :         CryptoContext::NonceStorage nonce;
     255            5 :         ReturnErrorOnFailure(
     256              :             CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), sourceNodeId));
     257            5 :         CHIP_ERROR err = SecureMessageCodec::Encrypt(cryptoContext, nonce, payloadHeader, packetHeader, message);
     258            5 :         ReturnErrorOnFailure(err);
     259              : 
     260              :         // Encode header now so we can privacy encrypt it
     261            5 :         ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
     262            5 :         headerEncoded = true;
     263              : 
     264              :         // Begin privacy encrypt for appropriate header fields
     265              : 
     266              :         // Since we are not using chained buffers, the message data length should be equal to the total length
     267            5 :         VerifyOrReturnError(message->TotalLength() == message->DataLength(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     268            5 :         uint8_t * data     = message->Start();
     269            5 :         size_t len         = message->TotalLength();
     270            5 :         uint16_t footerLen = packetHeader.MICTagLength();
     271            5 :         VerifyOrReturnError(footerLen <= len, CHIP_ERROR_INTERNAL);
     272              : 
     273            5 :         uint16_t taglen = 0;
     274              :         MessageAuthenticationCode mac;
     275            5 :         ReturnErrorOnFailure(mac.Decode(packetHeader, &data[len - footerLen], footerLen, &taglen));
     276            5 :         VerifyOrReturnError(taglen == footerLen, CHIP_ERROR_INTERNAL);
     277              : 
     278              :         // Pointer to the start of the privacy header within the message buffer.
     279              :         // The privacy header contains fields that need to be privacy-encrypted (e.g. Session ID, Message Counter).
     280            5 :         uint8_t * privacyHeader = packetHeader.PrivacyHeader(message->Start());
     281            5 :         size_t privacyLength    = packetHeader.PrivacyHeaderLength();
     282              : 
     283              :         // We must ensure that:
     284              :         // 1. The privacy header starts within the message buffer.
     285              :         // 2. The privacy header lies entirely within the encoded packet header bounds (to prevent encrypting payload).
     286              :         // 3. The packet header lies entirely within the valid message buffer bounds.
     287              :         //
     288              :         // (privacyHeader + privacyLength): Pointer to the end of the privacy header.
     289              :         // (message->Start() + packetHeader.EncodeSizeBytes()): Pointer to the end of the packet header.
     290              :         // (message->Start() + message->TotalLength()): Pointer to the end of the valid message data in the buffer.
     291            5 :         uint8_t * privacyHeaderEnd = (privacyHeader + privacyLength);
     292            5 :         uint8_t * headerEnd        = (message->Start() + packetHeader.EncodeSizeBytes());
     293            5 :         uint8_t * messageEnd       = (message->Start() + message->TotalLength());
     294              : 
     295              :         // Other fields such as message flags and session ID should exist in the header BEFORE the privacy fields,
     296              :         // so the start of the privacy header must be strictly after the message start
     297            5 :         VerifyOrReturnError(privacyHeader > message->Start(), CHIP_ERROR_INTERNAL);
     298              : 
     299              :         // When the message extensions (MX) security flag is set, this indicates that there will be a message extensions
     300              :         // portion of the header (with a non-zero length). This portion of the header exists after the privacy header end.
     301              :         // If the flag is not set, the end of the privacy header should be the end of the header itself.
     302            5 :         bool mxEnabled = packetHeader.GetSecurityFlags() & to_underlying(Header::SecFlagValues::kMsgExtensionFlag);
     303            5 :         if (mxEnabled)
     304              :         {
     305            0 :             VerifyOrReturnError(privacyHeaderEnd < headerEnd, CHIP_ERROR_INTERNAL);
     306              :         }
     307              :         else
     308              :         {
     309            5 :             VerifyOrReturnError(privacyHeaderEnd == headerEnd, CHIP_ERROR_INTERNAL);
     310              :         }
     311              : 
     312            5 :         VerifyOrReturnError(headerEnd < messageEnd, CHIP_ERROR_INTERNAL);
     313            5 :         ReturnErrorOnFailure(cryptoContext.PrivacyEncrypt(privacyHeader, privacyLength, privacyHeader, packetHeader, mac));
     314              : 
     315              : #if CHIP_PROGRESS_LOGGING
     316            5 :         destination = NodeIdFromGroupId(groupSession->GetGroupId());
     317            5 :         fabricIndex = groupSession->GetFabricIndex();
     318              : #endif // CHIP_PROGRESS_LOGGING
     319           10 :     }
     320            5 :     break;
     321        15055 :     case Transport::Session::SessionType::kSecure: {
     322        15055 :         SecureSession * session = sessionHandle->AsSecureSession();
     323        15055 :         if (session == nullptr)
     324              :         {
     325            0 :             return CHIP_ERROR_NOT_CONNECTED;
     326              :         }
     327              : 
     328        15055 :         MessageCounter & counter = session->GetSessionMessageCounter().GetLocalMessageCounter();
     329              :         uint32_t messageCounter;
     330        15055 :         ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
     331              :         packetHeader
     332        15054 :             .SetMessageCounter(messageCounter)         //
     333        15054 :             .SetSessionId(session->GetPeerSessionId()) //
     334        15054 :             .SetSessionType(Header::SessionType::kUnicastSession);
     335              : 
     336        15054 :         destination_address           = session->GetPeerAddress();
     337        15054 :         CryptoContext & cryptoContext = session->GetCryptoContext();
     338              : 
     339              :         // Trace before any encryption
     340              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kSecureSession, &payloadHeader, &packetHeader,
     341              :                                 chip::ByteSpan(message->Start(), message->TotalLength()),
     342              :                                 /* totalMessageSize = */
     343              :                                 (packetHeader.EncodeSizeBytes() + payloadHeader.EncodeSizeBytes() + message->TotalLength() +
     344              :                                  packetHeader.MICTagLength()));
     345        15054 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     346              : 
     347              :         CryptoContext::NonceStorage nonce;
     348        15054 :         sourceNodeId = session->GetLocalScopedNodeId().GetNodeId();
     349        15054 :         ReturnErrorOnFailure(CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, sourceNodeId));
     350              : 
     351        15054 :         ReturnErrorOnFailure(SecureMessageCodec::Encrypt(cryptoContext, nonce, payloadHeader, packetHeader, message));
     352              : 
     353              : #if CHIP_PROGRESS_LOGGING
     354        15054 :         destination = session->GetPeerNodeId();
     355        15054 :         fabricIndex = session->GetFabricIndex();
     356              : #endif // CHIP_PROGRESS_LOGGING
     357              :     }
     358        15054 :     break;
     359          123 :     case Transport::Session::SessionType::kUnauthenticated: {
     360          123 :         MessageCounter & counter = mGlobalUnencryptedMessageCounter;
     361              :         uint32_t messageCounter;
     362          123 :         ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
     363          123 :         packetHeader.SetMessageCounter(messageCounter);
     364          123 :         Transport::UnauthenticatedSession * session = sessionHandle->AsUnauthenticatedSession();
     365          123 :         switch (session->GetSessionRole())
     366              :         {
     367           72 :         case Transport::UnauthenticatedSession::SessionRole::kInitiator:
     368           72 :             packetHeader.SetSourceNodeId(session->GetEphemeralInitiatorNodeID());
     369           72 :             break;
     370           51 :         case Transport::UnauthenticatedSession::SessionRole::kResponder:
     371           51 :             packetHeader.SetDestinationNodeId(session->GetEphemeralInitiatorNodeID());
     372           51 :             break;
     373              :         }
     374              : 
     375          123 :         auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
     376          123 :         destination_address  = unauthenticated->GetPeerAddress();
     377              : 
     378              :         // Trace after all headers are settled.
     379              :         MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
     380              :                                 chip::ByteSpan(message->Start(), message->TotalLength()),
     381              :                                 /* messageTotalSize = */ packetHeader.EncodeSizeBytes() + payloadHeader.EncodeSizeBytes() +
     382              :                                     message->TotalLength());
     383          123 :         CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
     384              : 
     385          123 :         ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));
     386              : 
     387              : #if CHIP_PROGRESS_LOGGING
     388          123 :         destination = kUndefinedNodeId;
     389          123 :         fabricIndex = kUndefinedFabricIndex;
     390          123 :         if (session->GetSessionRole() == Transport::UnauthenticatedSession::SessionRole::kResponder)
     391              :         {
     392           51 :             destination = session->GetEphemeralInitiatorNodeID();
     393              :         }
     394           72 :         else if (session->GetSessionRole() == Transport::UnauthenticatedSession::SessionRole::kInitiator)
     395              :         {
     396           72 :             sourceNodeId = session->GetEphemeralInitiatorNodeID();
     397              :         }
     398              : #endif // CHIP_PROGRESS_LOGGING
     399              :     }
     400          123 :     break;
     401            0 :     default:
     402            0 :         return CHIP_ERROR_INTERNAL;
     403              :     }
     404              : 
     405        15182 :     if (!headerEncoded)
     406              :     {
     407        15177 :         ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
     408              :     }
     409              : 
     410              : #if CHIP_PROGRESS_LOGGING
     411        15182 :     CompressedFabricId compressedFabricId = kUndefinedCompressedFabricId;
     412              : 
     413        15182 :     if (fabricIndex != kUndefinedFabricIndex && mFabricTable != nullptr)
     414              :     {
     415        15012 :         auto fabricInfo = mFabricTable->FindFabricWithIndex(fabricIndex);
     416        15012 :         if (fabricInfo)
     417              :         {
     418        15012 :             compressedFabricId = fabricInfo->GetCompressedFabricId();
     419              :         }
     420              :     }
     421              : 
     422        15182 :     auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID());
     423        15182 :     auto * msgTypeName  = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType());
     424              : 
     425              :     //
     426              :     // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20
     427              :     //
     428              :     char ackBuf[20];
     429        15182 :     ackBuf[0] = '\0';
     430        15182 :     if (payloadHeader.GetAckMessageCounter().HasValue())
     431              :     {
     432        12727 :         snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value());
     433              :     }
     434              : 
     435        15182 :     char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
     436        15182 :     destination_address.ToString(addressStr);
     437              : 
     438              :     // Work around pigweed not allowing more than 14 format args in a log
     439              :     // message when using tokenized logs.
     440              :     char typeStr[4 + 1 + 2 + 1];
     441        15182 :     snprintf(typeStr, sizeof(typeStr), "%04X:%02X", payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType());
     442              : 
     443              :     // More work around pigweed not allowing more than 14 format args in a log
     444              :     // message when using tokenized logs.
     445              :     // ChipLogFormatExchangeId logs the numeric exchange ID (at most 5 chars,
     446              :     // since it's a uint16_t) and one char for initiator/responder.  Plus we
     447              :     // need a null-terminator.
     448              :     char exchangeStr[5 + 1 + 1];
     449        15182 :     snprintf(exchangeStr, sizeof(exchangeStr), ChipLogFormatExchangeId, ChipLogValueExchangeIdFromSentHeader(payloadHeader));
     450              : 
     451              :     // More work around pigweed not allowing more than 14 format args in a log
     452              :     // message when using tokenized logs.
     453              :     // text(5) + source(16) + text(4) + fabricIndex(uint16_t, at most 5 chars) + text(1) + destination(16) + text(2) + compressed
     454              :     // fabric id(4) + text(1) + null-terminator
     455              :     char sourceDestinationStr[5 + 16 + 4 + 5 + 1 + 16 + 2 + 4 + 1 + 1];
     456        15182 :     snprintf(sourceDestinationStr, sizeof(sourceDestinationStr), "from " ChipLogFormatX64 " to %u:" ChipLogFormatX64 " [%04X]",
     457        15182 :              ChipLogValueX64(sourceNodeId), fabricIndex, ChipLogValueX64(destination), static_cast<uint16_t>(compressedFabricId));
     458              : 
     459              :     //
     460              :     // Legend that can be used to decode this log line can be found in messaging/README.md
     461              :     //
     462        15182 :     ChipLogProgress(ExchangeManager,
     463              :                     "<<< [E:%s S:%u M:" ChipLogFormatMessageCounter "%s] (%s) Msg TX %s [%s] --- Type %s (%s:%s) (B:%u)",
     464              :                     exchangeStr, sessionHandle->SessionIdForLogging(), packetHeader.GetMessageCounter(), ackBuf,
     465              :                     Transport::GetSessionTypeString(sessionHandle), sourceDestinationStr, addressStr, typeStr, protocolName,
     466              :                     msgTypeName, static_cast<unsigned>(message->TotalLength()));
     467              : #endif
     468              : 
     469        15182 :     preparedMessage = EncryptedPacketBufferHandle::MarkEncrypted(std::move(message));
     470              : 
     471        15182 :     CountMessagesSent(sessionHandle, payloadHeader);
     472        15182 :     return CHIP_NO_ERROR;
     473              : }
     474              : 
     475        15213 : CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHandle,
     476              :                                                const EncryptedPacketBufferHandle & preparedMessage)
     477              : {
     478        15213 :     VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
     479        15213 :     VerifyOrReturnError(!preparedMessage.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     480              : 
     481        15213 :     Transport::PeerAddress multicastAddress; // Only used for the group case
     482              :     const Transport::PeerAddress * destination;
     483              : 
     484        15213 :     switch (sessionHandle->GetSessionType())
     485              :     {
     486            3 :     case Transport::Session::SessionType::kGroupOutgoing: {
     487            3 :         auto groupSession = sessionHandle->AsOutgoingGroupSession();
     488              : 
     489            3 :         const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
     490            3 :         VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     491            3 :         auto * groups = Credentials::GetGroupDataProvider();
     492            3 :         VerifyOrReturnError(nullptr != groups, CHIP_ERROR_INTERNAL);
     493              : 
     494            3 :         Credentials::GroupDataProvider::GroupInfo info;
     495            3 :         ReturnErrorOnFailure(groups->GetGroupInfo(groupSession->GetFabricIndex(), groupSession->GetGroupId(), info));
     496            3 :         multicastAddress = (info.UsePerGroupAddress())
     497            3 :             ? Transport::PeerAddress::BuildMatterPerGroupMulticastAddress(fabric->GetFabricId(), groupSession->GetGroupId())
     498            3 :             : Transport::PeerAddress::BuildMatterIanaMulticastAddress();
     499            3 :         destination      = &multicastAddress;
     500              :     }
     501            3 :     break;
     502        15084 :     case Transport::Session::SessionType::kSecure: {
     503              :         // Find an active connection to the specified peer node
     504        15084 :         SecureSession * secure = sessionHandle->AsSecureSession();
     505              : 
     506              :         // This marks any connection where we send data to as 'active'
     507        15084 :         secure->MarkActive();
     508              : 
     509        15084 :         destination = &secure->GetPeerAddress();
     510              :     }
     511        15084 :     break;
     512          126 :     case Transport::Session::SessionType::kUnauthenticated: {
     513          126 :         auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
     514          126 :         unauthenticated->MarkActive();
     515          126 :         destination = &unauthenticated->GetPeerAddress();
     516              :     }
     517          126 :     break;
     518            0 :     default:
     519            0 :         return CHIP_ERROR_INTERNAL;
     520              :     }
     521              : 
     522        30426 :     PacketBufferHandle msgBuf = preparedMessage.CastToWritable();
     523        15213 :     VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     524        15213 :     VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     525              : 
     526              : #if CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
     527        15213 :     if (sessionHandle->GetSessionType() == Transport::Session::SessionType::kGroupOutgoing)
     528              :     {
     529            3 :         chip::Inet::InterfaceIterator interfaceIt;
     530            3 :         chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
     531              :         chip::Inet::IPAddress addr;
     532            3 :         bool interfaceFound = false;
     533              : 
     534            9 :         while (interfaceIt.Next())
     535              :         {
     536            6 :             if (interfaceIt.SupportsMulticast() && interfaceIt.IsUp())
     537              :             {
     538              :                 char name[Inet::InterfaceId::kMaxIfNameLength];
     539            3 :                 TEMPORARY_RETURN_IGNORED interfaceIt.GetInterfaceName(name, Inet::InterfaceId::kMaxIfNameLength);
     540            3 :                 interfaceId = interfaceIt.GetInterfaceId();
     541            6 :                 if (CHIP_NO_ERROR == interfaceId.GetLinkLocalAddr(&addr))
     542              :                 {
     543            3 :                     ChipLogDetail(Inet, "Interface %s has a link local address", name);
     544              : 
     545            3 :                     interfaceFound             = true;
     546            3 :                     PacketBufferHandle tempBuf = msgBuf.CloneData();
     547            3 :                     VerifyOrReturnError(!tempBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
     548            3 :                     VerifyOrReturnError(!tempBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
     549              : 
     550            3 :                     destination = &(multicastAddress.SetInterface(interfaceId));
     551            3 :                     if (mTransportMgr != nullptr)
     552              :                     {
     553            6 :                         if (CHIP_NO_ERROR != mTransportMgr->SendMessage(*destination, std::move(tempBuf)))
     554              :                         {
     555            0 :                             ChipLogError(Inet, "Failed to send Multicast message on interface %s", name);
     556              :                         }
     557              :                         else
     558              :                         {
     559            3 :                             ChipLogDetail(Inet, "Successfully send Multicast message on interface %s", name);
     560              :                         }
     561              :                     }
     562            3 :                 }
     563              :             }
     564              :         }
     565              : 
     566            3 :         if (!interfaceFound)
     567              :         {
     568            0 :             ChipLogError(Inet, "No valid Interface found.. Sending to the default one.. ");
     569              :         }
     570              :         else
     571              :         {
     572              :             // Always return No error, because we expect some interface to fails and others to always succeed (e.g. lo interface)
     573            3 :             return CHIP_NO_ERROR;
     574              :         }
     575            3 :     }
     576              : 
     577              : #endif // CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
     578              : 
     579        15210 :     if (mTransportMgr != nullptr)
     580              :     {
     581        15210 :         CHIP_ERROR err = mTransportMgr->SendMessage(*destination, std::move(msgBuf));
     582              : #if CHIP_ERROR_LOGGING
     583        30420 :         if (err != CHIP_NO_ERROR)
     584              :         {
     585            5 :             char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
     586            5 :             destination->ToString(addressStr);
     587            5 :             ChipLogError(Inet, "SendMessage() to %s failed: %" CHIP_ERROR_FORMAT, addressStr, err.Format());
     588              :         }
     589              : #endif // CHIP_ERROR_LOGGING
     590        15210 :         return err;
     591              :     }
     592              : 
     593            0 :     ChipLogError(Inet, "The transport manager is not initialized. Unable to send the message");
     594            0 :     return CHIP_ERROR_INCORRECT_STATE;
     595              : }
     596              : 
     597            0 : void SessionManager::ExpireAllSessions(const ScopedNodeId & node)
     598              : {
     599            0 :     ChipLogDetail(Inet, "Expiring all sessions for node " ChipLogFormatScopedNodeId "!!", ChipLogValueScopedNodeId(node));
     600              : 
     601            0 :     ForEachMatchingSession(node, [](auto * session) { session->MarkForEviction(); });
     602            0 : }
     603              : 
     604            2 : void SessionManager::ExpireAllSessionsForFabric(FabricIndex fabricIndex)
     605              : {
     606            2 :     ChipLogDetail(Inet, "Expiring all sessions for fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
     607              : 
     608            8 :     ForEachMatchingSession(fabricIndex, [](auto * session) { session->MarkForEviction(); });
     609            2 : }
     610              : 
     611            0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node)
     612              : {
     613            0 :     ChipLogDetail(Inet, "Expiring all sessions to peer " ChipLogFormatScopedNodeId " that are on the same logical fabric!!",
     614              :                   ChipLogValueScopedNodeId(node));
     615              : 
     616            0 :     return ForEachMatchingSessionOnLogicalFabric(node, [](auto * session) { session->MarkForEviction(); });
     617              : }
     618              : 
     619            0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex)
     620              : {
     621            0 :     ChipLogDetail(Inet, "Expiring all sessions on the same logical fabric as fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
     622              : 
     623            0 :     return ForEachMatchingSessionOnLogicalFabric(fabricIndex, [](auto * session) { session->MarkForEviction(); });
     624              : }
     625              : 
     626            0 : void SessionManager::ExpireAllPASESessions()
     627              : {
     628            0 :     ChipLogDetail(Inet, "Expiring all PASE sessions");
     629            0 :     mSecureSessions.ForEachSession([&](auto session) {
     630            0 :         if (session->GetSecureSessionType() == Transport::SecureSession::Type::kPASE)
     631              :         {
     632            0 :             session->MarkForEviction();
     633              :         }
     634            0 :         return Loop::Continue;
     635              :     });
     636            0 : }
     637              : 
     638         1194 : void SessionManager::ExpireAllSecureSessions()
     639              : {
     640         1194 :     mSecureSessions.ForEachSession([&](auto session) {
     641         1739 :         session->MarkForEviction();
     642         1739 :         return Loop::Continue;
     643              :     });
     644         1194 : }
     645              : 
     646            0 : void SessionManager::MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type)
     647              : {
     648            0 :     mSecureSessions.ForEachSession([&node, &type](auto session) {
     649            0 :         if (session->IsActiveSession() && session->GetPeer() == node &&
     650            0 :             (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
     651              :         {
     652            0 :             session->MarkAsDefunct();
     653              :         }
     654            0 :         return Loop::Continue;
     655              :     });
     656            0 : }
     657              : 
     658            0 : void SessionManager::UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr)
     659              : {
     660            0 :     mSecureSessions.ForEachSession([&node, &addr](auto session) {
     661              :         // Arguably we should only be updating active and defunct sessions, but there is no harm
     662              :         // in updating evicted sessions.
     663            0 :         if (session->GetPeer() == node && Transport::SecureSession::Type::kCASE == session->GetSecureSessionType())
     664              :         {
     665            0 :             session->SetPeerAddress(addr);
     666              :         }
     667            0 :         return Loop::Continue;
     668              :     });
     669            0 : }
     670              : 
     671       133663 : Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType,
     672              :                                                         const ScopedNodeId & sessionEvictionHint)
     673              : {
     674       133663 :     VerifyOrReturnValue(mState == State::kInitialized, NullOptional);
     675       133663 :     return mSecureSessions.CreateNewSecureSession(secureSessionType, sessionEvictionHint);
     676              : }
     677              : 
     678         1837 : CHIP_ERROR SessionManager::InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
     679              :                                                         uint16_t peerSessionId, FabricIndex fabric,
     680              :                                                         const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role)
     681              : {
     682         1837 :     NodeId localNodeId              = kUndefinedNodeId;
     683              :     Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
     684              :         chip::Transport::SecureSession::Type::kPASE, localSessionId, localNodeId, peerNodeId, CATValues{}, peerSessionId, fabric,
     685         1837 :         GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
     686         1837 :     VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
     687         1837 :     SecureSession * secureSession = session.Value()->AsSecureSession();
     688         1837 :     secureSession->SetPeerAddress(peerAddress);
     689              : 
     690         1837 :     size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
     691         1837 :     ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
     692         1837 :     ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
     693              :         *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
     694         1837 :     secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
     695         1837 :     sessionHolder.Grab(session.Value());
     696         1837 :     return CHIP_NO_ERROR;
     697         1837 : }
     698              : 
     699           24 : CHIP_ERROR SessionManager::InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId,
     700              :                                                         uint16_t peerSessionId, NodeId localNodeId, NodeId peerNodeId,
     701              :                                                         FabricIndex fabric, const Transport::PeerAddress & peerAddress,
     702              :                                                         CryptoContext::SessionRole role, const CATValues & cats)
     703              : {
     704              :     Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
     705              :         chip::Transport::SecureSession::Type::kCASE, localSessionId, localNodeId, peerNodeId, cats, peerSessionId, fabric,
     706           24 :         GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
     707           24 :     VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
     708           24 :     SecureSession * secureSession = session.Value()->AsSecureSession();
     709           24 :     secureSession->SetPeerAddress(peerAddress);
     710              : 
     711           24 :     size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
     712           24 :     ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
     713           24 :     ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
     714              :         *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
     715           24 :     secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
     716           24 :     sessionHolder.Grab(session.Value());
     717           24 :     return CHIP_NO_ERROR;
     718           24 : }
     719              : 
     720        15106 : void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     721              :                                        Transport::MessageTransportContext * ctxt)
     722              : {
     723        15106 :     PacketHeader partialPacketHeader;
     724              : 
     725        15106 :     CHIP_ERROR err = partialPacketHeader.DecodeFixed(msg);
     726        30212 :     if (err != CHIP_NO_ERROR)
     727              :     {
     728            1 :         ChipLogError(Inet, "Failed to decode packet header: %" CHIP_ERROR_FORMAT, err.Format());
     729            1 :         return;
     730              :     }
     731              : 
     732        15105 :     if (partialPacketHeader.IsEncrypted())
     733              :     {
     734        14983 :         if (partialPacketHeader.IsGroupSession())
     735              :         {
     736            9 :             SecureGroupMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
     737              :         }
     738              :         else
     739              :         {
     740        14974 :             SecureUnicastMessageDispatch(partialPacketHeader, peerAddress, std::move(msg), ctxt);
     741              :         }
     742              :     }
     743              :     else
     744              :     {
     745          122 :         UnauthenticatedMessageDispatch(partialPacketHeader, peerAddress, std::move(msg), ctxt);
     746              :     }
     747              : }
     748              : 
     749              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     750            3 : void SessionManager::HandleConnectionReceived(Transport::ActiveTCPConnectionState & conn)
     751              : {
     752              :     char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     753              : 
     754            3 :     conn.mPeerAddr.ToString(peerAddrBuf);
     755            3 :     ChipLogProgress(Inet, "Received TCP connection request from %s.", peerAddrBuf);
     756              : 
     757            3 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn.mAppState;
     758            3 :     if (appTCPConnCbCtxt != nullptr && appTCPConnCbCtxt->connReceivedCb != nullptr)
     759              :     {
     760            0 :         appTCPConnCbCtxt->connReceivedCb(conn);
     761              :     }
     762            3 : }
     763              : 
     764            3 : void SessionManager::HandleConnectionAttemptComplete(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr)
     765              : {
     766            3 :     VerifyOrReturn(!conn.IsNull());
     767              : 
     768            3 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn->mAppState;
     769            3 :     bool callbackHandled                                       = false;
     770            3 :     if (appTCPConnCbCtxt != nullptr && appTCPConnCbCtxt->connCompleteCb != nullptr)
     771              :     {
     772            0 :         appTCPConnCbCtxt->connCompleteCb(conn, conErr);
     773            0 :         callbackHandled = true;
     774              :     }
     775              : 
     776            3 :     if ((mConnDelegate == nullptr || !mConnDelegate->OnTCPConnectionAttemptComplete(conn, conErr)) && !callbackHandled)
     777              :     {
     778              :         char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     779            0 :         conn->mPeerAddr.ToString(peerAddrBuf);
     780              : 
     781            0 :         ChipLogProgress(Inet, "TCP Connection established with peer %s, but no registered handler.", peerAddrBuf);
     782              :     }
     783              : }
     784              : 
     785            4 : void SessionManager::HandleConnectionClosed(Transport::ActiveTCPConnectionState & conn, CHIP_ERROR conErr)
     786              : {
     787            4 :     Transport::AppTCPConnectionCallbackCtxt * appTCPConnCbCtxt = conn.mAppState;
     788            4 :     if (appTCPConnCbCtxt != nullptr && appTCPConnCbCtxt->connClosedCb != nullptr)
     789              :     {
     790            0 :         appTCPConnCbCtxt->connClosedCb(conn, conErr);
     791              :     }
     792            4 :     MarkSecureSessionOverTCPForEviction(conn, conErr);
     793            4 :     mUnauthenticatedSessions.MarkSessionOverTCPForEviction(conn);
     794            4 : }
     795              : 
     796            0 : CHIP_ERROR SessionManager::TCPConnect(const PeerAddress & peerAddress, Transport::AppTCPConnectionCallbackCtxt * appState,
     797              :                                       Transport::ActiveTCPConnectionHandle & peerConnState)
     798              : {
     799              :     char peerAddrBuf[chip::Transport::PeerAddress::kMaxToStringSize];
     800            0 :     peerAddress.ToString(peerAddrBuf);
     801            0 :     if (mTransportMgr != nullptr)
     802              :     {
     803            0 :         ChipLogProgress(Inet, "Connecting over TCP with peer at %s.", peerAddrBuf);
     804            0 :         return mTransportMgr->TCPConnect(peerAddress, appState, peerConnState);
     805              :     }
     806              : 
     807            0 :     ChipLogError(Inet, "The transport manager is not initialized. Unable to connect to peer at %s.", peerAddrBuf);
     808              : 
     809            0 :     return CHIP_ERROR_INCORRECT_STATE;
     810              : }
     811              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     812              : 
     813          122 : void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader,
     814              :                                                     const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     815              :                                                     Transport::MessageTransportContext * ctxt)
     816              : {
     817              :     MATTER_TRACE_SCOPE("Unauthenticated Message Dispatch", "SessionManager");
     818              : 
     819              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     820          122 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp && ctxt->conn.IsNull())
     821              :     {
     822            0 :         ChipLogError(Inet, "Connection object is missing for received message.");
     823            0 :         return;
     824              :     }
     825              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     826              : 
     827              :     // Drop unsecured messages with privacy enabled.
     828          122 :     if (partialPacketHeader.HasPrivacyFlag())
     829              :     {
     830            0 :         ChipLogError(Inet, "Dropping unauthenticated message with privacy flag set");
     831            0 :         return;
     832              :     }
     833              : 
     834              :     // Capture length before consuming headers.
     835          122 :     [[maybe_unused]] size_t messageTotalSize = msg->TotalLength();
     836              : 
     837          122 :     PacketHeader packetHeader;
     838          122 :     ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
     839              : 
     840          122 :     Optional<NodeId> source      = packetHeader.GetSourceNodeId();
     841          122 :     Optional<NodeId> destination = packetHeader.GetDestinationNodeId();
     842              : 
     843          122 :     if ((source.HasValue() && destination.HasValue()) || (!source.HasValue() && !destination.HasValue()))
     844              :     {
     845            0 :         ChipLogProgress(Inet,
     846              :                         "Received malformed unsecure packet with source 0x" ChipLogFormatX64 " destination 0x" ChipLogFormatX64,
     847              :                         ChipLogValueX64(source.ValueOr(kUndefinedNodeId)), ChipLogValueX64(destination.ValueOr(kUndefinedNodeId)));
     848            0 :         return; // ephemeral node id is only assigned to the initiator, there should be one and only one node id exists.
     849              :     }
     850              : 
     851          122 :     Optional<SessionHandle> optionalSession;
     852          122 :     if (source.HasValue())
     853              :     {
     854              :         // Assume peer is the initiator, we are the responder.
     855           71 :         optionalSession = mUnauthenticatedSessions.FindOrAllocateResponder(source.Value(), GetDefaultMRPConfig(), peerAddress);
     856           71 :         if (!optionalSession.HasValue())
     857              :         {
     858            0 :             ChipLogError(Inet, "UnauthenticatedSession exhausted");
     859            0 :             return;
     860              :         }
     861              :     }
     862              :     else
     863              :     {
     864              :         // Assume peer is the responder, we are the initiator.
     865           51 :         optionalSession = mUnauthenticatedSessions.FindInitiator(destination.Value(), peerAddress);
     866           51 :         if (!optionalSession.HasValue())
     867              :         {
     868            0 :             ChipLogProgress(Inet, "Received unknown unsecure packet for initiator 0x" ChipLogFormatX64,
     869              :                             ChipLogValueX64(destination.Value()));
     870            0 :             return;
     871              :         }
     872              :     }
     873              : 
     874          122 :     const SessionHandle & session                        = optionalSession.Value();
     875          122 :     Transport::UnauthenticatedSession * unsecuredSession = session->AsUnauthenticatedSession();
     876          122 :     Transport::PeerAddress mutablePeerAddress            = peerAddress;
     877          122 :     CorrectPeerAddressInterfaceID(mutablePeerAddress);
     878          122 :     unsecuredSession->SetPeerAddress(mutablePeerAddress);
     879          122 :     SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
     880              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     881              :     // Associate the unauthenticated session with the connection, if not done already.
     882          122 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp)
     883              :     {
     884            1 :         Transport::ActiveTCPConnectionHandle sessionConn = unsecuredSession->GetTCPConnection();
     885            1 :         if (sessionConn.IsNull())
     886              :         {
     887            1 :             unsecuredSession->SetTCPConnection(ctxt->conn);
     888              :         }
     889              :         else
     890              :         {
     891            0 :             if (sessionConn != ctxt->conn)
     892              :             {
     893            0 :                 ChipLogError(Inet, "Unauthenticated data received over TCP connection %p instead of %p. Dropping it!",
     894              :                              static_cast<const void *>(ctxt->conn), static_cast<const void *>(sessionConn));
     895            0 :                 return;
     896              :             }
     897              :         }
     898            1 :     }
     899              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     900              : 
     901          122 :     unsecuredSession->MarkActiveRx();
     902              : 
     903          122 :     PayloadHeader payloadHeader;
     904          122 :     ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
     905              : 
     906              :     // Verify message counter
     907          122 :     CHIP_ERROR err = unsecuredSession->GetPeerMessageCounter().VerifyUnencrypted(packetHeader.GetMessageCounter());
     908          244 :     if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
     909              :     {
     910            0 :         ChipLogDetail(Inet,
     911              :                       "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
     912              :                       " on exchange " ChipLogFormatExchangeId,
     913              :                       packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
     914            0 :         isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
     915            0 :         err         = CHIP_NO_ERROR;
     916              :     }
     917              :     else
     918              :     {
     919              :         // VerifyUnencrypted always returns one of CHIP_NO_ERROR or
     920              :         // CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED.
     921          122 :         unsecuredSession->GetPeerMessageCounter().CommitUnencrypted(packetHeader.GetMessageCounter());
     922              :     }
     923          122 :     if (mCB != nullptr)
     924              :     {
     925              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
     926              :                                     unsecuredSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()),
     927              :                                     messageTotalSize);
     928              : 
     929          122 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength());
     930          122 :         CountMessagesReceived(session, payloadHeader);
     931          122 :         mCB->OnMessageReceived(packetHeader, payloadHeader, session, isDuplicate, std::move(msg));
     932              :     }
     933              :     else
     934              :     {
     935            0 :         ChipLogError(Inet, "Received UNSECURED message was not processed.");
     936              :     }
     937          122 : }
     938              : 
     939        14974 : void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader,
     940              :                                                   const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg,
     941              :                                                   Transport::MessageTransportContext * ctxt)
     942              : {
     943              :     MATTER_TRACE_SCOPE("Secure Unicast Message Dispatch", "SessionManager");
     944              : 
     945        14974 :     CHIP_ERROR err = CHIP_NO_ERROR;
     946              : 
     947              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     948        14974 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp && ctxt->conn.IsNull())
     949              :     {
     950            0 :         ChipLogError(Inet, "Connection object is missing for received message.");
     951           16 :         return;
     952              :     }
     953              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     954              : 
     955        14974 :     Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(partialPacketHeader.GetSessionId());
     956        14974 :     if (!session.HasValue())
     957              :     {
     958           10 :         ChipLogError(Inet, "Data received on an unknown session (LSID=%d). Dropping it!", partialPacketHeader.GetSessionId());
     959           10 :         return;
     960              :     }
     961              : 
     962        14964 :     Transport::SecureSession * secureSession  = session.Value()->AsSecureSession();
     963        14964 :     Transport::PeerAddress mutablePeerAddress = peerAddress;
     964        14964 :     CorrectPeerAddressInterfaceID(mutablePeerAddress);
     965        14964 :     if (secureSession->GetPeerAddress() != mutablePeerAddress)
     966              :     {
     967            6 :         secureSession->SetPeerAddress(mutablePeerAddress);
     968              :     }
     969              : 
     970              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     971              :     // Associate the secure session with the connection, if not done already.
     972        14964 :     if (peerAddress.GetTransportType() == Transport::Type::kTcp)
     973              :     {
     974            0 :         auto sessionConn = secureSession->GetTCPConnection();
     975            0 :         if (sessionConn.IsNull())
     976              :         {
     977            0 :             secureSession->SetTCPConnection(ctxt->conn);
     978              :         }
     979              :         else
     980              :         {
     981            0 :             if (sessionConn != ctxt->conn)
     982              :             {
     983            0 :                 ChipLogError(Inet, "Unicast data received over TCP connection %p instead of %p. Dropping it!",
     984              :                              static_cast<const void *>(ctxt->conn), static_cast<const void *>(sessionConn));
     985            0 :                 return;
     986              :             }
     987              :         }
     988            0 :     }
     989              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     990              :     // Capture length before consuming headers.
     991        14964 :     [[maybe_unused]] size_t messageTotalSize = msg->TotalLength();
     992              : 
     993        14964 :     PayloadHeader payloadHeader;
     994              : 
     995              :     // Drop secure unicast messages with privacy enabled.
     996        14964 :     if (partialPacketHeader.HasPrivacyFlag())
     997              :     {
     998            1 :         ChipLogError(Inet, "Dropping secure unicast message with privacy flag set");
     999            1 :         return;
    1000              :     }
    1001              : 
    1002        14963 :     PacketHeader packetHeader;
    1003        14963 :     ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
    1004              : 
    1005        14963 :     SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
    1006              : 
    1007        14963 :     if (msg.IsNull())
    1008              :     {
    1009            0 :         ChipLogError(Inet, "Secure transport received Unicast NULL packet, discarding");
    1010            0 :         return;
    1011              :     }
    1012              : 
    1013              :     // We need to allow through messages even on sessions that are pending
    1014              :     // evictions, because for some cases (UpdateNOC, RemoveFabric, etc) there
    1015              :     // can be a single exchange alive on the session waiting for a MRP ack, and
    1016              :     // we need to make sure to send the ack through.  The exchange manager is
    1017              :     // responsible for ensuring that such messages do not lead to new exchange
    1018              :     // creation.
    1019        14963 :     if (!secureSession->IsDefunct() && !secureSession->IsActiveSession() && !secureSession->IsPendingEviction())
    1020              :     {
    1021            0 :         ChipLogError(Inet, "Secure transport received message on a session in an invalid state (state = '%s')",
    1022              :                      secureSession->GetStateStr());
    1023            0 :         return;
    1024              :     }
    1025              : 
    1026              :     // Decrypt and verify the message before message counter verification or any further processing.
    1027              :     CryptoContext::NonceStorage nonce;
    1028              :     // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use
    1029              :     // and the key is short-lived and always different for each PASE session.
    1030        29936 :     CHIP_ERROR nonceResult = CryptoContext::BuildNonce(
    1031        14963 :         nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(),
    1032        14973 :         secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId() : kUndefinedNodeId);
    1033        44889 :     if ((nonceResult != CHIP_NO_ERROR) ||
    1034        44889 :         SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), nonce, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR)
    1035              :     {
    1036            3 :         ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding");
    1037            3 :         return;
    1038              :     }
    1039              : 
    1040              :     err =
    1041        14960 :         secureSession->GetSessionMessageCounter().GetPeerMessageCounter().VerifyEncryptedUnicast(packetHeader.GetMessageCounter());
    1042        29920 :     if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
    1043              :     {
    1044            8 :         ChipLogDetail(Inet,
    1045              :                       "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
    1046              :                       " on exchange " ChipLogFormatExchangeId,
    1047              :                       packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
    1048            8 :         isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
    1049            8 :         err         = CHIP_NO_ERROR;
    1050              :     }
    1051        29920 :     if (err != CHIP_NO_ERROR)
    1052              :     {
    1053            0 :         ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
    1054            0 :         return;
    1055              :     }
    1056              : 
    1057        14960 :     secureSession->MarkActiveRx();
    1058              : 
    1059        14960 :     if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck())
    1060              :     {
    1061              :         // If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU
    1062              :         // cycles on further message processing.
    1063            2 :         return;
    1064              :     }
    1065              : 
    1066        14958 :     if (isDuplicate == SessionMessageDelegate::DuplicateMessage::No)
    1067              :     {
    1068        14952 :         secureSession->GetSessionMessageCounter().GetPeerMessageCounter().CommitEncryptedUnicast(packetHeader.GetMessageCounter());
    1069              :     }
    1070              : 
    1071        14958 :     if (mCB != nullptr)
    1072              :     {
    1073              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kSecureUnicast, &payloadHeader, &packetHeader,
    1074              :                                     secureSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()),
    1075              :                                     messageTotalSize);
    1076        14958 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength());
    1077              : 
    1078              :         // Always recompute whether a message is for a commissioning session based on the latest knowledge of
    1079              :         // the fabric table.
    1080        14958 :         if (secureSession->IsCASESession())
    1081              :         {
    1082           20 :             secureSession->SetCaseCommissioningSessionStatus(secureSession->GetFabricIndex() ==
    1083           10 :                                                              mFabricTable->GetPendingNewFabricIndex());
    1084              :         }
    1085              : 
    1086        14958 :         CountMessagesReceived(session.Value(), payloadHeader);
    1087        14958 :         mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), isDuplicate, std::move(msg));
    1088              :     }
    1089              :     else
    1090              :     {
    1091            0 :         ChipLogError(Inet, "Received SECURED message was not processed.");
    1092              :     }
    1093        14974 : }
    1094              : 
    1095              : /**
    1096              :  * Helper function to implement a single attempt to decrypt a groupcast message
    1097              :  * using the given group key and privacy setting.
    1098              :  *
    1099              :  * @param[in] partialPacketHeader The partial packet header with non-obfuscated message fields (result of calling DecodeFixed).
    1100              :  * @param[out] packetHeaderCopy A copy of the packet header, to be filled with privacy decrypted fields
    1101              :  * @param[out] payloadHeader The payload header of the decrypted message
    1102              :  * @param[in] applyPrivacy Whether to apply privacy deobfuscation
    1103              :  * @param[out] msgCopy A copy of the message, to be filled with the decrypted message
    1104              :  * @param[in] mac The MAC of the message
    1105              :  * @param[in] groupContext The group context to use for decryption key material
    1106              :  *
    1107              :  * @return true if the message was decrypted successfully
    1108              :  * @return false if the message could not be decrypted
    1109              :  */
    1110            9 : static bool GroupKeyDecryptAttempt(const PacketHeader & partialPacketHeader, PacketHeader & packetHeaderCopy,
    1111              :                                    PayloadHeader & payloadHeader, bool applyPrivacy, System::PacketBufferHandle & msgCopy,
    1112              :                                    const MessageAuthenticationCode & mac,
    1113              :                                    const Credentials::GroupDataProvider::GroupSession & groupContext)
    1114              : {
    1115            9 :     bool decrypted = false;
    1116            9 :     CryptoContext context(groupContext.keyContext);
    1117              : 
    1118            9 :     if (applyPrivacy)
    1119              :     {
    1120              :         // Perform privacy deobfuscation, if applicable.
    1121            7 :         uint8_t * privacyHeader = partialPacketHeader.PrivacyHeader(msgCopy->Start());
    1122            7 :         size_t privacyLength    = partialPacketHeader.PrivacyHeaderLength();
    1123              : 
    1124              :         // Bounds check: we decrypt in place a privacy header located inside the packet.
    1125              :         // Validate that we are still within the packet as the length is based on header flags.
    1126            7 :         VerifyOrReturnValue((privacyHeader + privacyLength) <= (msgCopy->Start() + msgCopy->TotalLength()), false);
    1127              : 
    1128           12 :         if (CHIP_NO_ERROR != context.PrivacyDecrypt(privacyHeader, privacyLength, privacyHeader, partialPacketHeader, mac))
    1129              :         {
    1130            0 :             return false;
    1131              :         }
    1132              :     }
    1133              : 
    1134           16 :     if (packetHeaderCopy.DecodeAndConsume(msgCopy) != CHIP_NO_ERROR)
    1135              :     {
    1136            0 :         ChipLogError(Inet, "Failed to decode Groupcast packet header. Discarding.");
    1137            0 :         return false;
    1138              :     }
    1139              : 
    1140              :     // Optimization to reduce number of decryption attempts
    1141            8 :     GroupId groupId = packetHeaderCopy.GetDestinationGroupId().Value();
    1142            8 :     if (groupId != groupContext.group_id)
    1143              :     {
    1144            1 :         return false;
    1145              :     }
    1146              : 
    1147              :     CryptoContext::NonceStorage nonce;
    1148              :     CHIP_ERROR nonceResult =
    1149            7 :         CryptoContext::BuildNonce(nonce, packetHeaderCopy.GetSecurityFlags(), packetHeaderCopy.GetMessageCounter(),
    1150            7 :                                   packetHeaderCopy.GetSourceNodeId().Value());
    1151           21 :     decrypted = (nonceResult == CHIP_NO_ERROR) &&
    1152           14 :         (CHIP_NO_ERROR == SecureMessageCodec::Decrypt(context, nonce, payloadHeader, packetHeaderCopy, msgCopy));
    1153              : 
    1154            7 :     return decrypted;
    1155            9 : }
    1156              : 
    1157            9 : void SessionManager::SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader,
    1158              :                                                 const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
    1159              : {
    1160              :     MATTER_TRACE_SCOPE("Group Message Dispatch", "SessionManager");
    1161              : 
    1162           12 :     VerifyOrReturn(!msg->HasChainedBuffer());
    1163              : 
    1164              :     // Capture length before consuming headers.
    1165            9 :     [[maybe_unused]] size_t messageTotalSize = msg->TotalLength();
    1166              : 
    1167            9 :     PayloadHeader payloadHeader;
    1168            9 :     PacketHeader packetHeaderCopy; /// Packet header decoded per group key, with privacy decrypted fields
    1169            9 :     System::PacketBufferHandle msgCopy;
    1170            9 :     Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider();
    1171            9 :     VerifyOrReturn(nullptr != groups);
    1172            9 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1173              : 
    1174            9 :     if (!partialPacketHeader.HasDestinationGroupId())
    1175              :     {
    1176            0 :         return; // malformed packet
    1177              :     }
    1178              : 
    1179              :     // Check if Message Header is valid first
    1180            9 :     if (!(partialPacketHeader.IsValidMCSPMsg() || partialPacketHeader.IsValidGroupMsg()))
    1181              :     {
    1182            0 :         ChipLogError(Inet, "Invalid condition found in packet header");
    1183            0 :         return;
    1184              :     }
    1185              : 
    1186              :     // Trial decryption with GroupDataProvider
    1187            9 :     Credentials::GroupDataProvider::GroupSession groupContext;
    1188              : 
    1189              :     AutoRelease<Credentials::GroupDataProvider::GroupSessionIterator> iter(
    1190            9 :         groups->IterateGroupSessions(partialPacketHeader.GetSessionId()));
    1191              : 
    1192            9 :     if (iter.IsNull())
    1193              :     {
    1194            0 :         ChipLogError(Inet, "Failed to retrieve Groups iterator. Discarding everything");
    1195            0 :         return;
    1196              :     }
    1197              : 
    1198              :     // Extract MIC from the end of the message.
    1199            9 :     uint8_t * data     = msg->Start();
    1200            9 :     size_t len         = msg->TotalLength();
    1201            9 :     uint16_t footerLen = partialPacketHeader.MICTagLength();
    1202            9 :     VerifyOrReturn(footerLen <= len);
    1203              : 
    1204            9 :     uint16_t taglen = 0;
    1205              :     MessageAuthenticationCode mac;
    1206            9 :     ReturnOnFailure(mac.Decode(partialPacketHeader, &data[len - footerLen], footerLen, &taglen));
    1207            9 :     VerifyOrReturn(taglen == footerLen);
    1208              : 
    1209              :     // Groupcast Testing
    1210            9 :     auto & testing = chip::Groupcast::GetTesting();
    1211              : 
    1212            9 :     bool decrypted                    = false;
    1213            9 :     bool hasAnyKeysForFabricUnderTest = false;
    1214           18 :     while (!decrypted && iter->Next(groupContext))
    1215              :     {
    1216            9 :         if (testing.IsEnabled() && testing.IsFabricUnderTest(groupContext.fabric_index))
    1217              :         {
    1218            0 :             hasAnyKeysForFabricUnderTest = true;
    1219              :         }
    1220            9 :         CryptoContext context(groupContext.keyContext);
    1221            9 :         msgCopy = msg.CloneData();
    1222            9 :         if (msgCopy.IsNull())
    1223              :         {
    1224            0 :             ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
    1225            0 :             return;
    1226              :         }
    1227              : 
    1228            9 :         bool privacy = partialPacketHeader.HasPrivacyFlag();
    1229              :         decrypted =
    1230            9 :             GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, privacy, msgCopy, mac, groupContext);
    1231            9 :     }
    1232              :     iter.Release();
    1233              : 
    1234            9 :     if (testing.IsEnabled())
    1235              :     {
    1236            0 :         if (decrypted)
    1237              :         {
    1238              :             // We have a valid groupContext from the loop
    1239            0 :             if (testing.IsFabricUnderTest(groupContext.fabric_index))
    1240              :             {
    1241            0 :                 testing.SetGroupID(packetHeaderCopy.GetDestinationGroupId().Value());
    1242              :             }
    1243              :         }
    1244              :         else
    1245              :         {
    1246              :             // FAILURE CASE: No valid groupContext or decryption failed. This can happen
    1247              :             // for example, when there is an empty group key map. This means GroupSessions
    1248              :             // cannot be iterated over to populate groupContext, and the fabric index cannot be
    1249              :             // explicitly checked here.
    1250            0 :             testing.SetTestResult(hasAnyKeysForFabricUnderTest ? chip::Groupcast::Testing::Result::kFailedAuth
    1251              :                                                                : chip::Groupcast::Testing::Result::kNoAvailableKey);
    1252            0 :             testing.NotifyDelegate();
    1253              :         }
    1254              :     }
    1255              : 
    1256            9 :     if (!decrypted)
    1257              :     {
    1258            2 :         ChipLogError(Inet, "Failed to decrypt group message. Discarding everything");
    1259            2 :         return;
    1260              :     }
    1261            7 :     msg = std::move(msgCopy);
    1262              : 
    1263              :     // MCSP check
    1264            7 :     if (packetHeaderCopy.IsValidMCSPMsg())
    1265              :     {
    1266              :         // TODO: When MCSP Msg, create Secure Session instead of a Group session
    1267              : 
    1268              :         // TODO
    1269              :         // if (packetHeaderCopy.GetDestinationNodeId().Value() == ThisDeviceNodeID)
    1270              :         // {
    1271              :         //     MCSP processing..
    1272              :         // }
    1273              : 
    1274            0 :         return;
    1275              :     }
    1276              : 
    1277              :     // Group Messages should never send an Ack
    1278            7 :     if (payloadHeader.NeedsAck())
    1279              :     {
    1280            0 :         ChipLogError(Inet, "Unexpected ACK requested for group message");
    1281            0 :         return;
    1282              :     }
    1283              : 
    1284              :     // Handle Group message counter here spec 4.7.3
    1285              :     // spec 4.5.1.2 for msg counter
    1286            7 :     Transport::PeerMessageCounter * counter = nullptr;
    1287              : 
    1288            7 :     if (CHIP_NO_ERROR ==
    1289           21 :         gGroupPeerTable->FindOrAddPeer(groupContext.fabric_index, packetHeaderCopy.GetSourceNodeId().Value(),
    1290           14 :                                        packetHeaderCopy.IsSecureSessionControlMsg(), counter))
    1291              :     {
    1292            7 :         if (Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst == groupContext.security_policy)
    1293              :         {
    1294            7 :             err = counter->VerifyOrTrustFirstGroup(packetHeaderCopy.GetMessageCounter());
    1295              :         }
    1296              :         else
    1297              :         {
    1298              : 
    1299              :             // TODO support cache and sync with MCSP. Issue  #11689
    1300            0 :             ChipLogError(Inet, "Received Group Msg with key policy Cache and Sync, but MCSP is not implemented");
    1301            0 :             return;
    1302              : 
    1303              :             // cache and sync
    1304              :             // err = counter->VerifyGroup(packetHeaderCopy.GetMessageCounter());
    1305              :         }
    1306              : 
    1307           14 :         if (err != CHIP_NO_ERROR)
    1308              :         {
    1309            1 :             if (testing.IsEnabled() && testing.IsFabricUnderTest(groupContext.fabric_index))
    1310              :             {
    1311            0 :                 if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
    1312              :                 {
    1313            0 :                     testing.SetTestResult(chip::Groupcast::Testing::Result::kMessageReplay);
    1314              :                 }
    1315              :                 else
    1316              :                 {
    1317            0 :                     testing.SetTestResult(chip::Groupcast::Testing::Result::kGeneralError);
    1318              :                 }
    1319            0 :                 testing.NotifyDelegate();
    1320              :             }
    1321              :             // Exit now, since Group Messages don't have acks or responses of any kind.
    1322            1 :             ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
    1323            1 :             return;
    1324              :         }
    1325              :     }
    1326              :     else
    1327              :     {
    1328            0 :         if (testing.IsEnabled() && testing.IsFabricUnderTest(groupContext.fabric_index))
    1329              :         {
    1330            0 :             testing.SetTestResult(chip::Groupcast::Testing::Result::kGeneralError);
    1331            0 :             testing.NotifyDelegate();
    1332              :         }
    1333            0 :         ChipLogError(Inet,
    1334              :                      "Group Counter Tables full or invalid NodeId/FabricIndex after decryption of message, dropping everything");
    1335            0 :         return;
    1336              :     }
    1337              : 
    1338            6 :     counter->CommitGroup(packetHeaderCopy.GetMessageCounter());
    1339              : 
    1340            6 :     if (mCB != nullptr)
    1341              :     {
    1342              :         // TODO : When MCSP is done, clean up session creation logic
    1343            6 :         Transport::IncomingGroupSession groupSession(groupContext.group_id, groupContext.fabric_index,
    1344            6 :                                                      packetHeaderCopy.GetSourceNodeId().Value());
    1345              : 
    1346              :         MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kGroupMessage, &payloadHeader, &packetHeaderCopy,
    1347              :                                     &groupSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()),
    1348              :                                     messageTotalSize);
    1349              : 
    1350            6 :         CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeaderCopy, &groupSession, peerAddress, msg->Start(), msg->TotalLength());
    1351            6 :         SessionHandle session(groupSession);
    1352              : 
    1353            6 :         CountMessagesReceived(session, payloadHeader);
    1354            6 :         mCB->OnMessageReceived(packetHeaderCopy, payloadHeader, session, SessionMessageDelegate::DuplicateMessage::No,
    1355            6 :                                std::move(msg));
    1356            6 :     }
    1357              :     else
    1358              :     {
    1359            0 :         ChipLogError(Inet, "Received GROUP message was not processed.");
    1360              :     }
    1361           18 : }
    1362              : 
    1363            1 : Optional<SessionHandle> SessionManager::FindSecureSessionForNode(ScopedNodeId peerNodeId,
    1364              :                                                                  const Optional<Transport::SecureSession::Type> & type,
    1365              :                                                                  TransportPayloadCapability transportPayloadCapability)
    1366              : {
    1367            1 :     SecureSession * mrpSession = nullptr;
    1368              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1369            1 :     SecureSession * tcpSession = nullptr;
    1370              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1371              : 
    1372            1 :     mSecureSessions.ForEachSession([&peerNodeId, &type, &mrpSession,
    1373              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1374              :                                     &tcpSession,
    1375              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1376           15 :                                     &transportPayloadCapability](auto session) {
    1377            4 :         if (session->IsActiveSession() && session->GetPeer() == peerNodeId &&
    1378            2 :             (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
    1379              :         {
    1380            2 :             if (transportPayloadCapability == TransportPayloadCapability::kMRPOrTCPCompatiblePayload ||
    1381            2 :                 transportPayloadCapability == TransportPayloadCapability::kLargePayload)
    1382              :             {
    1383              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1384              :                 // Set up a TCP transport based session as standby
    1385            0 :                 if ((tcpSession == nullptr || tcpSession->GetLastPeerActivityTime() < session->GetLastPeerActivityTime()) &&
    1386            0 :                     !session->GetTCPConnection().IsNull())
    1387              :                 {
    1388            0 :                     tcpSession = session;
    1389              :                 }
    1390              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1391              :             }
    1392              : 
    1393            2 :             if ((mrpSession == nullptr) || (mrpSession->GetLastPeerActivityTime() < session->GetLastPeerActivityTime()))
    1394              :             {
    1395            2 :                 mrpSession = session;
    1396              :             }
    1397              :         }
    1398              : 
    1399            2 :         return Loop::Continue;
    1400              :     });
    1401              : 
    1402              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1403            1 :     if (transportPayloadCapability == TransportPayloadCapability::kLargePayload)
    1404              :     {
    1405            0 :         return tcpSession != nullptr ? MakeOptional<SessionHandle>(*tcpSession) : Optional<SessionHandle>::Missing();
    1406              :     }
    1407              : 
    1408            1 :     if (transportPayloadCapability == TransportPayloadCapability::kMRPOrTCPCompatiblePayload)
    1409              :     {
    1410              :         // If MRP-based session is available, use it.
    1411            0 :         if (mrpSession != nullptr)
    1412              :         {
    1413            0 :             return MakeOptional<SessionHandle>(*mrpSession);
    1414              :         }
    1415              : 
    1416              :         // Otherwise, look for a tcp-based session
    1417            0 :         if (tcpSession != nullptr)
    1418              :         {
    1419            0 :             return MakeOptional<SessionHandle>(*tcpSession);
    1420              :         }
    1421              : 
    1422            0 :         return Optional<SessionHandle>::Missing();
    1423              :     }
    1424              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1425              : 
    1426            1 :     return mrpSession != nullptr ? MakeOptional<SessionHandle>(*mrpSession) : Optional<SessionHandle>::Missing();
    1427              : }
    1428              : 
    1429              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
    1430            4 : void SessionManager::MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState & conn, CHIP_ERROR conErr)
    1431              : {
    1432              :     // Mark the corresponding secure sessions for eviction
    1433            4 :     mSecureSessions.ForEachSession([&](auto session) {
    1434            1 :         if (session->GetTCPConnection() == conn)
    1435              :         {
    1436            1 :             bool isActive = session->IsActiveSession();
    1437              : 
    1438            1 :             if (isActive)
    1439              :             {
    1440              :                 // Notify the SessionConnection delegate of the connection
    1441              :                 // closure before session eviction detaches holders and
    1442              :                 // releases exchanges.
    1443            0 :                 if (mConnDelegate != nullptr)
    1444              :                 {
    1445            0 :                     SessionHandle handle(*session);
    1446            0 :                     mConnDelegate->OnTCPConnectionClosed(conn, handle, conErr);
    1447            0 :                 }
    1448              :             }
    1449              : 
    1450              :             // Explicitly release the TCP connection handle to ensure the transport resource is reclaimed immediately.
    1451            1 :             session->ReleaseTCPConnection();
    1452              : 
    1453              :             // Mark session for eviction regardless of its current state (Active, Defunct, or Establishing).
    1454            1 :             session->MarkForEviction();
    1455              :         }
    1456              : 
    1457            1 :         return Loop::Continue;
    1458              :     });
    1459            4 : }
    1460              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
    1461              : 
    1462              : /**
    1463              :  * Provides a means to get diagnostic information such as number of sessions.
    1464              :  */
    1465            0 : [[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda)
    1466              : {
    1467            0 :     mSecureSessions.ForEachSession([&](auto session) {
    1468            0 :         SessionHandle handle(*session);
    1469            0 :         lambda(context, handle);
    1470            0 :         return Loop::Continue;
    1471            0 :     });
    1472            0 :     return CHIP_NO_ERROR;
    1473              : }
    1474              : 
    1475              : // Session handle parameter included here for future counting usage.
    1476        15086 : void SessionManager::CountMessagesReceived(const SessionHandle &, const PayloadHeader & payloadHeader)
    1477              : {
    1478        15086 :     if (payloadHeader.GetProtocolID() == Protocols::InteractionModel::Id)
    1479              :     {
    1480        12600 :         mMessageStats.interactionModelMessagesReceived++;
    1481              :     }
    1482        15086 : }
    1483              : 
    1484              : // Session handle parameter included here for future counting usage.
    1485        15182 : void SessionManager::CountMessagesSent(const SessionHandle &, const PayloadHeader & payloadHeader)
    1486              : {
    1487        15182 :     if (payloadHeader.GetProtocolID() == Protocols::InteractionModel::Id)
    1488              :     {
    1489        12655 :         mMessageStats.interactionModelMessagesSent++;
    1490              :     }
    1491        15182 : }
    1492              : 
    1493              : } // namespace chip
        

Generated by: LCOV version 2.0-1