Matter SDK Coverage Report
Current view: top level - transport/raw - MessageHeader.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 94.8 % 115 109
Test Date: 2025-01-17 19:00:11 Functions: 94.5 % 55 52

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : /**
      19              :  * @file
      20              :  * This file defines CHIP binary header encode/decode.
      21              :  */
      22              : 
      23              : #pragma once
      24              : 
      25              : #include <cstddef>
      26              : #include <cstdint>
      27              : #include <string.h>
      28              : 
      29              : #include <type_traits>
      30              : 
      31              : #include <crypto/CHIPCryptoPAL.h>
      32              : #include <lib/core/CHIPError.h>
      33              : #include <lib/core/GroupId.h>
      34              : #include <lib/core/Optional.h>
      35              : #include <lib/core/PeerId.h>
      36              : #include <lib/support/BitFlags.h>
      37              : #include <lib/support/BufferReader.h>
      38              : #include <lib/support/CodeUtils.h>
      39              : #include <lib/support/TypeTraits.h>
      40              : #include <protocols/Protocols.h>
      41              : #include <system/SystemPacketBuffer.h>
      42              : 
      43              : namespace chip {
      44              : 
      45              : namespace detail {
      46              : // Figure out the max size of a packet we can allocate, including all headers.
      47              : static constexpr size_t kMaxIPPacketSizeBytes       = 1280;
      48              : static constexpr size_t kMaxUDPAndIPHeaderSizeBytes = 48;
      49              : 
      50              : static_assert(kMaxIPPacketSizeBytes >= kMaxUDPAndIPHeaderSizeBytes + CHIP_SYSTEM_HEADER_RESERVE_SIZE,
      51              :               "Matter headers and IP headers must fit in an MTU.");
      52              : 
      53              : // Max space we have for our Application Payload and MIC, per spec.
      54              : static constexpr size_t kMaxPerSpecApplicationPayloadAndMICSizeBytes =
      55              :     kMaxIPPacketSizeBytes - kMaxUDPAndIPHeaderSizeBytes - CHIP_SYSTEM_HEADER_RESERVE_SIZE;
      56              : 
      57              : // Max space we have for our Application Payload and MIC in our actual packet
      58              : // buffers.  This is the size _excluding_ the header reserve.
      59              : static constexpr size_t kMaxPacketBufferApplicationPayloadAndMICSizeBytes = System::PacketBuffer::kMaxSize;
      60              : 
      61              : static constexpr size_t kMaxApplicationPayloadAndMICSizeBytes =
      62              :     std::min(kMaxPerSpecApplicationPayloadAndMICSizeBytes, kMaxPacketBufferApplicationPayloadAndMICSizeBytes);
      63              : } // namespace detail
      64              : 
      65              : static constexpr size_t kMaxTagLen = 16;
      66              : 
      67              : static_assert(detail::kMaxApplicationPayloadAndMICSizeBytes > kMaxTagLen, "Need to be able to fit our tag in a message");
      68              : 
      69              : // This is somewhat of an under-estimate, because in practice any time we have a
      70              : // tag we will not have source/destination node IDs, but above we are including
      71              : // those in the header sizes.
      72              : static constexpr size_t kMaxAppMessageLen = detail::kMaxApplicationPayloadAndMICSizeBytes - kMaxTagLen;
      73              : 
      74              : static constexpr uint16_t kMsgUnicastSessionIdUnsecured = 0x0000;
      75              : 
      76              : // Minimum header size of TCP + IPv6 without options.
      77              : static constexpr size_t kMaxTCPAndIPHeaderSizeBytes = 60;
      78              : 
      79              : // Max space for the Application Payload and MIC for large packet buffers
      80              : // This is the size _excluding_ the header reserve.
      81              : static constexpr size_t kMaxLargeApplicationPayloadAndMICSizeBytes =
      82              :     System::PacketBuffer::kLargeBufMaxSize - kMaxTCPAndIPHeaderSizeBytes;
      83              : 
      84              : static constexpr size_t kMaxLargeAppMessageLen = kMaxLargeApplicationPayloadAndMICSizeBytes - kMaxTagLen;
      85              : 
      86              : typedef int PacketHeaderFlags;
      87              : 
      88              : namespace Header {
      89              : 
      90              : enum class SessionType : uint8_t
      91              : {
      92              :     kUnicastSession = 0,
      93              :     kGroupSession   = 1,
      94              : };
      95              : 
      96              : /**
      97              :  *  @brief
      98              :  *    The CHIP Exchange header flag bits.
      99              :  */
     100              : enum class ExFlagValues : uint8_t
     101              : {
     102              :     /// Set when current message is sent by the initiator of an exchange.
     103              :     kExchangeFlag_Initiator = 0x01,
     104              : 
     105              :     /// Set when current message is an acknowledgment for a previously received message.
     106              :     kExchangeFlag_AckMsg = 0x02,
     107              : 
     108              :     /// Set when current message is requesting an acknowledgment from the recipient.
     109              :     kExchangeFlag_NeedsAck = 0x04,
     110              : 
     111              :     /// Secured Extension block is present.
     112              :     kExchangeFlag_SecuredExtension = 0x08,
     113              : 
     114              :     /// Set when a vendor id is prepended to the Message Protocol Id field.
     115              :     kExchangeFlag_VendorIdPresent = 0x10,
     116              : };
     117              : 
     118              : // Message flags 8-bit value of the form
     119              : //  |  4 bits | 1 | 1 | 2 bits |
     120              : //  +---------+-------+--------|
     121              : //  | version | - | S | DSIZ
     122              : //                  |   |
     123              : //                  |   +---------------- Destination Id field
     124              : //                  +-------------------- Source node Id present
     125              : 
     126              : enum class MsgFlagValues : uint8_t
     127              : {
     128              :     /// Header flag specifying that a source node id is included in the header.
     129              :     kSourceNodeIdPresent       = 0b00000100,
     130              :     kDestinationNodeIdPresent  = 0b00000001,
     131              :     kDestinationGroupIdPresent = 0b00000010,
     132              :     kDSIZReserved              = 0b00000011,
     133              : 
     134              : };
     135              : 
     136              : // Security flags 8-bit value of the form
     137              : //  | 1 | 1 | 1  | 3 | 2 bits |
     138              : //  +------------+---+--------|
     139              : //  | P | C | MX | - | SessionType
     140              : //
     141              : // With :
     142              : // P  = Privacy flag
     143              : // C  = Control Msg flag
     144              : // MX = Message Extension
     145              : 
     146              : enum class SecFlagValues : uint8_t
     147              : {
     148              :     kPrivacyFlag      = 0b10000000,
     149              :     kControlMsgFlag   = 0b01000000,
     150              :     kMsgExtensionFlag = 0b00100000,
     151              : };
     152              : 
     153              : enum SecFlagMask
     154              : {
     155              :     kSessionTypeMask = 0b00000011, ///< Mask to extract sessionType
     156              : };
     157              : 
     158              : using MsgFlags = BitFlags<MsgFlagValues>;
     159              : using SecFlags = BitFlags<SecFlagValues>;
     160              : 
     161              : using ExFlags = BitFlags<ExFlagValues>;
     162              : 
     163              : } // namespace Header
     164              : 
     165              : /**
     166              :  * Handles encoding/decoding of CHIP packet message headers.
     167              :  *
     168              :  * Packet headers are **UNENCRYPTED** and are placed at the start of
     169              :  * a message buffer.
     170              :  */
     171              : class PacketHeader
     172              : {
     173              : public:
     174              :     enum
     175              :     {
     176              :         kHeaderMinLength        = 8,
     177              :         kPrivacyHeaderMinLength = 4,
     178              :         kPrivacyHeaderOffset    = 4,
     179              :     };
     180              : 
     181              :     /**
     182              :      * Gets the message counter set in the header.
     183              :      *
     184              :      * Message IDs are expecte to monotonically increase by one for each mesage
     185              :      * that has been sent.
     186              :      */
     187        74377 :     uint32_t GetMessageCounter() const { return mMessageCounter; }
     188              : 
     189              :     /**
     190              :      * Gets the source node id in the current message.
     191              :      *
     192              :      * NOTE: the source node id is optional and may be missing.
     193              :      */
     194          109 :     const Optional<NodeId> & GetSourceNodeId() const { return mSourceNodeId; }
     195              : 
     196              :     /**
     197              :      * Gets the destination node id in the current message.
     198              :      *
     199              :      * NOTE: the destination node id is optional and may be missing.
     200              :      */
     201         9848 :     const Optional<NodeId> & GetDestinationNodeId() const { return mDestinationNodeId; }
     202              : 
     203              :     /**
     204              :      * Gets the destination group id in the current message.
     205              :      *
     206              :      * NOTE: the destination group id is optional and may be missing.
     207              :      */
     208            8 :     const Optional<GroupId> & GetDestinationGroupId() const { return mDestinationGroupId; }
     209              : 
     210         9650 :     uint16_t GetSessionId() const { return mSessionId; }
     211              :     Header::SessionType GetSessionType() const { return mSessionType; }
     212              : 
     213              :     uint8_t GetMessageFlags() const { return mMsgFlags.Raw(); }
     214              : 
     215        19363 :     uint8_t GetSecurityFlags() const { return mSecFlags.Raw(); }
     216              : 
     217         9736 :     bool HasPrivacyFlag() const { return mSecFlags.Has(Header::SecFlagValues::kPrivacyFlag); }
     218              : 
     219           18 :     bool HasSourceNodeId() const { return mMsgFlags.Has(Header::MsgFlagValues::kSourceNodeIdPresent); }
     220           11 :     bool HasDestinationNodeId() const { return mMsgFlags.Has(Header::MsgFlagValues::kDestinationNodeIdPresent); }
     221           13 :     bool HasDestinationGroupId() const { return mMsgFlags.Has(Header::MsgFlagValues::kDestinationGroupIdPresent); }
     222              : 
     223              :     void SetFlags(Header::SecFlagValues value) { mSecFlags.Set(value); }
     224              :     void SetFlags(Header::MsgFlagValues value) { mMsgFlags.Set(value); }
     225              : 
     226        35671 :     void SetMessageFlags(uint8_t flags) { mMsgFlags.SetRaw(flags); }
     227              : 
     228        35671 :     void SetSecurityFlags(uint8_t securityFlags)
     229              :     {
     230        35671 :         mSecFlags.SetRaw(securityFlags);
     231        35671 :         mSessionType = static_cast<Header::SessionType>(securityFlags & Header::SecFlagMask::kSessionTypeMask);
     232        35671 :     }
     233              : 
     234        19380 :     bool IsGroupSession() const { return mSessionType == Header::SessionType::kGroupSession; }
     235          286 :     bool IsUnicastSession() const { return mSessionType == Header::SessionType::kUnicastSession; }
     236              : 
     237        55134 :     bool IsSessionTypeValid() const
     238              :     {
     239        55134 :         switch (mSessionType)
     240              :         {
     241        55119 :         case Header::SessionType::kUnicastSession:
     242        55119 :             return true;
     243           15 :         case Header::SessionType::kGroupSession:
     244           15 :             return true;
     245            0 :         default:
     246            0 :             return false;
     247              :         }
     248              :     }
     249              : 
     250            7 :     bool IsValidGroupMsg() const
     251              :     {
     252              :         // Check is based on spec 4.11.2
     253            7 :         return (IsGroupSession() && HasSourceNodeId() && HasDestinationGroupId() && !IsSecureSessionControlMsg());
     254              :     }
     255              : 
     256           11 :     bool IsValidMCSPMsg() const
     257              :     {
     258              :         // Check is based on spec 4.9.2.4
     259           11 :         return (IsGroupSession() && HasSourceNodeId() && HasDestinationNodeId() && IsSecureSessionControlMsg());
     260              :     }
     261              : 
     262        77477 :     bool IsEncrypted() const { return !((mSessionId == kMsgUnicastSessionIdUnsecured) && IsUnicastSession()); }
     263              : 
     264        58088 :     uint16_t MICTagLength() const { return (IsEncrypted()) ? chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES : 0; }
     265              : 
     266              :     /** Check if it's a secure session control message. */
     267           12 :     bool IsSecureSessionControlMsg() const { return mSecFlags.Has(Header::SecFlagValues::kControlMsgFlag); }
     268              : 
     269            0 :     PacketHeader & SetSecureSessionControlMsg(bool value)
     270              :     {
     271            0 :         mSecFlags.Set(Header::SecFlagValues::kControlMsgFlag, value);
     272            0 :         return *this;
     273              :     }
     274              : 
     275           59 :     PacketHeader & SetSourceNodeId(NodeId id)
     276              :     {
     277           59 :         mSourceNodeId.SetValue(id);
     278           59 :         mMsgFlags.Set(Header::MsgFlagValues::kSourceNodeIdPresent);
     279           59 :         return *this;
     280              :     }
     281              : 
     282              :     PacketHeader & SetSourceNodeId(Optional<NodeId> id)
     283              :     {
     284              :         mSourceNodeId = id;
     285              :         mMsgFlags.Set(Header::MsgFlagValues::kSourceNodeIdPresent, id.HasValue());
     286              :         return *this;
     287              :     }
     288              : 
     289              :     PacketHeader & ClearSourceNodeId()
     290              :     {
     291              :         mSourceNodeId.ClearValue();
     292              :         mMsgFlags.Clear(Header::MsgFlagValues::kSourceNodeIdPresent);
     293              :         return *this;
     294              :     }
     295              : 
     296           40 :     PacketHeader & SetDestinationNodeId(NodeId id)
     297              :     {
     298           40 :         mDestinationNodeId.SetValue(id);
     299           40 :         mMsgFlags.Set(Header::MsgFlagValues::kDestinationNodeIdPresent);
     300           40 :         return *this;
     301              :     }
     302              : 
     303              :     PacketHeader & SetDestinationNodeId(Optional<NodeId> id)
     304              :     {
     305              :         mDestinationNodeId = id;
     306              :         mMsgFlags.Set(Header::MsgFlagValues::kDestinationNodeIdPresent, id.HasValue());
     307              :         return *this;
     308              :     }
     309              : 
     310              :     PacketHeader & ClearDestinationNodeId()
     311              :     {
     312              :         mDestinationNodeId.ClearValue();
     313              :         mMsgFlags.Clear(Header::MsgFlagValues::kDestinationNodeIdPresent);
     314              :         return *this;
     315              :     }
     316              : 
     317            1 :     PacketHeader & SetDestinationGroupId(GroupId id)
     318              :     {
     319            1 :         mDestinationGroupId.SetValue(id);
     320            1 :         mMsgFlags.Set(Header::MsgFlagValues::kDestinationGroupIdPresent);
     321            1 :         return *this;
     322              :     }
     323              : 
     324              :     PacketHeader & SetDestinationGroupId(Optional<GroupId> id)
     325              :     {
     326              :         mDestinationGroupId = id;
     327              :         mMsgFlags.Set(Header::MsgFlagValues::kDestinationGroupIdPresent, id.HasValue());
     328              :         return *this;
     329              :     }
     330              : 
     331              :     PacketHeader & ClearDestinationGroupId()
     332              :     {
     333              :         mDestinationGroupId.ClearValue();
     334              :         mMsgFlags.Clear(Header::MsgFlagValues::kDestinationGroupIdPresent);
     335              :         return *this;
     336              :     }
     337              : 
     338         9725 :     PacketHeader & SetSessionType(Header::SessionType type)
     339              :     {
     340         9725 :         mSessionType     = type;
     341         9725 :         uint8_t typeMask = to_underlying(Header::kSessionTypeMask);
     342         9725 :         mSecFlags.SetRaw(static_cast<uint8_t>((mSecFlags.Raw() & ~typeMask) | (to_underlying(type) & typeMask)));
     343         9725 :         return *this;
     344              :     }
     345              : 
     346         9679 :     PacketHeader & SetSessionId(uint16_t id)
     347              :     {
     348         9679 :         mSessionId = id;
     349         9679 :         return *this;
     350              :     }
     351              : 
     352         9777 :     PacketHeader & SetMessageCounter(uint32_t id)
     353              :     {
     354         9777 :         mMessageCounter = id;
     355         9777 :         return *this;
     356              :     }
     357              : 
     358              :     PacketHeader & SetUnsecured()
     359              :     {
     360              :         mSessionId   = kMsgUnicastSessionIdUnsecured;
     361              :         mSessionType = Header::SessionType::kUnicastSession;
     362              :         return *this;
     363              :     }
     364              : 
     365              :     /**
     366              :      * Returns a pointer to the start of the privacy header
     367              :      * given a pointer to the start of the message.
     368              :      */
     369            3 :     uint8_t * PrivacyHeader(uint8_t * msgBuf) const { return msgBuf + PacketHeader::kPrivacyHeaderOffset; }
     370              : 
     371            3 :     size_t PrivacyHeaderLength() const
     372              :     {
     373            3 :         size_t length = kPrivacyHeaderMinLength;
     374            3 :         if (mMsgFlags.Has(Header::MsgFlagValues::kSourceNodeIdPresent))
     375              :         {
     376            3 :             length += sizeof(NodeId);
     377              :         }
     378            3 :         if (mMsgFlags.Has(Header::MsgFlagValues::kDestinationNodeIdPresent))
     379              :         {
     380            0 :             length += sizeof(NodeId);
     381              :         }
     382            3 :         else if (mMsgFlags.Has(Header::MsgFlagValues::kDestinationGroupIdPresent))
     383              :         {
     384            3 :             length += sizeof(GroupId);
     385              :         }
     386            3 :         return length;
     387              :     }
     388              : 
     389              :     size_t PayloadOffset() const
     390              :     {
     391              :         size_t offset = kPrivacyHeaderMinLength;
     392              :         offset += PrivacyHeaderLength();
     393              :         return offset;
     394              :     }
     395              : 
     396              :     /**
     397              :      * A call to `Encode` will require at least this many bytes on the current
     398              :      * object to be successful.
     399              :      *
     400              :      * @return the number of bytes needed in a buffer to be able to Encode.
     401              :      */
     402              :     uint16_t EncodeSizeBytes() const;
     403              : 
     404              :     /**
     405              :      * Decodes the fixed portion of the header fields from the given buffer.
     406              :      * The fixed header includes: message flags, session id, and security flags.
     407              :      *
     408              :      * @return CHIP_NO_ERROR on success.
     409              :      *
     410              :      * Possible failures:
     411              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     412              :      *    CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
     413              :      */
     414              :     CHIP_ERROR DecodeFixed(const System::PacketBufferHandle & buf);
     415              : 
     416              :     /**
     417              :      * Decodes a header from the given buffer.
     418              :      *
     419              :      * @param data - the buffer to read from
     420              :      * @param size - bytes available in the buffer
     421              :      * @param decode_size - number of bytes read from the buffer to decode the
     422              :      *                      object
     423              :      *
     424              :      * @return CHIP_NO_ERROR on success.
     425              :      *
     426              :      * Possible failures:
     427              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     428              :      *    CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
     429              :      */
     430              :     CHIP_ERROR Decode(const uint8_t * data, size_t size, uint16_t * decode_size);
     431              : 
     432              :     /**
     433              :      * A version of Decode that uses the type system to determine available
     434              :      * space.
     435              :      */
     436              :     template <size_t N>
     437              :     inline CHIP_ERROR Decode(const uint8_t (&data)[N], uint16_t * decode_size)
     438              :     {
     439              :         return Decode(data, N, decode_size);
     440              :     }
     441              : 
     442              :     /**
     443              :      * A version of Decode that decodes from the start of a PacketBuffer and
     444              :      * consumes the bytes we decoded from.
     445              :      */
     446              :     CHIP_ERROR DecodeAndConsume(const System::PacketBufferHandle & buf);
     447              : 
     448              :     /**
     449              :      * Encodes a header into the given buffer.
     450              :      *
     451              :      * @param data - the buffer to write to
     452              :      * @param size - space available in the buffer (in bytes)
     453              :      * @param encode_size - number of bytes written to the buffer.
     454              :      *
     455              :      * @return CHIP_NO_ERROR on success.
     456              :      *
     457              :      * Possible failures:
     458              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     459              :      */
     460              :     CHIP_ERROR Encode(uint8_t * data, size_t size, uint16_t * encode_size) const;
     461              : 
     462              :     /**
     463              :      * A version of Encode that uses the type system to determine available
     464              :      * space.
     465              :      */
     466              :     template <size_t N>
     467              :     inline CHIP_ERROR Encode(uint8_t (&data)[N], uint16_t * encode_size) const
     468              :     {
     469              :         return Encode(data, N, encode_size);
     470              :     }
     471              : 
     472              :     /**
     473              :      * A version of Encode that encodes into a PacketBuffer before the
     474              :      * PacketBuffer's current data.
     475              :      */
     476              :     CHIP_ERROR EncodeBeforeData(const System::PacketBufferHandle & buf) const;
     477              : 
     478              :     /**
     479              :      * A version of Encode that encodes into a PacketBuffer at the start of the
     480              :      * current data space.  This assumes that someone has already preallocated
     481              :      * space for the header.
     482              :      */
     483         9833 :     inline CHIP_ERROR EncodeAtStart(const System::PacketBufferHandle & buf, uint16_t * encode_size) const
     484              :     {
     485         9833 :         return Encode(buf->Start(), buf->DataLength(), encode_size);
     486              :     }
     487              : 
     488              : private:
     489              :     /**
     490              :      * Decodes the fixed portion of the header fields from the stream reader.
     491              :      * The fixed header includes: message flags, session id, and security flags.
     492              :      *
     493              :      * @return CHIP_NO_ERROR on success.
     494              :      *
     495              :      * Possible failures:
     496              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     497              :      *    CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
     498              :      */
     499              :     CHIP_ERROR DecodeFixedCommon(Encoding::LittleEndian::Reader & reader);
     500              : 
     501              :     /// Represents the current encode/decode header version (4 bits)
     502              :     static constexpr uint8_t kMsgHeaderVersion = 0x00;
     503              : 
     504              :     /// Value expected to be incremented for each message sent.
     505              :     uint32_t mMessageCounter = 0;
     506              : 
     507              :     /// What node the message originated from
     508              :     Optional<NodeId> mSourceNodeId;
     509              : 
     510              :     /// Intended recipient of the message.
     511              :     Optional<NodeId> mDestinationNodeId;
     512              :     Optional<GroupId> mDestinationGroupId;
     513              : 
     514              :     /// Session ID
     515              :     uint16_t mSessionId = kMsgUnicastSessionIdUnsecured;
     516              : 
     517              :     Header::SessionType mSessionType = Header::SessionType::kUnicastSession;
     518              : 
     519              :     /// Flags read from the message.
     520              :     Header::MsgFlags mMsgFlags;
     521              :     Header::SecFlags mSecFlags;
     522              : };
     523              : 
     524              : /**
     525              :  * Handles encoding/decoding of CHIP payload headers.
     526              :  *
     527              :  * Payload headers are **ENCRYPTED** and are placed at the start of
     528              :  * an encrypted message payload.
     529              :  */
     530              : class PayloadHeader
     531              : {
     532              : public:
     533        18096 :     constexpr PayloadHeader() { SetProtocol(Protocols::NotSpecified); }
     534              :     constexpr PayloadHeader(const PayloadHeader &)   = default;
     535              :     PayloadHeader & operator=(const PayloadHeader &) = default;
     536              : 
     537              :     /** Get the Session ID from this header. */
     538        56079 :     uint16_t GetExchangeID() const { return mExchangeID; }
     539              : 
     540              :     /** Get the Protocol ID from this header. */
     541        66775 :     Protocols::Id GetProtocolID() const { return mProtocolID; }
     542              : 
     543              :     /** Check whether the header has a given protocol */
     544        11925 :     bool HasProtocol(Protocols::Id protocol) const { return mProtocolID == protocol; }
     545              : 
     546              :     /** Get the secure msg type from this header. */
     547        49076 :     uint8_t GetMessageType() const { return mMessageType; }
     548              : 
     549              :     /** Get the raw exchange flags from this header. */
     550              :     uint8_t GetExchangeFlags() const { return mExchangeFlags.Raw(); }
     551              : 
     552              :     /** Check whether the header has a given secure message type */
     553         5024 :     bool HasMessageType(uint8_t type) const { return mMessageType == type; }
     554              :     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
     555        12384 :     bool HasMessageType(MessageType type) const
     556              :     {
     557        12384 :         return HasProtocol(Protocols::MessageTypeTraits<MessageType>::ProtocolId()) && HasMessageType(to_underlying(type));
     558              :     }
     559              : 
     560              :     /**
     561              :      * Gets the Acknowledged Message Counter from this header.
     562              :      *
     563              :      * NOTE: the Acknowledged Message Counter is optional and may be missing.
     564              :      */
     565        51452 :     const Optional<uint32_t> & GetAckMessageCounter() const { return mAckMessageCounter; }
     566              : 
     567              :     /**
     568              :      * Set the message type for this header.  This requires setting the protocol
     569              :      * id as well, because the meaning of a message type is only relevant given
     570              :      * a specific protocol.
     571              :      *
     572              :      * This should only be used for cases when we don't have a strongly typed
     573              :      * message type and hence can't automatically determine the protocol from
     574              :      * the message type.
     575              :      */
     576         9052 :     PayloadHeader & SetMessageType(Protocols::Id protocol, uint8_t type)
     577              :     {
     578         9052 :         SetProtocol(protocol);
     579         9052 :         mMessageType = type;
     580         9052 :         return *this;
     581              :     }
     582              : 
     583              :     /** Set the secure message type, with the protocol id derived from the
     584              :         message type. */
     585              :     template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
     586            1 :     PayloadHeader & SetMessageType(MessageType type)
     587              :     {
     588            1 :         SetMessageType(Protocols::MessageTypeTraits<MessageType>::ProtocolId(), to_underlying(type));
     589            1 :         return *this;
     590              :     }
     591              : 
     592              :     /** Set the security session ID for this header. */
     593         9051 :     PayloadHeader & SetExchangeID(uint16_t id)
     594              :     {
     595         9051 :         mExchangeID = id;
     596         9051 :         return *this;
     597              :     }
     598              : 
     599              :     /** Set the Initiator flag bit. */
     600         9778 :     PayloadHeader & SetInitiator(bool inInitiator)
     601              :     {
     602         9778 :         mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_Initiator, inInitiator);
     603         9778 :         return *this;
     604              :     }
     605              : 
     606         8035 :     PayloadHeader & SetAckMessageCounter(uint32_t id)
     607              :     {
     608         8035 :         mAckMessageCounter.SetValue(id);
     609         8035 :         mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_AckMsg);
     610         8035 :         return *this;
     611              :     }
     612              : 
     613              :     /** Set the AckMsg flag bit. */
     614              :     PayloadHeader & SetAckMessageCounter(Optional<uint32_t> id)
     615              :     {
     616              :         mAckMessageCounter = id;
     617              :         mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_AckMsg, id.HasValue());
     618              :         return *this;
     619              :     }
     620              : 
     621              :     /** Set the NeedsAck flag bit. */
     622         9778 :     PayloadHeader & SetNeedsAck(bool inNeedsAck)
     623              :     {
     624         9778 :         mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_NeedsAck, inNeedsAck);
     625         9778 :         return *this;
     626              :     }
     627              : 
     628              :     /**
     629              :      *  Determine whether the initiator of the exchange.
     630              :      *
     631              :      *  @return Returns 'true' if it is the initiator, else 'false'.
     632              :      *
     633              :      */
     634        29266 :     bool IsInitiator() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_Initiator); }
     635              : 
     636              :     /**
     637              :      *  Determine whether the current message is an acknowledgment for a previously received message.
     638              :      *
     639              :      *  @return Returns 'true' if current message is an acknowledgment, else 'false'.
     640              :      *
     641              :      */
     642         9528 :     bool IsAckMsg() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_AckMsg); }
     643              : 
     644              :     /**
     645              :      *  Determine whether current message is requesting an acknowledgment from the recipient.
     646              :      *
     647              :      *  @return Returns 'true' if the current message is requesting an acknowledgment from the recipient, else 'false'.
     648              :      *
     649              :      */
     650         9702 :     bool NeedsAck() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_NeedsAck); }
     651              : 
     652              :     /**
     653              :      * A call to `Encode` will require at least this many bytes on the current
     654              :      * object to be successful.
     655              :      *
     656              :      * @return the number of bytes needed in a buffer to be able to Encode.
     657              :      */
     658              :     uint16_t EncodeSizeBytes() const;
     659              : 
     660              :     /**
     661              :      * Decodes the encrypted header fields from the given buffer.
     662              :      *
     663              :      * @param data - the buffer to read from
     664              :      * @param size - bytes available in the buffer
     665              :      * @param decode_size - number of bytes read from the buffer to decode the
     666              :      *                      object
     667              :      *
     668              :      * @return CHIP_NO_ERROR on success.
     669              :      *
     670              :      * Possible failures:
     671              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     672              :      *    CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
     673              :      */
     674              :     CHIP_ERROR Decode(const uint8_t * data, size_t size, uint16_t * decode_size);
     675              : 
     676              :     /**
     677              :      * A version of Decode that uses the type system to determine available
     678              :      * space.
     679              :      */
     680              :     template <size_t N>
     681              :     inline CHIP_ERROR Decode(const uint8_t (&data)[N], uint16_t * decode_size)
     682              :     {
     683              :         return Decode(data, N, decode_size);
     684              :     }
     685              : 
     686              :     /**
     687              :      * A version of Decode that decodes from the start of a PacketBuffer and
     688              :      * consumes the bytes we decoded from.
     689              :      */
     690              :     CHIP_ERROR DecodeAndConsume(const System::PacketBufferHandle & buf);
     691              : 
     692              :     /**
     693              :      * Encodes the encrypted part of the header into the given buffer.
     694              :      *
     695              :      * @param data - the buffer to write to
     696              :      * @param size - space available in the buffer (in bytes)
     697              :      * @param encode_size - number of bytes written to the buffer.
     698              :      *
     699              :      * @return CHIP_NO_ERROR on success.
     700              :      *
     701              :      * Possible failures:
     702              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     703              :      */
     704              :     CHIP_ERROR Encode(uint8_t * data, size_t size, uint16_t * encode_size) const;
     705              : 
     706              :     /**
     707              :      * A version of Encode that uses the type system to determine available
     708              :      * space.
     709              :      */
     710              :     template <size_t N>
     711              :     inline CHIP_ERROR Encode(uint8_t (&data)[N], uint16_t * decode_size) const
     712              :     {
     713              :         return Encode(data, N, decode_size);
     714              :     }
     715              : 
     716              :     /**
     717              :      * A version of Encode that encodes into a PacketBuffer before the
     718              :      * PacketBuffer's current data.
     719              :      */
     720              :     CHIP_ERROR EncodeBeforeData(const System::PacketBufferHandle & buf) const;
     721              : 
     722              :     /**
     723              :      * A version of Encode that encodes into a PacketBuffer at the start of the
     724              :      * current data space.  This assumes that someone has already preallocated
     725              :      * space for the header.
     726              :      */
     727         9824 :     inline CHIP_ERROR EncodeAtStart(const System::PacketBufferHandle & buf, uint16_t * encode_size) const
     728              :     {
     729         9824 :         return Encode(buf->Start(), buf->DataLength(), encode_size);
     730              :     }
     731              : 
     732              : private:
     733        27147 :     constexpr void SetProtocol(Protocols::Id protocol)
     734              :     {
     735        27147 :         mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_VendorIdPresent, protocol.GetVendorId() != VendorId::Common);
     736        27147 :         mProtocolID = protocol;
     737        27147 :     }
     738              : 
     739        58767 :     constexpr bool HaveVendorId() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_VendorIdPresent); }
     740              : 
     741              :     /// Packet type (application data, security control packets, e.g. pairing,
     742              :     /// configuration, rekey etc)
     743              :     uint8_t mMessageType = 0;
     744              : 
     745              :     /// Security session identifier
     746              :     uint16_t mExchangeID = 0;
     747              : 
     748              :     /// Protocol identifier
     749              :     Protocols::Id mProtocolID = Protocols::NotSpecified;
     750              : 
     751              :     /// Bit flag indicators for CHIP Exchange header
     752              :     Header::ExFlags mExchangeFlags;
     753              : 
     754              :     /// Message counter of a previous message that is being acknowledged by the current message
     755              :     Optional<uint32_t> mAckMessageCounter;
     756              : };
     757              : 
     758              : /** Handles encoding/decoding of CHIP message headers */
     759              : class MessageAuthenticationCode
     760              : {
     761              : public:
     762         9647 :     const uint8_t * GetTag() const { return &mTag[0]; }
     763              : 
     764              :     /** Set the message auth tag for this header. */
     765         9727 :     MessageAuthenticationCode & SetTag(PacketHeader * header, const uint8_t * tag, size_t len)
     766              :     {
     767         9727 :         const size_t tagLen = chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES;
     768         9727 :         if (tagLen > 0 && tagLen <= kMaxTagLen && len == tagLen)
     769              :         {
     770         9727 :             memcpy(&mTag, tag, tagLen);
     771              :         }
     772              : 
     773         9727 :         return *this;
     774              :     }
     775              : 
     776              :     /**
     777              :      * Decodes the Message Authentication Tag from the given buffer.
     778              :      *
     779              :      * @param packetHeader - header containing encryption information
     780              :      * @param data - the buffer to read from
     781              :      * @param size - bytes available in the buffer
     782              :      * @param decode_size - number of bytes read from the buffer to decode the
     783              :      *                      object
     784              :      *
     785              :      * @return CHIP_NO_ERROR on success.
     786              :      *
     787              :      * Possible failures:
     788              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     789              :      *    CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
     790              :      */
     791              :     CHIP_ERROR Decode(const PacketHeader & packetHeader, const uint8_t * data, size_t size, uint16_t * decode_size);
     792              : 
     793              :     /**
     794              :      * Encodes the Messae Authentication Tag into the given buffer.
     795              :      *
     796              :      * @param packetHeader - header containing encryption information
     797              :      * @param data - the buffer to write to
     798              :      * @param size - space available in the buffer (in bytes)
     799              :      * @param encode_size - number of bytes written to the buffer.
     800              :      *
     801              :      * @return CHIP_NO_ERROR on success.
     802              :      *
     803              :      * Possible failures:
     804              :      *    CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
     805              :      */
     806              :     CHIP_ERROR Encode(const PacketHeader & packetHeader, uint8_t * data, size_t size, uint16_t * encode_size) const;
     807              : 
     808              : private:
     809              :     /// Message authentication tag generated at encryption of the message.
     810              :     uint8_t mTag[kMaxTagLen];
     811              : };
     812              : 
     813              : } // namespace chip
        

Generated by: LCOV version 2.0-1