Matter SDK Coverage Report
Current view: top level - transport - SessionManager.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 41.5 % 82 34
Test Date: 2025-01-17 19:00:11 Functions: 69.2 % 26 18

            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/SecureSessionTable.h>
      45              : #include <transport/Session.h>
      46              : #include <transport/SessionDelegate.h>
      47              : #include <transport/SessionHolder.h>
      48              : #include <transport/SessionMessageDelegate.h>
      49              : #include <transport/TransportMgr.h>
      50              : #include <transport/UnauthenticatedSessionTable.h>
      51              : #include <transport/raw/Base.h>
      52              : #include <transport/raw/PeerAddress.h>
      53              : #include <transport/raw/Tuple.h>
      54              : 
      55              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
      56              : #include <transport/SessionConnectionDelegate.h>
      57              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
      58              : 
      59              : namespace chip {
      60              : 
      61              : /*
      62              :  * This enum indicates whether a session needs to be established over a
      63              :  * suitable transport that meets certain payload size requirements for
      64              :  * transmitted messages.
      65              :  *
      66              :  */
      67              : enum class TransportPayloadCapability : uint8_t
      68              : {
      69              :     kMRPPayload,               // Transport requires the maximum payload size to fit within a single
      70              :                                // IPv6 packet(1280 bytes).
      71              :     kLargePayload,             // Transport needs to handle payloads larger than the single IPv6
      72              :                                // packet, as supported by MRP. The transport of choice, in this
      73              :                                // case, is TCP.
      74              :     kMRPOrTCPCompatiblePayload // This option provides the ability to use MRP
      75              :                                // as the preferred transport, but use a large
      76              :                                // payload transport if that is already
      77              :                                // available.
      78              : };
      79              : /**
      80              :  * @brief
      81              :  *  Tracks ownership of a encrypted packet buffer.
      82              :  *
      83              :  *  EncryptedPacketBufferHandle is a kind of PacketBufferHandle class and used to hold a packet buffer
      84              :  *  object whose payload has already been encrypted.
      85              :  */
      86              : class EncryptedPacketBufferHandle final : private System::PacketBufferHandle
      87              : {
      88              : public:
      89         9778 :     EncryptedPacketBufferHandle() {}
      90              :     EncryptedPacketBufferHandle(EncryptedPacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
      91              : 
      92         9823 :     void operator=(EncryptedPacketBufferHandle && aBuffer) { PacketBufferHandle::operator=(std::move(aBuffer)); }
      93              : 
      94              :     using System::PacketBufferHandle::IsNull;
      95              :     // Pass-through to HasChainedBuffer on our underlying buffer without
      96              :     // exposing operator->
      97              :     bool HasChainedBuffer() const { return (*this)->HasChainedBuffer(); }
      98              : 
      99              :     uint32_t GetMessageCounter() const;
     100              : 
     101              :     /**
     102              :      * Creates a copy of the data in this packet.
     103              :      *
     104              :      * Does NOT support chained buffers.
     105              :      *
     106              :      * @returns empty handle on allocation failure.
     107              :      */
     108              :     EncryptedPacketBufferHandle CloneData() { return EncryptedPacketBufferHandle(PacketBufferHandle::CloneData()); }
     109              : 
     110              : #ifdef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
     111              :     /**
     112              :      * Extracts the (unencrypted) packet header from this encrypted packet
     113              :      * buffer.  Returns error if a packet header cannot be extracted (e.g. if
     114              :      * there are not enough bytes in this packet buffer).  After this call the
     115              :      * buffer does not have a packet header.  This API is meant for
     116              :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
     117              :      * should not be defined normally.
     118              :      */
     119              :     CHIP_ERROR ExtractPacketHeader(PacketHeader & aPacketHeader) { return aPacketHeader.DecodeAndConsume(*this); }
     120              : 
     121              :     /**
     122              :      * Inserts a new (unencrypted) packet header in the encrypted packet buffer
     123              :      * based on the given PacketHeader.  This API is meant for
     124              :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
     125              :      * should not be defined normally.
     126              :      */
     127              :     CHIP_ERROR InsertPacketHeader(const PacketHeader & aPacketHeader) { return aPacketHeader.EncodeBeforeData(*this); }
     128              : #endif // CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
     129              : 
     130         9823 :     static EncryptedPacketBufferHandle MarkEncrypted(PacketBufferHandle && aBuffer)
     131              :     {
     132         9823 :         return EncryptedPacketBufferHandle(std::move(aBuffer));
     133              :     }
     134              : 
     135              :     /**
     136              :      * Get a handle to the data that allows mutating the bytes.  This should
     137              :      * only be used if absolutely necessary, because EncryptedPacketBufferHandle
     138              :      * represents a buffer that we want to resend as-is.
     139              :      */
     140         9857 :     PacketBufferHandle CastToWritable() const { return PacketBufferHandle::Retain(); }
     141              : 
     142              : private:
     143         9777 :     EncryptedPacketBufferHandle(PacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
     144              : };
     145              : 
     146              : class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTable::Delegate
     147              : {
     148              : public:
     149              :     SessionManager();
     150              :     ~SessionManager() override;
     151              : 
     152              :     /**
     153              :      * @brief
     154              :      *   This function takes the payload and returns an encrypted message which can be sent multiple times.
     155              :      *
     156              :      * @details
     157              :      *   It does the following:
     158              :      *    1. Encrypt the msgBuf
     159              :      *    2. construct the packet header
     160              :      *    3. Encode the packet header and prepend it to message.
     161              :      *   Returns a encrypted message in encryptedMessage.
     162              :      */
     163              :     CHIP_ERROR PrepareMessage(const SessionHandle & session, PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf,
     164              :                               EncryptedPacketBufferHandle & encryptedMessage);
     165              : 
     166              :     /**
     167              :      * @brief
     168              :      *   Send a prepared message to a currently connected peer.
     169              :      */
     170              :     CHIP_ERROR SendPreparedMessage(const SessionHandle & session, const EncryptedPacketBufferHandle & preparedMessage);
     171              : 
     172              :     /// @brief Set the delegate for handling incoming messages. There can be only one message delegate (probably the
     173              :     /// ExchangeManager)
     174           98 :     void SetMessageDelegate(SessionMessageDelegate * cb) { mCB = cb; }
     175              : 
     176              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     177          345 :     void SetConnectionDelegate(SessionConnectionDelegate * cb) { mConnDelegate = cb; }
     178              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     179              : 
     180              :     // Test-only: create a session on the fly.
     181              :     CHIP_ERROR InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
     182              :                                             uint16_t peerSessionId, FabricIndex fabricIndex,
     183              :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role);
     184              :     CHIP_ERROR InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, uint16_t peerSessionId,
     185              :                                             NodeId localNodeId, NodeId peerNodeId, FabricIndex fabric,
     186              :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role,
     187              :                                             const CATValues & cats = CATValues{});
     188              : 
     189              :     /**
     190              :      * @brief
     191              :      *   Allocate a secure session and non-colliding session ID in the secure
     192              :      *   session table.
     193              :      *
     194              :      *   If we're either establishing or just finished establishing a session to a peer in either initiator or responder
     195              :      *   roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
     196              :      *   to a default-constructed ScopedNodeId().
     197              :      *
     198              :      * @return SessionHandle with a reference to a SecureSession, else NullOptional on failure
     199              :      */
     200              :     CHECK_RETURN_VALUE
     201              :     Optional<SessionHandle> AllocateSession(Transport::SecureSession::Type secureSessionType,
     202              :                                             const ScopedNodeId & sessionEvictionHint);
     203              : 
     204              :     /**
     205              :      *  A set of templated helper function that call a provided lambda
     206              :      *  on all sessions in the underlying session table that match the provided
     207              :      *  query criteria.
     208              :      *
     209              :      */
     210              : 
     211              :     /**
     212              :      * Call the provided lambda on sessions whose remote side match the provided ScopedNodeId.
     213              :      *
     214              :      */
     215              :     template <typename Function>
     216            7 :     void ForEachMatchingSession(const ScopedNodeId & node, Function && function)
     217              :     {
     218            7 :         mSecureSessions.ForEachSession([&](auto * session) {
     219           28 :             if (session->GetPeer() == node)
     220              :             {
     221            7 :                 function(session);
     222              :             }
     223              : 
     224           28 :             return Loop::Continue;
     225              :         });
     226            7 :     }
     227              : 
     228              :     /**
     229              :      * Call the provided lambda on sessions that match the provided fabric index.
     230              :      *
     231              :      */
     232              :     template <typename Function>
     233            2 :     void ForEachMatchingSession(FabricIndex fabricIndex, Function && function)
     234              :     {
     235            2 :         mSecureSessions.ForEachSession([&](auto * session) {
     236           16 :             if (session->GetFabricIndex() == fabricIndex)
     237              :             {
     238            6 :                 function(session);
     239              :             }
     240              : 
     241           16 :             return Loop::Continue;
     242              :         });
     243            2 :     }
     244              : 
     245              :     /**
     246              :      * Call the provided lambda on all sessions whose remote side match the logical fabric
     247              :      * associated with the provided ScopedNodeId and target the same logical remote node.
     248              :      *
     249              :      * *NOTE* This is identical in behavior to ForEachMatchingSession(const ScopedNodeId ..)
     250              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     251              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     252              :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     253              :      *        and each is assigned a unique fabric index.
     254              :      */
     255              :     template <typename Function>
     256            0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(const ScopedNodeId & node, Function && function)
     257              :     {
     258            0 :         Crypto::P256PublicKey targetPubKey;
     259              : 
     260            0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(node.GetFabricIndex());
     261            0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     262              : 
     263            0 :         auto err = targetFabric->FetchRootPubkey(targetPubKey);
     264            0 :         VerifyOrDie(err == CHIP_NO_ERROR);
     265              : 
     266            0 :         mSecureSessions.ForEachSession([&](auto * session) {
     267            0 :             Crypto::P256PublicKey comparePubKey;
     268              : 
     269              :             //
     270              :             // It's entirely possible to either come across a PASE session OR, a CASE session
     271              :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     272              :             // waiting for a Sigma1 message to arrive). Let's skip those.
     273              :             //
     274            0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     275              :             {
     276            0 :                 return Loop::Continue;
     277              :             }
     278              : 
     279            0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     280            0 :             VerifyOrDie(compareFabric != nullptr);
     281              : 
     282            0 :             err = compareFabric->FetchRootPubkey(comparePubKey);
     283            0 :             VerifyOrDie(err == CHIP_NO_ERROR);
     284              : 
     285            0 :             if (comparePubKey.Matches(targetPubKey) && targetFabric->GetFabricId() == compareFabric->GetFabricId() &&
     286            0 :                 session->GetPeerNodeId() == node.GetNodeId())
     287              :             {
     288            0 :                 function(session);
     289              :             }
     290              : 
     291            0 :             return Loop::Continue;
     292            0 :         });
     293              : 
     294            0 :         return CHIP_NO_ERROR;
     295            0 :     }
     296              : 
     297              :     /**
     298              :      * Call the provided lambda on all sessions that match the logical fabric
     299              :      * associated with the provided fabric index.
     300              :      *
     301              :      * *NOTE* This is identical in behavior to ForEachMatchingSession(FabricIndex ..)
     302              :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     303              :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     304              :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     305              :      *        and each is assigned a unique fabric index.
     306              :      */
     307              :     template <typename Function>
     308            0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(FabricIndex fabricIndex, Function && function)
     309              :     {
     310            0 :         Crypto::P256PublicKey targetPubKey;
     311              : 
     312            0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(fabricIndex);
     313            0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     314              : 
     315            0 :         auto err = targetFabric->FetchRootPubkey(targetPubKey);
     316            0 :         VerifyOrDie(err == CHIP_NO_ERROR);
     317              : 
     318            0 :         mSecureSessions.ForEachSession([&](auto * session) {
     319            0 :             Crypto::P256PublicKey comparePubKey;
     320              : 
     321              :             //
     322              :             // It's entirely possible to either come across a PASE session OR, a CASE session
     323              :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     324              :             // waiting for a Sigma1 message to arrive). Let's skip those.
     325              :             //
     326            0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     327              :             {
     328            0 :                 return Loop::Continue;
     329              :             }
     330              : 
     331            0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     332            0 :             VerifyOrDie(compareFabric != nullptr);
     333              : 
     334            0 :             err = compareFabric->FetchRootPubkey(comparePubKey);
     335            0 :             VerifyOrDie(err == CHIP_NO_ERROR);
     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        17853 :     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              :     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::ActiveTCPConnectionState ** peerConnState);
     479              : 
     480              :     CHIP_ERROR TCPDisconnect(const Transport::PeerAddress & peerAddress);
     481              : 
     482              :     void TCPDisconnect(Transport::ActiveTCPConnectionState * conn, bool shouldAbort = 0);
     483              : 
     484              :     void HandleConnectionReceived(Transport::ActiveTCPConnectionState * conn) override;
     485              : 
     486              :     void HandleConnectionAttemptComplete(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr) override;
     487              : 
     488              :     void HandleConnectionClosed(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr) override;
     489              : 
     490              :     // Functors for callbacks into higher layers
     491              :     using OnTCPConnectionReceivedCallback = void (*)(Transport::ActiveTCPConnectionState * conn);
     492              : 
     493              :     using OnTCPConnectionCompleteCallback = void (*)(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr);
     494              : 
     495              :     using OnTCPConnectionClosedCallback = void (*)(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr);
     496              : 
     497              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     498              : 
     499            0 :     Optional<SessionHandle> CreateUnauthenticatedSession(const Transport::PeerAddress & peerAddress,
     500              :                                                          const ReliableMessageProtocolConfig & config)
     501              :     {
     502              :         // Allocate ephemeralInitiatorNodeID in Operational Node ID range
     503              :         NodeId ephemeralInitiatorNodeID;
     504              :         do
     505              :         {
     506            0 :             ephemeralInitiatorNodeID = static_cast<NodeId>(Crypto::GetRandU64());
     507            0 :         } while (!IsOperationalNodeId(ephemeralInitiatorNodeID));
     508            0 :         return mUnauthenticatedSessions.AllocInitiator(ephemeralInitiatorNodeID, peerAddress, config);
     509              :     }
     510              : 
     511              :     //
     512              :     // Find an existing secure session given a peer's scoped NodeId and a type of session to match against.
     513              :     // If matching against all types of sessions is desired, NullOptional should be passed into type.
     514              :     //
     515              :     // If a valid session is found, an Optional<SessionHandle> with the value set to the SessionHandle of the session
     516              :     // is returned. Otherwise, an Optional<SessionHandle> with no value set is returned.
     517              :     //
     518              :     //
     519              :     Optional<SessionHandle>
     520              :     FindSecureSessionForNode(ScopedNodeId peerNodeId, const Optional<Transport::SecureSession::Type> & type = NullOptional,
     521              :                              TransportPayloadCapability transportPayloadCapability = TransportPayloadCapability::kMRPPayload);
     522              : 
     523              :     using SessionHandleCallback = bool (*)(void * context, SessionHandle & sessionHandle);
     524              :     CHIP_ERROR ForEachSessionHandle(void * context, SessionHandleCallback callback);
     525              : 
     526              :     //// FabricTable::Delegate Implementation ////
     527            5 :     void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
     528              :     {
     529              :         (void) fabricTable;
     530            5 :         this->FabricRemoved(fabricIndex);
     531            5 :     }
     532              : 
     533        19232 :     FabricTable * GetFabricTable() const { return mFabricTable; }
     534              : 
     535          149 :     Crypto::SessionKeystore * GetSessionKeystore() const { return mSessionKeystore; }
     536              : 
     537              : private:
     538              :     /**
     539              :      *    The State of a secure transport object.
     540              :      */
     541              :     enum class State
     542              :     {
     543              :         kNotReady,    /**< State before initialization. */
     544              :         kInitialized, /**< State when the object is ready connect to other peers. */
     545              :     };
     546              : 
     547              :     enum class EncryptionState
     548              :     {
     549              :         kPayloadIsEncrypted,
     550              :         kPayloadIsUnencrypted,
     551              :     };
     552              : 
     553              :     System::Layer * mSystemLayer               = nullptr;
     554              :     FabricTable * mFabricTable                 = nullptr;
     555              :     Crypto::SessionKeystore * mSessionKeystore = nullptr;
     556              :     Transport::UnauthenticatedSessionTable<CHIP_CONFIG_UNAUTHENTICATED_CONNECTION_POOL_SIZE> mUnauthenticatedSessions;
     557              :     Transport::SecureSessionTable mSecureSessions;
     558              :     State mState; // < Initialization state of the object
     559              :     chip::Transport::GroupOutgoingCounters mGroupClientCounter;
     560              : 
     561              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     562              :     OnTCPConnectionReceivedCallback mConnReceivedCb = nullptr;
     563              :     OnTCPConnectionCompleteCallback mConnCompleteCb = nullptr;
     564              :     OnTCPConnectionClosedCallback mConnClosedCb     = nullptr;
     565              : 
     566              :     // Hold the TCPConnection callback context for the receiver application in the SessionManager.
     567              :     // On receipt of a connection from a peer, the SessionManager
     568              :     Transport::AppTCPConnectionCallbackCtxt * mServerTCPConnCbCtxt = nullptr;
     569              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     570              : 
     571              :     SessionMessageDelegate * mCB = nullptr;
     572              : 
     573              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     574              :     SessionConnectionDelegate * mConnDelegate = nullptr;
     575              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     576              : 
     577              :     TransportMgrBase * mTransportMgr                                   = nullptr;
     578              :     Transport::MessageCounterManagerInterface * mMessageCounterManager = nullptr;
     579              : 
     580              :     GlobalUnencryptedMessageCounter mGlobalUnencryptedMessageCounter;
     581              : 
     582              :     /**
     583              :      * @brief Parse, decrypt, validate, and dispatch a secure unicast message.
     584              :      *
     585              :      * @param[in] partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     586              :      * If the message decrypts successfully, this will be filled with a fully decoded PacketHeader.
     587              :      * @param[in] peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     588              :      * @param msg The full message buffer, including header fields.
     589              :      * @param ctxt The pointer to additional context on the underlying transport. For TCP, it is a pointer
     590              :      *             to the underlying connection object.
     591              :      */
     592              :     void SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     593              :                                       System::PacketBufferHandle && msg, Transport::MessageTransportContext * ctxt = nullptr);
     594              : 
     595              :     /**
     596              :      * @brief Parse, decrypt, validate, and dispatch a secure group message.
     597              :      *
     598              :      * @param partialPacketHeader The partial PacketHeader of the message once processed with DecodeFixed.
     599              :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     600              :      * @param msg The full message buffer, including header fields.
     601              :      */
     602              :     void SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     603              :                                     System::PacketBufferHandle && msg);
     604              : 
     605              :     /**
     606              :      * @brief Parse, decrypt, validate, and dispatch an unsecured message.
     607              :      *
     608              :      * @param partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     609              :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     610              :      * @param msg The full message buffer, including header fields.
     611              :      * @param ctxt The pointer to additional context on the underlying transport. For TCP, it is a pointer
     612              :      *             to the underlying connection object.
     613              :      */
     614              :     void UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     615              :                                         System::PacketBufferHandle && msg, Transport::MessageTransportContext * ctxt = nullptr);
     616              : 
     617              :     void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source);
     618              : 
     619              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     620              :     void MarkSecureSessionOverTCPForEviction(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr);
     621              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     622              : 
     623         9825 :     static bool IsControlMessage(PayloadHeader & payloadHeader)
     624              :     {
     625        19650 :         return payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq) ||
     626        19650 :             payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncRsp);
     627              :     }
     628              : };
     629              : 
     630              : namespace MessagePacketBuffer {
     631              : /**
     632              :  * Maximum size of a message footer, in bytes.
     633              :  */
     634              : inline constexpr uint16_t kMaxFooterSize = kMaxTagLen;
     635              : 
     636              : /**
     637              :  * Allocates a packet buffer with space for message headers and footers.
     638              :  *
     639              :  *  Fails and returns \c nullptr if no memory is available, or if the size requested is too large.
     640              :  *
     641              :  *  @param[in]  aAvailableSize  Minimum number of octets to for application data.
     642              :  *
     643              :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     644              :  */
     645         1631 : inline System::PacketBufferHandle New(size_t aAvailableSize)
     646              : {
     647              :     static_assert(System::PacketBuffer::kMaxSize > kMaxFooterSize, "inadequate capacity");
     648         1631 :     if (aAvailableSize > System::PacketBuffer::kMaxSize - kMaxFooterSize)
     649              :     {
     650            0 :         return System::PacketBufferHandle();
     651              :     }
     652         1631 :     return System::PacketBufferHandle::New(aAvailableSize + kMaxFooterSize);
     653              : }
     654              : 
     655              : /**
     656              :  * Allocates a packet buffer with initial contents.
     657              :  *
     658              :  *  @param[in]  aData           Initial buffer contents.
     659              :  *  @param[in]  aDataSize       Size of initial buffer contents.
     660              :  *
     661              :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     662              :  */
     663            0 : inline System::PacketBufferHandle NewWithData(const void * aData, size_t aDataSize)
     664              : {
     665            0 :     return System::PacketBufferHandle::NewWithData(aData, aDataSize, kMaxFooterSize);
     666              : }
     667              : 
     668              : /**
     669              :  * Check whether a packet buffer has enough space for a message footer.
     670              :  *
     671              :  * @returns true if there is space, false otherwise.
     672              :  */
     673            2 : inline bool HasFooterSpace(const System::PacketBufferHandle & aBuffer)
     674              : {
     675            2 :     return aBuffer->AvailableDataLength() >= kMaxFooterSize;
     676              : }
     677              : 
     678              : } // namespace MessagePacketBuffer
     679              : 
     680              : } // namespace chip
        

Generated by: LCOV version 2.0-1