LCOV - code coverage report
Current view: top level - transport - SessionManager.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 33 81 40.7 %
Date: 2024-02-15 08:20:41 Functions: 17 25 68.0 %

          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             : namespace chip {
      56             : 
      57             : /**
      58             :  * @brief
      59             :  *  Tracks ownership of a encrypted packet buffer.
      60             :  *
      61             :  *  EncryptedPacketBufferHandle is a kind of PacketBufferHandle class and used to hold a packet buffer
      62             :  *  object whose payload has already been encrypted.
      63             :  */
      64             : class EncryptedPacketBufferHandle final : private System::PacketBufferHandle
      65             : {
      66             : public:
      67        9540 :     EncryptedPacketBufferHandle() {}
      68             :     EncryptedPacketBufferHandle(EncryptedPacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
      69             : 
      70        9585 :     void operator=(EncryptedPacketBufferHandle && aBuffer) { PacketBufferHandle::operator=(std::move(aBuffer)); }
      71             : 
      72             :     using System::PacketBufferHandle::IsNull;
      73             :     // Pass-through to HasChainedBuffer on our underlying buffer without
      74             :     // exposing operator->
      75             :     bool HasChainedBuffer() const { return (*this)->HasChainedBuffer(); }
      76             : 
      77             :     uint32_t GetMessageCounter() const;
      78             : 
      79             :     /**
      80             :      * Creates a copy of the data in this packet.
      81             :      *
      82             :      * Does NOT support chained buffers.
      83             :      *
      84             :      * @returns empty handle on allocation failure.
      85             :      */
      86             :     EncryptedPacketBufferHandle CloneData() { return EncryptedPacketBufferHandle(PacketBufferHandle::CloneData()); }
      87             : 
      88             : #ifdef CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
      89             :     /**
      90             :      * Extracts the (unencrypted) packet header from this encrypted packet
      91             :      * buffer.  Returns error if a packet header cannot be extracted (e.g. if
      92             :      * there are not enough bytes in this packet buffer).  After this call the
      93             :      * buffer does not have a packet header.  This API is meant for
      94             :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
      95             :      * should not be defined normally.
      96             :      */
      97             :     CHIP_ERROR ExtractPacketHeader(PacketHeader & aPacketHeader) { return aPacketHeader.DecodeAndConsume(*this); }
      98             : 
      99             :     /**
     100             :      * Inserts a new (unencrypted) packet header in the encrypted packet buffer
     101             :      * based on the given PacketHeader.  This API is meant for
     102             :      * unit tests only.   The CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API define
     103             :      * should not be defined normally.
     104             :      */
     105             :     CHIP_ERROR InsertPacketHeader(const PacketHeader & aPacketHeader) { return aPacketHeader.EncodeBeforeData(*this); }
     106             : #endif // CHIP_ENABLE_TEST_ENCRYPTED_BUFFER_API
     107             : 
     108        9585 :     static EncryptedPacketBufferHandle MarkEncrypted(PacketBufferHandle && aBuffer)
     109             :     {
     110        9585 :         return EncryptedPacketBufferHandle(std::move(aBuffer));
     111             :     }
     112             : 
     113             :     /**
     114             :      * Get a handle to the data that allows mutating the bytes.  This should
     115             :      * only be used if absolutely necessary, because EncryptedPacketBufferHandle
     116             :      * represents a buffer that we want to resend as-is.
     117             :      */
     118        9619 :     PacketBufferHandle CastToWritable() const { return PacketBufferHandle::Retain(); }
     119             : 
     120             : private:
     121        9539 :     EncryptedPacketBufferHandle(PacketBufferHandle && aBuffer) : PacketBufferHandle(std::move(aBuffer)) {}
     122             : };
     123             : 
     124             : class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTable::Delegate
     125             : {
     126             : public:
     127             :     SessionManager();
     128             :     ~SessionManager() override;
     129             : 
     130             :     /**
     131             :      * @brief
     132             :      *   This function takes the payload and returns an encrypted message which can be sent multiple times.
     133             :      *
     134             :      * @details
     135             :      *   It does the following:
     136             :      *    1. Encrypt the msgBuf
     137             :      *    2. construct the packet header
     138             :      *    3. Encode the packet header and prepend it to message.
     139             :      *   Returns a encrypted message in encryptedMessage.
     140             :      */
     141             :     CHIP_ERROR PrepareMessage(const SessionHandle & session, PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf,
     142             :                               EncryptedPacketBufferHandle & encryptedMessage);
     143             : 
     144             :     /**
     145             :      * @brief
     146             :      *   Send a prepared message to a currently connected peer.
     147             :      */
     148             :     CHIP_ERROR SendPreparedMessage(const SessionHandle & session, const EncryptedPacketBufferHandle & preparedMessage);
     149             : 
     150             :     /// @brief Set the delegate for handling incoming messages. There can be only one message delegate (probably the
     151             :     /// ExchangeManager)
     152         226 :     void SetMessageDelegate(SessionMessageDelegate * cb) { mCB = cb; }
     153             : 
     154             :     // Test-only: create a session on the fly.
     155             :     CHIP_ERROR InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
     156             :                                             uint16_t peerSessionId, FabricIndex fabricIndex,
     157             :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role);
     158             :     CHIP_ERROR InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, uint16_t peerSessionId,
     159             :                                             NodeId localNodeId, NodeId peerNodeId, FabricIndex fabric,
     160             :                                             const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role,
     161             :                                             const CATValues & cats = CATValues{});
     162             : 
     163             :     /**
     164             :      * @brief
     165             :      *   Allocate a secure session and non-colliding session ID in the secure
     166             :      *   session table.
     167             :      *
     168             :      *   If we're either establishing or just finished establishing a session to a peer in either initiator or responder
     169             :      *   roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
     170             :      *   to a default-constructed ScopedNodeId().
     171             :      *
     172             :      * @return SessionHandle with a reference to a SecureSession, else NullOptional on failure
     173             :      */
     174             :     CHECK_RETURN_VALUE
     175             :     Optional<SessionHandle> AllocateSession(Transport::SecureSession::Type secureSessionType,
     176             :                                             const ScopedNodeId & sessionEvictionHint);
     177             : 
     178             :     /**
     179             :      *  A set of templated helper function that call a provided lambda
     180             :      *  on all sessions in the underlying session table that match the provided
     181             :      *  query criteria.
     182             :      *
     183             :      */
     184             : 
     185             :     /**
     186             :      * Call the provided lambda on sessions whose remote side match the provided ScopedNodeId.
     187             :      *
     188             :      */
     189             :     template <typename Function>
     190           7 :     void ForEachMatchingSession(const ScopedNodeId & node, Function && function)
     191             :     {
     192           7 :         mSecureSessions.ForEachSession([&](auto * session) {
     193          28 :             if (session->GetPeer() == node)
     194             :             {
     195           7 :                 function(session);
     196             :             }
     197             : 
     198          28 :             return Loop::Continue;
     199             :         });
     200           7 :     }
     201             : 
     202             :     /**
     203             :      * Call the provided lambda on sessions that match the provided fabric index.
     204             :      *
     205             :      */
     206             :     template <typename Function>
     207           2 :     void ForEachMatchingSession(FabricIndex fabricIndex, Function && function)
     208             :     {
     209           2 :         mSecureSessions.ForEachSession([&](auto * session) {
     210          16 :             if (session->GetFabricIndex() == fabricIndex)
     211             :             {
     212           6 :                 function(session);
     213             :             }
     214             : 
     215          16 :             return Loop::Continue;
     216             :         });
     217           2 :     }
     218             : 
     219             :     /**
     220             :      * Call the provided lambda on all sessions whose remote side match the logical fabric
     221             :      * associated with the provided ScopedNodeId and target the same logical remote node.
     222             :      *
     223             :      * *NOTE* This is identical in behavior to ForEachMatchingSession(const ScopedNodeId ..)
     224             :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     225             :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     226             :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     227             :      *        and each is assigned a unique fabric index.
     228             :      */
     229             :     template <typename Function>
     230           0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(const ScopedNodeId & node, Function && function)
     231             :     {
     232           0 :         Crypto::P256PublicKey targetPubKey;
     233             : 
     234           0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(node.GetFabricIndex());
     235           0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     236             : 
     237           0 :         auto err = targetFabric->FetchRootPubkey(targetPubKey);
     238           0 :         VerifyOrDie(err == CHIP_NO_ERROR);
     239             : 
     240           0 :         mSecureSessions.ForEachSession([&](auto * session) {
     241           0 :             Crypto::P256PublicKey comparePubKey;
     242             : 
     243             :             //
     244             :             // It's entirely possible to either come across a PASE session OR, a CASE session
     245             :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     246             :             // waiting for a Sigma1 message to arrive). Let's skip those.
     247             :             //
     248           0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     249             :             {
     250           0 :                 return Loop::Continue;
     251             :             }
     252             : 
     253           0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     254           0 :             VerifyOrDie(compareFabric != nullptr);
     255             : 
     256           0 :             err = compareFabric->FetchRootPubkey(comparePubKey);
     257           0 :             VerifyOrDie(err == CHIP_NO_ERROR);
     258             : 
     259           0 :             if (comparePubKey.Matches(targetPubKey) && targetFabric->GetFabricId() == compareFabric->GetFabricId() &&
     260           0 :                 session->GetPeerNodeId() == node.GetNodeId())
     261             :             {
     262           0 :                 function(session);
     263             :             }
     264             : 
     265           0 :             return Loop::Continue;
     266           0 :         });
     267             : 
     268           0 :         return CHIP_NO_ERROR;
     269           0 :     }
     270             : 
     271             :     /**
     272             :      * Call the provided lambda on all sessions that match the logical fabric
     273             :      * associated with the provided fabric index.
     274             :      *
     275             :      * *NOTE* This is identical in behavior to ForEachMatchingSession(FabricIndex ..)
     276             :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     277             :      *        on the same logical fabric (i.e root public key + fabric ID tuple).
     278             :      *        This can ONLY happen if multiple controller instances on the same fabric is permitted
     279             :      *        and each is assigned a unique fabric index.
     280             :      */
     281             :     template <typename Function>
     282           0 :     CHIP_ERROR ForEachMatchingSessionOnLogicalFabric(FabricIndex fabricIndex, Function && function)
     283             :     {
     284           0 :         Crypto::P256PublicKey targetPubKey;
     285             : 
     286           0 :         auto * targetFabric = mFabricTable->FindFabricWithIndex(fabricIndex);
     287           0 :         VerifyOrReturnError(targetFabric != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
     288             : 
     289           0 :         auto err = targetFabric->FetchRootPubkey(targetPubKey);
     290           0 :         VerifyOrDie(err == CHIP_NO_ERROR);
     291             : 
     292           0 :         mSecureSessions.ForEachSession([&](auto * session) {
     293           0 :             Crypto::P256PublicKey comparePubKey;
     294             : 
     295             :             //
     296             :             // It's entirely possible to either come across a PASE session OR, a CASE session
     297             :             // that has yet to be activated (i.e a CASEServer holding onto a SecureSession object
     298             :             // waiting for a Sigma1 message to arrive). Let's skip those.
     299             :             //
     300           0 :             if (!session->IsCASESession() || session->GetFabricIndex() == kUndefinedFabricIndex)
     301             :             {
     302           0 :                 return Loop::Continue;
     303             :             }
     304             : 
     305           0 :             auto * compareFabric = mFabricTable->FindFabricWithIndex(session->GetFabricIndex());
     306           0 :             VerifyOrDie(compareFabric != nullptr);
     307             : 
     308           0 :             err = compareFabric->FetchRootPubkey(comparePubKey);
     309           0 :             VerifyOrDie(err == CHIP_NO_ERROR);
     310             : 
     311           0 :             if (comparePubKey.Matches(targetPubKey) && targetFabric->GetFabricId() == compareFabric->GetFabricId())
     312             :             {
     313           0 :                 function(session);
     314             :             }
     315             : 
     316           0 :             return Loop::Continue;
     317           0 :         });
     318             : 
     319           0 :         return CHIP_NO_ERROR;
     320           0 :     }
     321             : 
     322             :     void ExpireAllSessions(const ScopedNodeId & node);
     323             :     void ExpireAllSessionsForFabric(FabricIndex fabricIndex);
     324             : 
     325             :     /**
     326             :      * Expire all sessions whose remote side matches the logical fabric
     327             :      * associated with the provided ScopedNodeId and target the same logical remote node.
     328             :      *
     329             :      * *NOTE* This is identical in behavior to ExpireAllSessions(const ScopedNodeId ..)
     330             :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     331             :      *        on the same logical fabric (i.e root public key + fabric ID tuple).  This can ONLY happen
     332             :      *        if multiple controller instances on the same fabric is permitted and each is assigned
     333             :      *        a unique fabric index.
     334             :      *
     335             :      */
     336             :     CHIP_ERROR ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node);
     337             : 
     338             :     /**
     339             :      * Expire all sessions whose remote side matches the logical fabric
     340             :      * associated with the provided fabric index.
     341             :      *
     342             :      * *NOTE* This is identical in behavior to ExpireAllSessExpireAllSessionsForFabricions(FabricIndex ..)
     343             :      *        EXCEPT if there are multiple FabricInfo instances in the FabricTable that collide
     344             :      *        on the same logical fabric (i.e root public key + fabric ID tuple).  This can ONLY happen
     345             :      *        if multiple controller instances on the same fabric is permitted and each is assigned
     346             :      *        a unique fabric index.
     347             :      *
     348             :      */
     349             :     CHIP_ERROR ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex);
     350             : 
     351             :     void ExpireAllPASESessions();
     352             : 
     353             :     /**
     354             :      * @brief
     355             :      *   Marks all active sessions that match provided arguments as defunct.
     356             :      *
     357             :      * @param node    Scoped node ID of the active sessions we should mark as defunct.
     358             :      * @param type    Type of session we are looking to mark as defunct. If matching
     359             :      *                against all types of sessions is desired, NullOptional should
     360             :      *                be passed into type.
     361             :      */
     362             :     void MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type);
     363             : 
     364             :     /**
     365             :      * @brief
     366             :      *   Update all CASE sessions that match `node` with the provided transport peer address.
     367             :      *
     368             :      * @param node    Scoped node ID of the active sessions we want to update.
     369             :      * @param addr    Transport peer address that we want to update to.
     370             :      */
     371             :     void UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr);
     372             : 
     373             :     /**
     374             :      * @brief
     375             :      *   Return the System Layer pointer used by current SessionManager.
     376             :      */
     377       17662 :     System::Layer * SystemLayer() { return mSystemLayer; }
     378             : 
     379             :     /**
     380             :      * @brief
     381             :      *   Initialize a Secure Session Manager
     382             :      *
     383             :      * @param systemLayer           System layer to use
     384             :      * @param transportMgr          Transport to use
     385             :      * @param messageCounterManager The message counter manager
     386             :      * @param storageDelegate       Persistent storage implementation
     387             :      * @param fabricTable           Fabric table to hold information about joined fabrics
     388             :      * @param sessionKeystore       Session keystore for management of symmetric encryption keys
     389             :      */
     390             :     CHIP_ERROR Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
     391             :                     Transport::MessageCounterManagerInterface * messageCounterManager,
     392             :                     chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
     393             :                     Crypto::SessionKeystore & sessionKeystore);
     394             : 
     395             :     /**
     396             :      * @brief
     397             :      *  Shutdown the Secure Session Manager. This terminates this instance
     398             :      *  of the object and reset it's state.
     399             :      */
     400             :     void Shutdown();
     401             : 
     402             :     /**
     403             :      * @brief Notification that a fabric was removed.
     404             :      */
     405             :     void FabricRemoved(FabricIndex fabricIndex);
     406             : 
     407             :     TransportMgrBase * GetTransportManager() const { return mTransportMgr; }
     408             :     Transport::SecureSessionTable & GetSecureSessions() { return mSecureSessions; }
     409             : 
     410             :     /**
     411             :      * @brief
     412             :      *   Handle received secure message. Implements TransportMgrDelegate
     413             :      *
     414             :      * @param source    the source address of the package
     415             :      * @param msgBuf    the buffer containing a full CHIP message (except for the optional length field).
     416             :      */
     417             :     void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf) override;
     418             : 
     419           0 :     Optional<SessionHandle> CreateUnauthenticatedSession(const Transport::PeerAddress & peerAddress,
     420             :                                                          const ReliableMessageProtocolConfig & config)
     421             :     {
     422             :         // Allocate ephemeralInitiatorNodeID in Operational Node ID range
     423             :         NodeId ephemeralInitiatorNodeID;
     424             :         do
     425             :         {
     426           0 :             ephemeralInitiatorNodeID = static_cast<NodeId>(Crypto::GetRandU64());
     427           0 :         } while (!IsOperationalNodeId(ephemeralInitiatorNodeID));
     428           0 :         return mUnauthenticatedSessions.AllocInitiator(ephemeralInitiatorNodeID, peerAddress, config);
     429             :     }
     430             : 
     431             :     //
     432             :     // Find an existing secure session given a peer's scoped NodeId and a type of session to match against.
     433             :     // If matching against all types of sessions is desired, NullOptional should be passed into type.
     434             :     //
     435             :     // If a valid session is found, an Optional<SessionHandle> with the value set to the SessionHandle of the session
     436             :     // is returned. Otherwise, an Optional<SessionHandle> with no value set is returned.
     437             :     //
     438             :     //
     439             :     Optional<SessionHandle> FindSecureSessionForNode(ScopedNodeId peerNodeId,
     440             :                                                      const Optional<Transport::SecureSession::Type> & type = NullOptional);
     441             : 
     442             :     using SessionHandleCallback = bool (*)(void * context, SessionHandle & sessionHandle);
     443             :     CHIP_ERROR ForEachSessionHandle(void * context, SessionHandleCallback callback);
     444             : 
     445             :     //// FabricTable::Delegate Implementation ////
     446           5 :     void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
     447             :     {
     448             :         (void) fabricTable;
     449           5 :         this->FabricRemoved(fabricIndex);
     450           5 :     }
     451             : 
     452       18754 :     FabricTable * GetFabricTable() const { return mFabricTable; }
     453             : 
     454         152 :     Crypto::SessionKeystore * GetSessionKeystore() const { return mSessionKeystore; }
     455             : 
     456             : private:
     457             :     /**
     458             :      *    The State of a secure transport object.
     459             :      */
     460             :     enum class State
     461             :     {
     462             :         kNotReady,    /**< State before initialization. */
     463             :         kInitialized, /**< State when the object is ready connect to other peers. */
     464             :     };
     465             : 
     466             :     enum class EncryptionState
     467             :     {
     468             :         kPayloadIsEncrypted,
     469             :         kPayloadIsUnencrypted,
     470             :     };
     471             : 
     472             :     System::Layer * mSystemLayer               = nullptr;
     473             :     FabricTable * mFabricTable                 = nullptr;
     474             :     Crypto::SessionKeystore * mSessionKeystore = nullptr;
     475             :     Transport::UnauthenticatedSessionTable<CHIP_CONFIG_UNAUTHENTICATED_CONNECTION_POOL_SIZE> mUnauthenticatedSessions;
     476             :     Transport::SecureSessionTable mSecureSessions;
     477             :     State mState; // < Initialization state of the object
     478             :     chip::Transport::GroupOutgoingCounters mGroupClientCounter;
     479             : 
     480             :     SessionMessageDelegate * mCB = nullptr;
     481             : 
     482             :     TransportMgrBase * mTransportMgr                                   = nullptr;
     483             :     Transport::MessageCounterManagerInterface * mMessageCounterManager = nullptr;
     484             : 
     485             :     GlobalUnencryptedMessageCounter mGlobalUnencryptedMessageCounter;
     486             : 
     487             :     /**
     488             :      * @brief Parse, decrypt, validate, and dispatch a secure unicast message.
     489             :      *
     490             :      * @param[in] partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     491             :      * If the message decrypts successfully, this will be filled with a fully decoded PacketHeader.
     492             :      * @param[in] peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     493             :      * @param msg The full message buffer, including header fields.
     494             :      */
     495             :     void SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     496             :                                       System::PacketBufferHandle && msg);
     497             : 
     498             :     /**
     499             :      * @brief Parse, decrypt, validate, and dispatch a secure group message.
     500             :      *
     501             :      * @param partialPacketHeader The partial PacketHeader of the message once processed with DecodeFixed.
     502             :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     503             :      * @param msg The full message buffer, including header fields.
     504             :      */
     505             :     void SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     506             :                                     System::PacketBufferHandle && msg);
     507             : 
     508             :     /**
     509             :      * @brief Parse, decrypt, validate, and dispatch an unsecured message.
     510             :      *
     511             :      * @param partialPacketHeader The partial PacketHeader of the message after processing with DecodeFixed.
     512             :      * @param peerAddress The PeerAddress of the message as provided by the receiving Transport Endpoint.
     513             :      * @param msg The full message buffer, including header fields.
     514             :      */
     515             :     void UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader, const Transport::PeerAddress & peerAddress,
     516             :                                         System::PacketBufferHandle && msg);
     517             : 
     518             :     void OnReceiveError(CHIP_ERROR error, const Transport::PeerAddress & source);
     519             : 
     520        9587 :     static bool IsControlMessage(PayloadHeader & payloadHeader)
     521             :     {
     522       19174 :         return payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncReq) ||
     523       19174 :             payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::MsgCounterSyncRsp);
     524             :     }
     525             : };
     526             : 
     527             : namespace MessagePacketBuffer {
     528             : /**
     529             :  * Maximum size of a message footer, in bytes.
     530             :  */
     531             : inline constexpr uint16_t kMaxFooterSize = kMaxTagLen;
     532             : 
     533             : /**
     534             :  * Allocates a packet buffer with space for message headers and footers.
     535             :  *
     536             :  *  Fails and returns \c nullptr if no memory is available, or if the size requested is too large.
     537             :  *
     538             :  *  @param[in]  aAvailableSize  Minimum number of octets to for application data.
     539             :  *
     540             :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     541             :  */
     542        1556 : inline System::PacketBufferHandle New(size_t aAvailableSize)
     543             : {
     544             :     static_assert(System::PacketBuffer::kMaxSize > kMaxFooterSize, "inadequate capacity");
     545        1556 :     if (aAvailableSize > System::PacketBuffer::kMaxSize - kMaxFooterSize)
     546             :     {
     547           0 :         return System::PacketBufferHandle();
     548             :     }
     549        1556 :     return System::PacketBufferHandle::New(aAvailableSize + kMaxFooterSize);
     550             : }
     551             : 
     552             : /**
     553             :  * Allocates a packet buffer with initial contents.
     554             :  *
     555             :  *  @param[in]  aData           Initial buffer contents.
     556             :  *  @param[in]  aDataSize       Size of initial buffer contents.
     557             :  *
     558             :  *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     559             :  */
     560           0 : inline System::PacketBufferHandle NewWithData(const void * aData, size_t aDataSize)
     561             : {
     562           0 :     return System::PacketBufferHandle::NewWithData(aData, aDataSize, kMaxFooterSize);
     563             : }
     564             : 
     565             : /**
     566             :  * Check whether a packet buffer has enough space for a message footer.
     567             :  *
     568             :  * @returns true if there is space, false otherwise.
     569             :  */
     570           2 : inline bool HasFooterSpace(const System::PacketBufferHandle & aBuffer)
     571             : {
     572           2 :     return aBuffer->AvailableDataLength() >= kMaxFooterSize;
     573             : }
     574             : 
     575             : } // namespace MessagePacketBuffer
     576             : 
     577             : } // namespace chip

Generated by: LCOV version 1.14