LCOV - code coverage report
Current view: top level - transport/raw - MessageHeader.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 109 115 94.8 %
Date: 2024-02-15 08:20:41 Functions: 52 55 94.5 %

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

Generated by: LCOV version 1.14