Matter SDK Coverage Report
Current view: top level - transport - SessionManager.h (source / functions) Coverage Total Hit
Test: SHA:e98a48c2e59f85a25417956e1d105721433aa5d1 Lines: 52.9 % 85 45
Test Date: 2026-01-09 16:53:50 Functions: 80.6 % 31 25

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  * @file
      21              :  *   This file defines a secure transport layer which adds encryption to data
      22              :  *   sent over a transport.
      23              :  *
      24              :  */
      25              : 
      26              : #pragma once
      27              : 
      28              : #include <utility>
      29              : 
      30              : #include <credentials/FabricTable.h>
      31              : #include <crypto/RandUtils.h>
      32              : #include <crypto/SessionKeystore.h>
      33              : #include <inet/IPAddress.h>
      34              : #include <lib/core/CHIPCore.h>
      35              : #include <lib/core/CHIPPersistentStorageDelegate.h>
      36              : #include <lib/support/CodeUtils.h>
      37              : #include <lib/support/DLLUtil.h>
      38              : #include <messaging/ReliableMessageProtocolConfig.h>
      39              : #include <protocols/secure_channel/Constants.h>
      40              : #include <transport/CryptoContext.h>
      41              : #include <transport/GroupPeerMessageCounter.h>
      42              : #include <transport/GroupSession.h>
      43              : #include <transport/MessageCounterManagerInterface.h>
      44              : #include <transport/MessageStats.h>
      45              : #include <transport/SecureSessionTable.h>
      46              : #include <transport/Session.h>
      47              : #include <transport/SessionDelegate.h>
      48              : #include <transport/SessionHolder.h>
      49              : #include <transport/SessionMessageDelegate.h>
      50              : #include <transport/TransportMgr.h>
      51              : #include <transport/UnauthenticatedSessionTable.h>
      52              : #include <transport/raw/Base.h>
      53              : #include <transport/raw/PeerAddress.h>
      54              : #include <transport/raw/Tuple.h>
      55              : 
      56              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
      57              : #include <transport/SessionConnectionDelegate.h>
      58              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
      59              : 
      60              : namespace chip {
      61              : 
      62              : /*
      63              :  * This enum indicates whether a session needs to be established over a
      64              :  * suitable transport that meets certain payload size requirements for
      65              :  * transmitted messages.
      66              :  *
      67              :  */
      68              : enum class TransportPayloadCapability : uint8_t
      69              : {
      70              :     kMRPPayload,               // Transport requires the maximum payload size to fit within a single
      71              :                                // IPv6 packet(1280 bytes).
      72              :     kLargePayload,             // Transport needs to handle payloads larger than the single IPv6
      73              :                                // packet, as supported by MRP. The transport of choice, in this
      74              :                                // case, is TCP.
      75              :     kMRPOrTCPCompatiblePayload // This option provides the ability to use MRP
      76              :                                // as the preferred transport, but use a large
      77              :                                // payload transport if that is already
      78              :                                // available.
      79              : };
      80              : /**
      81              :  * @brief
      82              :  *  Tracks ownership of a encrypted packet buffer.
      83              :  *
      84              :  *  EncryptedPacketBufferHandle is a kind of PacketBufferHandle class and used to hold a packet buffer
      85              :  *  object whose payload has already been encrypted.
      86              :  */
      87              : class EncryptedPacketBufferHandle final : private System::PacketBufferHandle
      88              : {
      89              : public:
      90        15060 :     EncryptedPacketBufferHandle() {}
      91              :     EncryptedPacketBufferHandle(EncryptedPacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
      92              : 
      93        15096 :     void operator=(EncryptedPacketBufferHandle && aBuffer) { PacketBufferHandle::operator=(std::move(aBuffer)); }
      94              : 
      95              :     using System::PacketBufferHandle::IsNull;
      96              :     // Pass-through to HasChainedBuffer on our underlying buffer without
      97              :     // exposing operator->
      98              :     bool HasChainedBuffer() const { return (*this)->HasChainedBuffer(); }
      99              : 
     100              :     uint32_t GetMessageCounter() const;
     101              : 
     102              :     /**
     103              :      * Creates a copy of the data in this packet.
     104              :      *
     105              :      * Does NOT support chained buffers.
     106              :      *
     107              :      * @returns empty handle on allocation failure.
     108              :      */
     109            2 :     EncryptedPacketBufferHandle CloneData() { return EncryptedPacketBufferHandle(PacketBufferHandle::CloneData()); }
     110              : 
     111              : #ifdef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
     112              :     /**
     113              :      * Extracts the (unencrypted) packet header from this encrypted packet
     114              :      * buffer.  Returns error if a packet header cannot be extracted (e.g. if
     115              :      * there are not enough bytes in this packet buffer).  After this call the
     116              :      * buffer does not have a packet header.  This API is meant for
     117              :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
     118              :      * should not be defined normally.
     119              :      */
     120            2 :     CHIP_ERROR ExtractPacketHeader(PacketHeader & aPacketHeader) { return aPacketHeader.DecodeAndConsume(*this); }
     121              : 
     122              :     /**
     123              :      * Inserts a new (unencrypted) packet header in the encrypted packet buffer
     124              :      * based on the given PacketHeader.  This API is meant for
     125              :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
     126              :      * should not be defined normally.
     127              :      */
     128            2 :     CHIP_ERROR InsertPacketHeader(const PacketHeader & aPacketHeader) { return aPacketHeader.EncodeBeforeData(*this); }
     129              : #endif // CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
     130              : 
     131        15096 :     static EncryptedPacketBufferHandle MarkEncrypted(PacketBufferHandle && aBuffer)
     132              :     {
     133        15096 :         return EncryptedPacketBufferHandle(std::move(aBuffer));
     134              :     }
     135              : 
     136              :     /**
     137              :      * Get a handle to the data that allows mutating the bytes.  This should
     138              :      * only be used if absolutely necessary, because EncryptedPacketBufferHandle
     139              :      * represents a buffer that we want to resend as-is.
     140              :      */
     141        15126 :     PacketBufferHandle CastToWritable() const { return PacketBufferHandle::Retain(); }
     142              : 
     143              : private:
     144        15098 :     EncryptedPacketBufferHandle(PacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
     145              : };
     146              : 
     147              : class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTable::Delegate
     148              : {
     149              : public:
     150              :     SessionManager();
     151              :     ~SessionManager() override;
     152              : 
     153              :     /**
     154              :      * @brief
     155              :      *   This function takes the payload and returns an encrypted message which can be sent multiple times.
     156              :      *   Every successful call to this function MUST be followed by a send attempt with the prepared message.
     157              :      *
     158              :      * @details
     159              :      *   It does the following:
     160              :      *    1. Encrypt the msgBuf
     161              :      *    2. construct the packet header
     162              :      *    3. Encode the packet header and prepend it to message.
     163              :      *   Returns a encrypted message in encryptedMessage.
     164              :      */
     165              :     CHIP_ERROR PrepareMessage(const SessionHandle & session, PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf,
     166              :                               EncryptedPacketBufferHandle & encryptedMessage);
     167              : 
     168              :     /**
     169              :      * @brief
     170              :      *   Send a prepared message to a currently connected peer.
     171              :      */
     172              :     CHIP_ERROR SendPreparedMessage(const SessionHandle & session, const EncryptedPacketBufferHandle & preparedMessage);
     173              : 
     174              :     /// @brief Set the delegate for handling incoming messages. There can be only one message delegate (probably the
     175              :     /// ExchangeManager)
     176          863 :     void SetMessageDelegate(SessionMessageDelegate * cb) { mCB = cb; }
     177              : 
     178              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     179          422 :     void SetConnectionDelegate(SessionConnectionDelegate * cb) { mConnDelegate = cb; }
     180              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     181              : 
     182              :     // Test-only: create a session on the fly.
     183              :     CHIP_ERROR InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
     184              :                                             uint16_t peerSessionId, FabricIndex fabricIndex,
     185              :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role);
     186              :     CHIP_ERROR InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, uint16_t peerSessionId,
     187              :                                             NodeId localNodeId, NodeId peerNodeId, FabricIndex fabric,
     188              :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role,
     189              :                                             const CATValues & cats = CATValues{});
     190              : 
     191              :     /**
     192              :      * @brief
     193              :      *   Allocate a secure session and non-colliding session ID in the secure
     194              :      *   session table.
     195              :      *
     196              :      *   If we're either establishing or just finished establishing a session to a peer in either initiator or responder
     197              :      *   roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
     198              :      *   to a default-constructed ScopedNodeId().
     199              :      *
     200              :      * @return SessionHandle with a reference to a SecureSession, else NullOptional on failure
     201              :      */
     202              :     CHECK_RETURN_VALUE
     203              :     Optional<SessionHandle> AllocateSession(Transport::SecureSession::Type secureSessionType,
     204              :                                             const ScopedNodeId & sessionEvictionHint);
     205              : 
     206              :     /**
     207              :      *  A set of templated helper function that call a provided lambda
     208              :      *  on all sessions in the underlying session table that match the provided
     209              :      *  query criteria.
     210              :      *
     211              :      */
     212              : 
     213              :     /**
     214              :      * Call the provided lambda on sessions whose remote side match the provided ScopedNodeId.
     215              :      *
     216              :      */
     217              :     template <typename Function>
     218            9 :     void ForEachMatchingSession(const ScopedNodeId & node, Function && function)
     219              :     {
     220            9 :         mSecureSessions.ForEachSession([&](auto * session) {
     221           36 :             if (session->GetPeer() == node)
     222              :             {
     223            9 :                 function(session);
     224              :             }
     225              : 
     226           36 :             return Loop::Continue;
     227              :         });
     228            9 :     }
     229              : 
     230              :     /**
     231              :      * Call the provided lambda on sessions that match the provided fabric index.
     232              :      *
     233              :      */
     234              :     template <typename Function>
     235            2 :     void ForEachMatchingSession(FabricIndex fabricIndex, Function && function)
     236              :     {
     237            2 :         mSecureSessions.ForEachSession([&](auto * session) {
     238           16 :             if (session->GetFabricIndex() == fabricIndex)
     239              :             {
     240            6 :                 function(session);
     241              :             }
     242              : 
     243           16 :             return Loop::Continue;
     244              :         });
     245            2 :     }
     246              : 
     247              :     /**
     248              :      * Call the provided lambda on all sessions whose remote side match the logical fabric
     249              :      * associated with the provided ScopedNodeId and target the same logical remote node.
     250              :      *
     251              :      * *NOTE* This is identical in behavior to ForEachMatchingSession(const ScopedNodeId ..)
     252              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     253              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     254              :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     255              :      *        and each is assigned a unique fabric index.
     256              :      */
     257              :     template <typename Function>
     258            0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(const ScopedNodeId & node, Function && function)
     259              :     {
     260            0 :         Crypto::P256PublicKey targetPubKey;
     261              : 
     262            0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(node.GetFabricIndex());
     263            0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     264              : 
     265            0 :         auto err = targetFabric->FetchRootPubkey(targetPubKey);
     266            0 :         VerifyOrDie(err == CHIP_NO_ERROR);
     267              : 
     268            0 :         mSecureSessions.ForEachSession([&](auto * session) {
     269            0 :             Crypto::P256PublicKey comparePubKey;
     270              : 
     271              :             //
     272              :             // It's entirely possible to either come across a PASE session OR, a CASE session
     273              :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     274              :             // waiting for a Sigma1 message to arrive). Let's skip those.
     275              :             //
     276            0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     277              :             {
     278            0 :                 return Loop::Continue;
     279              :             }
     280              : 
     281            0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     282            0 :             VerifyOrDie(compareFabric != nullptr);
     283              : 
     284            0 :             err = compareFabric->FetchRootPubkey(comparePubKey);
     285            0 :             VerifyOrDie(err == CHIP_NO_ERROR);
     286              : 
     287            0 :             if (comparePubKey.Matches(targetPubKey) && targetFabric->GetFabricId() == compareFabric->GetFabricId() &&
     288            0 :                 session->GetPeerNodeId() == node.GetNodeId())
     289              :             {
     290            0 :                 function(session);
     291              :             }
     292              : 
     293            0 :             return Loop::Continue;
     294            0 :         });
     295              : 
     296            0 :         return CHIP_NO_ERROR;
     297            0 :     }
     298              : 
     299              :     /**
     300              :      * Call the provided lambda on all sessions that match the logical fabric
     301              :      * associated with the provided fabric index.
     302              :      *
     303              :      * *NOTE* This is identical in behavior to ForEachMatchingSession(FabricIndex ..)
     304              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     305              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     306              :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     307              :      *        and each is assigned a unique fabric index.
     308              :      */
     309              :     template <typename Function>
     310            0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(FabricIndex fabricIndex, Function && function)
     311              :     {
     312            0 :         Crypto::P256PublicKey targetPubKey;
     313              : 
     314            0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(fabricIndex);
     315            0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     316              : 
     317            0 :         SuccessOrDie(targetFabric->FetchRootPubkey(targetPubKey));
     318              : 
     319            0 :         mSecureSessions.ForEachSession([&](auto * session) {
     320            0 :             Crypto::P256PublicKey comparePubKey;
     321              : 
     322              :             //
     323              :             // It's entirely possible to either come across a PASE session OR, a CASE session
     324              :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     325              :             // waiting for a Sigma1 message to arrive). Let's skip those.
     326              :             //
     327            0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     328              :             {
     329            0 :                 return Loop::Continue;
     330              :             }
     331              : 
     332            0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     333            0 :             VerifyOrDie(compareFabric != nullptr);
     334              : 
     335            0 :             SuccessOrDie(compareFabric->FetchRootPubkey(comparePubKey));
     336              : 
     337            0 :             if (comparePubKey.Matches(targetPubKey) && targetFabric->GetFabricId() == compareFabric->GetFabricId())
     338              :             {
     339            0 :                 function(session);
     340              :             }
     341              : 
     342            0 :             return Loop::Continue;
     343            0 :         });
     344              : 
     345            0 :         return CHIP_NO_ERROR;
     346            0 :     }
     347              : 
     348              :     /**
     349              :      * Expire all sessions for a given peer, as identified by a specific fabric
     350              :      * index and node ID.
     351              :      */
     352              :     void ExpireAllSessions(const ScopedNodeId & node);
     353              : 
     354              :     /**
     355              :      * Expire all sessions associated with the given fabric index.
     356              :      *
     357              :      * *NOTE* This is generally all sessions for a given fabric _EXCEPT_ if there are multiple
     358              :      *        FabricInfo instances in the FabricTable that collide on the same logical fabric (i.e
     359              :      *        root public key + fabric ID tuple).  This can ONLY happen if multiple controller
     360              :      *        instances on the same fabric is permitted and each is assigned a unique fabric index.
     361              :      */
     362              :     void ExpireAllSessionsForFabric(FabricIndex fabricIndex);
     363              : 
     364              :     /**
     365              :      * Expire all sessions whose remote side matches the logical fabric
     366              :      * associated with the provided ScopedNodeId and target the same logical remote node.
     367              :      *
     368              :      * *NOTE* This is identical in behavior to ExpireAllSessions(const ScopedNodeId ..)
     369              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     370              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).  This can ONLY happen
     371              :      *        if multiple controller instances on the same fabric is permitted and each is assigned
     372              :      *        a unique fabric index.
     373              :      *
     374              :      */
     375              :     CHIP_ERROR ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node);
     376              : 
     377              :     /**
     378              :      * Expire all sessions whose remote side matches the logical fabric
     379              :      * associated with the provided fabric index.
     380              :      *
     381              :      * *NOTE* This is identical in behavior to ExpireAllSessExpireAllSessionsForFabricions(FabricIndex ..)
     382              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     383              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).  This can ONLY happen
     384              :      *        if multiple controller instances on the same fabric is permitted and each is assigned
     385              :      *        a unique fabric index.
     386              :      *
     387              :      */
     388              :     CHIP_ERROR ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex);
     389              : 
     390              :     void ExpireAllPASESessions();
     391              : 
     392              :     /**
     393              :      * Expire all secure sessions.  See documentation for Shutdown on when it's
     394              :      * appropriate to use this.
     395              :      */
     396              :     void ExpireAllSecureSessions();
     397              : 
     398              :     /**
     399              :      * @brief
     400              :      *   Marks all active sessions that match provided arguments as defunct.
     401              :      *
     402              :      * @param node    Scoped node ID of the active sessions we should mark as defunct.
     403              :      * @param type    Type of session we are looking to mark as defunct. If matching
     404              :      *                against all types of sessions is desired, NullOptional should
     405              :      *                be passed into type.
     406              :      */
     407              :     void MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type);
     408              : 
     409              :     /**
     410              :      * @brief
     411              :      *   Update all CASE sessions that match `node` with the provided transport peer address.
     412              :      *
     413              :      * @param node    Scoped node ID of the active sessions we want to update.
     414              :      * @param addr    Transport peer address that we want to update to.
     415              :      */
     416              :     void UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr);
     417              : 
     418              :     /**
     419              :      * @brief
     420              :      *   Return the System Layer pointer used by current SessionManager.
     421              :      */
     422        25358 :     System::Layer * SystemLayer() { return mSystemLayer; }
     423              : 
     424              :     /**
     425              :      * @brief
     426              :      *   Initialize a Secure Session Manager
     427              :      *
     428              :      * @param systemLayer           System layer to use
     429              :      * @param transportMgr          Transport to use
     430              :      * @param messageCounterManager The message counter manager
     431              :      * @param storageDelegate       Persistent storage implementation
     432              :      * @param fabricTable           Fabric table to hold information about joined fabrics
     433              :      * @param sessionKeystore       Session keystore for management of symmetric encryption keys
     434              :      */
     435              :     CHIP_ERROR Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
     436              :                     Transport::MessageCounterManagerInterface * messageCounterManager,
     437              :                     chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
     438              :                     Crypto::SessionKeystore & sessionKeystore);
     439              : 
     440              :     /**
     441              :      * @brief
     442              :      *  Shutdown the Secure Session Manager. This terminates this instance
     443              :      *  of the object and reset it's state.
     444              :      *
     445              :      * The proper order of shutdown for SessionManager is as follows:
     446              :      *
     447              :      * 1) Call ExpireAllSecureSessions() on the SessionManager, and ensure that any unauthenticated
     448              :      *    sessions (e.g. CASEServer and CASESessionManager instances, or anything that does PASE
     449              :      *    handshakes) are released.
     450              :      * 2) Shut down the exchange manager, so that it's no longer referencing
     451              :      *    the to-be-shut-down SessionManager.
     452              :      * 3) Shut down the SessionManager.
     453              :      */
     454              :     void Shutdown();
     455              : 
     456              :     /**
     457              :      * @brief Notification that a fabric was removed.
     458              :      */
     459              :     void FabricRemoved(FabricIndex fabricIndex);
     460              : 
     461              :     TransportMgrBase * GetTransportManager() const { return mTransportMgr; }
     462            1 :     Transport::SecureSessionTable & GetSecureSessions() { return mSecureSessions; }
     463              : 
     464              :     /**
     465              :      * @brief
     466              :      *   Handle received secure message. Implements TransportMgrDelegate
     467              :      *
     468              :      * @param source    the source address of the package
     469              :      * @param msgBuf    the buffer containing a full CHIP message (except for the optional length field).
     470              :      * @param ctxt      pointer to additional context on the underlying transport. For TCP, it is a pointer
     471              :      *                  to the underlying connection object.
     472              :      */
     473              :     void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf,
     474              :                            Transport::MessageTransportContext * ctxt = nullptr) override;
     475              : 
     476              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     477              :     CHIP_ERROR TCPConnect(const Transport::PeerAddress & peerAddress, Transport::AppTCPConnectionCallbackCtxt * appState,
     478              :                           Transport::ActiveTCPConnectionHandle & peerConnState);
     479              : 
     480              :     void HandleConnectionReceived(Transport::ActiveTCPConnectionState & conn) override;
     481              : 
     482              :     void HandleConnectionAttemptComplete(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr) override;
     483              : 
     484              :     void HandleConnectionClosed(Transport::ActiveTCPConnectionState & conn, CHIP_ERROR conErr) override;
     485              : 
     486              :     // Functors for callbacks into higher layers
     487              :     using OnTCPConnectionReceivedCallback = void (*)(Transport::ActiveTCPConnectionHandle & conn);
     488              : 
     489              :     using OnTCPConnectionCompleteCallback = void (*)(Transport::ActiveTCPConnectionHandle & conn, CHIP_ERROR conErr);
     490              : 
     491              :     using OnTCPConnectionClosedCallback = void (*)(Transport::ActiveTCPConnectionState & conn, CHIP_ERROR conErr);
     492              : 
     493              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     494              : 
     495           27 :     Optional<SessionHandle> CreateUnauthenticatedSession(const Transport::PeerAddress & peerAddress,
     496              :                                                          const ReliableMessageProtocolConfig & config)
     497              :     {
     498              :         // Allocate ephemeralInitiatorNodeID in Operational Node ID range
     499              :         NodeId ephemeralInitiatorNodeID;
     500              :         do
     501              :         {
     502           27 :             ephemeralInitiatorNodeID = static_cast<NodeId>(Crypto::GetRandU64());
     503           27 :         } while (!IsOperationalNodeId(ephemeralInitiatorNodeID));
     504           27 :         return mUnauthenticatedSessions.AllocInitiator(ephemeralInitiatorNodeID, peerAddress, config);
     505              :     }
     506              : 
     507              :     //
     508              :     // Find an existing secure session given a peer's scoped NodeId and a type of session to match against.
     509              :     // If matching against all types of sessions is desired, NullOptional should be passed into type.
     510              :     //
     511              :     // If a valid session is found, an Optional<SessionHandle> with the value set to the SessionHandle of the session
     512              :     // is returned. Otherwise, an Optional<SessionHandle> with no value set is returned.
     513              :     //
     514              :     //
     515              :     Optional<SessionHandle>
     516              :     FindSecureSessionForNode(ScopedNodeId peerNodeId, const Optional<Transport::SecureSession::Type> & type = NullOptional,
     517              :                              TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
     518              : 
     519              :     using SessionHandleCallback = bool (*)(void * context, SessionHandle & sessionHandle);
     520              :     CHIP_ERROR ForEachSessionHandle(void * context, SessionHandleCallback callback);
     521              : 
     522              :     //// FabricTable::Delegate Implementation ////
     523            7 :     void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
     524              :     {
     525              :         (void) fabricTable;
     526            7 :         this->FabricRemoved(fabricIndex);
     527            7 :     }
     528              : 
     529        29742 :     FabricTable * GetFabricTable() const { return mFabricTable; }
     530              : 
     531          169 :     Crypto::SessionKeystore * GetSessionKeystore() const { return mSessionKeystore; }
     532              : 
     533            2 :     MessageStats GetMessageStats() const { return mMessageStats; }
     534              : 
     535              : private:
     536              :     /**
     537              :      *    The State of a secure transport object.
     538              :      */
     539              :     enum class State
     540              :     {
     541              :         kNotReady,    /**< State before initialization. */
     542              :         kInitialized, /**< State when the object is ready connect to other peers. */
     543              :     };
     544              : 
     545              :     enum class EncryptionState
     546              :     {
     547              :         kPayloadIsEncrypted,
     548              :         kPayloadIsUnencrypted,
     549              :     };
     550              : 
     551              :     System::Layer * mSystemLayer               = nullptr;
     552              :     FabricTable * mFabricTable                 = nullptr;
     553              :     Crypto::SessionKeystore * mSessionKeystore = nullptr;
     554              :     Transport::UnauthenticatedSessionTable<CHIP_CONFIG_UNAUTHENTICATED_CONNECTION_POOL_SIZE> mUnauthenticatedSessions;
     555              :     Transport::SecureSessionTable mSecureSessions;
     556              :     State mState; // < Initialization state of the object
     557              :     chip::Transport::GroupOutgoingCounters mGroupClientCounter;
     558              :     MessageStats mMessageStats;
     559              : 
     560              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     561              :     OnTCPConnectionReceivedCallback mConnReceivedCb = nullptr;
     562              :     OnTCPConnectionCompleteCallback mConnCompleteCb = nullptr;
     563              :     OnTCPConnectionClosedCallback mConnClosedCb     = nullptr;
     564              : 
     565              :     // Hold the TCPConnection callback context for the receiver application in the SessionManager.
     566              :     // On receipt of a connection from a peer, the SessionManager
     567              :     Transport::AppTCPConnectionCallbackCtxt * mServerTCPConnCbCtxt = nullptr;
     568              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     569              : 
     570              :     SessionMessageDelegate * mCB = nullptr;
     571              : 
     572              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     573              :     SessionConnectionDelegate * mConnDelegate = nullptr;
     574              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     575              : 
     576              :     TransportMgrBase * mTransportMgr                                   = nullptr;
     577              :     Transport::MessageCounterManagerInterface * mMessageCounterManager = nullptr;
     578              : 
     579              :     GlobalUnencryptedMessageCounter mGlobalUnencryptedMessageCounter;
     580              : 
     581              :     /**
     582              :      * @brief Parse, decrypt, validate, and dispatch a secure unicast message.
     583              :      *
     584              :      * @param[in] partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     585              :      * If the message decrypts successfully, this will be filled with a fully decoded PacketHeader.
     586              :      * @param[in] peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     587              :      * @param msg The full message buffer, including header fields.
     588              :      * @param ctxt The pointer to additional context on the underlying transport. For TCP, it is a pointer
     589              :      *             to the underlying connection object.
     590              :      */
     591              :     void SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     592              :                                       System::PacketBufferHandle && msg, Transport::MessageTransportContext * ctxt = nullptr);
     593              : 
     594              :     /**
     595              :      * @brief Parse, decrypt, validate, and dispatch a secure group message.
     596              :      *
     597              :      * @param partialPacketHeader The partial PacketHeader of the message once processed with DecodeFixed.
     598              :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     599              :      * @param msg The full message buffer, including header fields.
     600              :      */
     601              :     void SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     602              :                                     System::PacketBufferHandle && msg);
     603              : 
     604              :     /**
     605              :      * @brief Parse, decrypt, validate, and dispatch an unsecured message.
     606              :      *
     607              :      * @param partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     608              :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     609              :      * @param msg The full message buffer, including header fields.
     610              :      * @param ctxt The pointer to additional context on the underlying transport. For TCP, it is a pointer
     611              :      *             to the underlying connection object.
     612              :      */
     613              :     void UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     614              :                                         System::PacketBufferHandle && msg, Transport::MessageTransportContext * ctxt = nullptr);
     615              : 
     616              :     void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source);
     617              : 
     618              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     619              :     void MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState & conn, CHIP_ERROR conErr);
     620              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     621              : 
     622        15098 :     static bool IsControlMessage(PayloadHeader & payloadHeader)
     623              :     {
     624        30196 :         return payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq) ||
     625        30196 :             payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncRsp);
     626              :     }
     627              : 
     628              :     void CountMessagesReceived(const SessionHandle & sessionHandle, const PayloadHeader & payloadHeader);
     629              :     void CountMessagesSent(const SessionHandle & sessionHandle, const PayloadHeader & payloadHeader);
     630              : };
     631              : 
     632              : namespace MessagePacketBuffer {
     633              : /**
     634              :  * Maximum size of a message footer, in bytes.
     635              :  */
     636              : inline constexpr uint16_t kMaxFooterSize = kMaxTagLen;
     637              : 
     638              : /**
     639              :  * Allocates a packet buffer with space for message headers and footers.
     640              :  *
     641              :  *  Fails and returns \c nullptr if no memory is available, or if the size requested is too large.
     642              :  *
     643              :  *  @param[in]  aAvailableSize  Minimum number of octets to for application data.
     644              :  *
     645              :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     646              :  */
     647         2500 : inline System::PacketBufferHandle New(size_t aAvailableSize)
     648              : {
     649              :     static_assert(System::PacketBuffer::kMaxSize > kMaxFooterSize, "inadequate capacity");
     650         2500 :     if (aAvailableSize > System::PacketBuffer::kMaxSize - kMaxFooterSize)
     651              :     {
     652            0 :         return System::PacketBufferHandle();
     653              :     }
     654         2500 :     return System::PacketBufferHandle::New(aAvailableSize + kMaxFooterSize);
     655              : }
     656              : 
     657              : /**
     658              :  * Allocates a packet buffer with initial contents.
     659              :  *
     660              :  *  @param[in]  aData           Initial buffer contents.
     661              :  *  @param[in]  aDataSize       Size of initial buffer contents.
     662              :  *
     663              :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     664              :  */
     665          127 : inline System::PacketBufferHandle NewWithData(const void * aData, size_t aDataSize)
     666              : {
     667          127 :     return System::PacketBufferHandle::NewWithData(aData, aDataSize, kMaxFooterSize);
     668              : }
     669              : 
     670              : /**
     671              :  * Check whether a packet buffer has enough space for a message footer.
     672              :  *
     673              :  * @returns true if there is space, false otherwise.
     674              :  */
     675            2 : inline bool HasFooterSpace(const System::PacketBufferHandle & aBuffer)
     676              : {
     677            2 :     return aBuffer->AvailableDataLength() >= kMaxFooterSize;
     678              : }
     679              : 
     680              : } // namespace MessagePacketBuffer
     681              : 
     682              : } // namespace chip
        

Generated by: LCOV version 2.0-1