Matter SDK Coverage Report
Current view: top level - transport/raw - MessageHeader.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 98.8 % 166 164
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 14 14

            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 contains the implementation the chip message header
      21              :  *   encode/decode classes.
      22              :  */
      23              : 
      24              : #include "MessageHeader.h"
      25              : 
      26              : #include <assert.h>
      27              : #include <limits.h>
      28              : #include <stdint.h>
      29              : 
      30              : #include <type_traits>
      31              : 
      32              : #include <lib/core/CHIPError.h>
      33              : #include <lib/support/BufferReader.h>
      34              : #include <lib/support/CodeUtils.h>
      35              : 
      36              : /**********************************************
      37              :  * Header format (little endian):
      38              :  *
      39              :  * -------- Unencrypted header -----------------------------------------------------
      40              :  *  8 bit:  | Message Flags: VERSION: 4 bit | S: 1 bit | RESERVED: 1 bit | DSIZ: 2 bit |
      41              :  *  8 bit:  | Security Flags: P: 1 bit | C: 1 bit | MX: 1 bit | RESERVED: 3 bit | Session Type: 2 bit |
      42              :  *  16 bit: | Session ID                                                           |
      43              :  *  32 bit: | Message Counter                                                      |
      44              :  *  64 bit: | SOURCE_NODE_ID (iff source node flag is set)                         |
      45              :  *  64 bit: | DEST_NODE_ID (iff destination node flag is set)                      |
      46              :  * -------- Encrypted header -------------------------------------------------------
      47              :  *  8 bit:  | Exchange Flags: RESERVED: 3 bit | V: 1 bit | SX: 1 bit | R: 1 bit | A: 1 bit | I: 1 bit |
      48              :  *  8 bit:  | Protocol Opcode                                                      |
      49              :  * 16 bit:  | Exchange ID                                                          |
      50              :  * 16 bit:  | Protocol ID                                                          |
      51              :  * 16 bit:  | Optional Vendor ID                                                   |
      52              :  * 32 bit:  | Acknowledged Message Counter (if A flag in the Header is set)        |
      53              :  * -------- Encrypted Application Data Start ---------------------------------------
      54              :  *  <var>:  | Encrypted Data                                                       |
      55              :  * -------- Encrypted Application Data End -----------------------------------------
      56              :  *  <var>:  | (Unencrypted) Message Authentication Tag                             |
      57              :  *
      58              :  **********************************************/
      59              : 
      60              : namespace chip {
      61              : namespace {
      62              : 
      63              : using namespace chip::Encoding;
      64              : 
      65              : /// size of the fixed portion of the header
      66              : constexpr size_t kFixedUnencryptedHeaderSizeBytes = 8;
      67              : 
      68              : /// size of the encrypted portion of the header
      69              : constexpr size_t kEncryptedHeaderSizeBytes = 6;
      70              : 
      71              : /// size of a serialized node id inside a header
      72              : constexpr size_t kNodeIdSizeBytes = 8;
      73              : 
      74              : /// size of a serialized group id inside a header
      75              : constexpr size_t kGroupIdSizeBytes = 2;
      76              : 
      77              : /// size of a serialized vendor id inside a header
      78              : constexpr size_t kVendorIdSizeBytes = 2;
      79              : 
      80              : /// size of a serialized ack message counter inside a header
      81              : constexpr size_t kAckMessageCounterSizeBytes = 4;
      82              : 
      83              : /// Mask to extract just the version part from a 8bits header prefix.
      84              : constexpr uint8_t kVersionMask = 0xF0;
      85              : 
      86              : constexpr uint8_t kMsgFlagsMask = 0x07;
      87              : /// Shift to convert to/from a masked version 8bit value to a 4bit version.
      88              : constexpr int kVersionShift = 4;
      89              : 
      90              : } // namespace
      91              : 
      92        97414 : uint16_t PacketHeader::EncodeSizeBytes() const
      93              : {
      94        97414 :     size_t size = kFixedUnencryptedHeaderSizeBytes;
      95              : 
      96        97414 :     if (mSourceNodeId.HasValue())
      97              :     {
      98          351 :         size += kNodeIdSizeBytes;
      99              :     }
     100              : 
     101        97414 :     if (mDestinationNodeId.HasValue())
     102              :     {
     103          236 :         size += kNodeIdSizeBytes;
     104              :     }
     105        97178 :     else if (mDestinationGroupId.HasValue())
     106              :     {
     107           37 :         size += kGroupIdSizeBytes;
     108              :     }
     109              : 
     110              :     static_assert(kFixedUnencryptedHeaderSizeBytes + kNodeIdSizeBytes + kNodeIdSizeBytes <= UINT16_MAX,
     111              :                   "Header size does not fit in uint16_t");
     112        97414 :     return static_cast<uint16_t>(size);
     113              : }
     114              : 
     115        39194 : uint16_t PayloadHeader::EncodeSizeBytes() const
     116              : {
     117        39194 :     size_t size = kEncryptedHeaderSizeBytes;
     118              : 
     119        39194 :     if (HaveVendorId())
     120              :     {
     121           90 :         size += kVendorIdSizeBytes;
     122              :     }
     123              : 
     124        39194 :     if (mAckMessageCounter.HasValue())
     125              :     {
     126        32099 :         size += kAckMessageCounterSizeBytes;
     127              :     }
     128              : 
     129              :     static_assert(kEncryptedHeaderSizeBytes + kVendorIdSizeBytes + kAckMessageCounterSizeBytes <= UINT16_MAX,
     130              :                   "Header size does not fit in uint16_t");
     131        39194 :     return static_cast<uint16_t>(size);
     132              : }
     133              : 
     134        35771 : CHIP_ERROR PacketHeader::DecodeFixedCommon(Encoding::LittleEndian::Reader & reader)
     135              : {
     136        35771 :     CHIP_ERROR err = CHIP_NO_ERROR;
     137              :     int version;
     138              : 
     139              :     uint8_t msgFlags;
     140        35771 :     SuccessOrExit(err = reader.Read8(&msgFlags).StatusCode());
     141        35766 :     version = ((msgFlags & kVersionMask) >> kVersionShift);
     142        35766 :     VerifyOrExit(version == kMsgHeaderVersion, err = CHIP_ERROR_VERSION_MISMATCH);
     143        35766 :     SetMessageFlags(msgFlags);
     144              : 
     145        35766 :     SuccessOrExit(err = reader.Read16(&mSessionId).StatusCode());
     146              : 
     147              :     uint8_t securityFlags;
     148        35756 :     SuccessOrExit(err = reader.Read8(&securityFlags).StatusCode());
     149        35751 :     SetSecurityFlags(securityFlags);
     150              : 
     151        35771 : exit:
     152              : 
     153        35771 :     return err;
     154              : }
     155              : 
     156         9746 : CHIP_ERROR PacketHeader::DecodeFixed(const System::PacketBufferHandle & buf)
     157              : {
     158         9746 :     const uint8_t * const data = buf->Start();
     159         9746 :     size_t size                = buf->DataLength();
     160         9746 :     LittleEndian::Reader reader(data, size);
     161         9746 :     return DecodeFixedCommon(reader);
     162              : }
     163              : 
     164        26025 : CHIP_ERROR PacketHeader::Decode(const uint8_t * const data, size_t size, uint16_t * decode_len)
     165              : {
     166        26025 :     CHIP_ERROR err = CHIP_NO_ERROR;
     167        26025 :     LittleEndian::Reader reader(data, size);
     168              :     // TODO: De-uint16-ify everything related to this library
     169              :     uint16_t octets_read;
     170              : 
     171        26025 :     SuccessOrExit(err = DecodeFixedCommon(reader));
     172              : 
     173        26005 :     SuccessOrExit(err = reader.Read32(&mMessageCounter).StatusCode());
     174              : 
     175        25985 :     if (mMsgFlags.Has(Header::MsgFlagValues::kSourceNodeIdPresent))
     176              :     {
     177              :         uint64_t sourceNodeId;
     178          212 :         SuccessOrExit(err = reader.Read64(&sourceNodeId).StatusCode());
     179          188 :         mSourceNodeId.SetValue(sourceNodeId);
     180              :     }
     181              :     else
     182              :     {
     183        25773 :         mSourceNodeId.ClearValue();
     184              :     }
     185              : 
     186        25961 :     if (!IsSessionTypeValid())
     187              :     {
     188              :         // Reserved.
     189            0 :         SuccessOrExit(err = CHIP_ERROR_INTERNAL);
     190              :     }
     191              : 
     192        25961 :     if (mMsgFlags.HasAll(Header::MsgFlagValues::kDestinationNodeIdPresent, Header::MsgFlagValues::kDestinationGroupIdPresent))
     193              :     {
     194              :         // Reserved.
     195            0 :         SuccessOrExit(err = CHIP_ERROR_INTERNAL);
     196              :     }
     197        25961 :     else if (mMsgFlags.Has(Header::MsgFlagValues::kDestinationNodeIdPresent))
     198              :     {
     199              :         // No need to check if session is Unicast because for MCSP
     200              :         // a destination node ID is present with a group session ID.
     201              :         // Spec 4.9.2.4
     202              :         uint64_t destinationNodeId;
     203          142 :         SuccessOrExit(err = reader.Read64(&destinationNodeId).StatusCode());
     204          134 :         mDestinationNodeId.SetValue(destinationNodeId);
     205          134 :         mDestinationGroupId.ClearValue();
     206              :     }
     207        25819 :     else if (mMsgFlags.Has(Header::MsgFlagValues::kDestinationGroupIdPresent))
     208              :     {
     209           15 :         if (mSessionType != Header::SessionType::kGroupSession)
     210              :         {
     211            2 :             SuccessOrExit(err = CHIP_ERROR_INTERNAL);
     212              :         }
     213              :         uint16_t destinationGroupId;
     214           15 :         SuccessOrExit(err = reader.Read16(&destinationGroupId).StatusCode());
     215           13 :         mDestinationGroupId.SetValue(destinationGroupId);
     216           13 :         mDestinationNodeId.ClearValue();
     217              :     }
     218              :     else
     219              :     {
     220        25804 :         mDestinationNodeId.ClearValue();
     221        25804 :         mDestinationGroupId.ClearValue();
     222              :     }
     223              : 
     224        25951 :     if (mSecFlags.Has(Header::SecFlagValues::kMsgExtensionFlag))
     225              :     {
     226              :         // If present, skip over Message Extension block.
     227              :         // Spec 4.4.1.8. Message Extensions (variable)
     228              :         uint16_t mxLength;
     229            8 :         SuccessOrExit(err = reader.Read16(&mxLength).StatusCode());
     230            8 :         VerifyOrExit(mxLength <= reader.Remaining(), err = CHIP_ERROR_INTERNAL);
     231            8 :         reader.Skip(mxLength);
     232              :     }
     233              : 
     234        25951 :     octets_read = static_cast<uint16_t>(reader.OctetsRead());
     235        25951 :     *decode_len = octets_read;
     236              : 
     237        26025 : exit:
     238              : 
     239        26025 :     return err;
     240              : }
     241              : 
     242         9754 : CHIP_ERROR PacketHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
     243              : {
     244         9754 :     uint16_t headerSize = 0;
     245         9754 :     ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
     246         9754 :     buf->ConsumeHead(headerSize);
     247         9754 :     return CHIP_NO_ERROR;
     248              : }
     249              : 
     250         9751 : CHIP_ERROR PayloadHeader::Decode(const uint8_t * const data, size_t size, uint16_t * decode_len)
     251              : {
     252         9751 :     CHIP_ERROR err = CHIP_NO_ERROR;
     253         9751 :     LittleEndian::Reader reader(data, size);
     254              :     uint8_t header;
     255              :     uint16_t octets_read;
     256              : 
     257         9751 :     SuccessOrExit(err = reader.Read8(&header).Read8(&mMessageType).Read16(&mExchangeID).StatusCode());
     258              : 
     259         9747 :     mExchangeFlags.SetRaw(header);
     260              : 
     261              :     VendorId vendor_id;
     262         9747 :     if (HaveVendorId())
     263              :     {
     264              :         uint16_t vendor_id_raw;
     265           22 :         SuccessOrExit(err = reader.Read16(&vendor_id_raw).StatusCode());
     266           22 :         vendor_id = static_cast<VendorId>(vendor_id_raw);
     267              :     }
     268              :     else
     269              :     {
     270         9725 :         vendor_id = VendorId::Common;
     271              :     }
     272              : 
     273              :     uint16_t protocol_id;
     274         9747 :     SuccessOrExit(err = reader.Read16(&protocol_id).StatusCode());
     275              : 
     276         9745 :     mProtocolID = Protocols::Id(vendor_id, protocol_id);
     277              : 
     278         9745 :     if (mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_AckMsg))
     279              :     {
     280              :         uint32_t ack_message_counter;
     281         7994 :         SuccessOrExit(err = reader.Read32(&ack_message_counter).StatusCode());
     282         7994 :         mAckMessageCounter.SetValue(ack_message_counter);
     283              :     }
     284              :     else
     285              :     {
     286         1751 :         mAckMessageCounter.ClearValue();
     287              :     }
     288              : 
     289         9745 :     if (mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_SecuredExtension))
     290              :     {
     291              :         // If present, skip over Secured Extension block.
     292              :         // Spec 4.4.3.7. Secured Extensions (variable)
     293              :         uint16_t sxLength;
     294            3 :         SuccessOrExit(err = reader.Read16(&sxLength).StatusCode());
     295            3 :         VerifyOrExit(sxLength <= reader.Remaining(), err = CHIP_ERROR_INTERNAL);
     296            3 :         reader.Skip(sxLength);
     297              :     }
     298              : 
     299         9745 :     octets_read = static_cast<uint16_t>(reader.OctetsRead());
     300         9745 :     *decode_len = octets_read;
     301              : 
     302         9751 : exit:
     303              : 
     304         9751 :     return err;
     305              : }
     306              : 
     307         9732 : CHIP_ERROR PayloadHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
     308              : {
     309         9732 :     uint16_t headerSize = 0;
     310         9732 :     ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
     311         9732 :     buf->ConsumeHead(headerSize);
     312         9732 :     return CHIP_NO_ERROR;
     313              : }
     314              : 
     315        29268 : CHIP_ERROR PacketHeader::Encode(uint8_t * data, size_t size, uint16_t * encode_size) const
     316              : {
     317        29268 :     VerifyOrReturnError(size >= EncodeSizeBytes(), CHIP_ERROR_INVALID_ARGUMENT);
     318        29226 :     VerifyOrReturnError(!(mDestinationNodeId.HasValue() && mDestinationGroupId.HasValue()), CHIP_ERROR_INTERNAL);
     319        29225 :     VerifyOrReturnError(encode_size != nullptr, CHIP_ERROR_INTERNAL);
     320        29225 :     VerifyOrReturnError(IsSessionTypeValid(), CHIP_ERROR_INTERNAL);
     321              : 
     322        29225 :     Header::MsgFlags messageFlags = mMsgFlags;
     323        29225 :     messageFlags.Set(Header::MsgFlagValues::kSourceNodeIdPresent, mSourceNodeId.HasValue())
     324        29225 :         .Set(Header::MsgFlagValues::kDestinationNodeIdPresent, mDestinationNodeId.HasValue())
     325        29225 :         .Set(Header::MsgFlagValues::kDestinationGroupIdPresent, mDestinationGroupId.HasValue());
     326              : 
     327        29225 :     uint8_t msgFlags = (kMsgHeaderVersion << kVersionShift) | (messageFlags.Raw() & kMsgFlagsMask);
     328              : 
     329        29225 :     uint8_t * p = data;
     330        29225 :     Write8(p, msgFlags);
     331        29225 :     LittleEndian::Write16(p, mSessionId);
     332        29225 :     Write8(p, mSecFlags.Raw());
     333        29225 :     LittleEndian::Write32(p, mMessageCounter);
     334        29225 :     if (mSourceNodeId.HasValue())
     335              :     {
     336           90 :         LittleEndian::Write64(p, mSourceNodeId.Value());
     337              :     }
     338        29225 :     if (mDestinationNodeId.HasValue())
     339              :     {
     340           62 :         LittleEndian::Write64(p, mDestinationNodeId.Value());
     341              :     }
     342        29163 :     else if (mDestinationGroupId.HasValue())
     343              :     {
     344           10 :         LittleEndian::Write16(p, mDestinationGroupId.Value());
     345              :     }
     346              : 
     347              :     // Written data size provided to caller on success
     348        29225 :     VerifyOrReturnError(p - data == EncodeSizeBytes(), CHIP_ERROR_INTERNAL);
     349        29225 :     *encode_size = static_cast<uint16_t>(p - data);
     350              : 
     351        29225 :     return CHIP_NO_ERROR;
     352              : }
     353              : 
     354         9833 : CHIP_ERROR PacketHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
     355              : {
     356              :     // Note: PayloadHeader::EncodeBeforeData probably needs changes if you
     357              :     // change anything here.
     358         9833 :     uint16_t headerSize = EncodeSizeBytes();
     359         9833 :     VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
     360         9833 :     buf->SetStart(buf->Start() - headerSize);
     361              :     uint16_t actualEncodedHeaderSize;
     362         9833 :     ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
     363         9833 :     VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
     364         9833 :     return CHIP_NO_ERROR;
     365              : }
     366              : 
     367         9832 : CHIP_ERROR PayloadHeader::Encode(uint8_t * data, size_t size, uint16_t * encode_size) const
     368              : {
     369         9832 :     VerifyOrReturnError(size >= EncodeSizeBytes(), CHIP_ERROR_INVALID_ARGUMENT);
     370              : 
     371         9826 :     uint8_t * p          = data;
     372         9826 :     const uint8_t header = mExchangeFlags.Raw();
     373              : 
     374         9826 :     Write8(p, header);
     375         9826 :     Write8(p, mMessageType);
     376         9826 :     LittleEndian::Write16(p, mExchangeID);
     377         9826 :     if (HaveVendorId())
     378              :     {
     379           21 :         LittleEndian::Write16(p, to_underlying(mProtocolID.GetVendorId()));
     380              :     }
     381         9826 :     LittleEndian::Write16(p, mProtocolID.GetProtocolId());
     382         9826 :     if (mAckMessageCounter.HasValue())
     383              :     {
     384         8035 :         LittleEndian::Write32(p, mAckMessageCounter.Value());
     385              :     }
     386              : 
     387              :     // Written data size provided to caller on success
     388         9826 :     VerifyOrReturnError(p - data == EncodeSizeBytes(), CHIP_ERROR_INTERNAL);
     389         9826 :     *encode_size = static_cast<uint16_t>(p - data);
     390              : 
     391         9826 :     return CHIP_NO_ERROR;
     392              : }
     393              : 
     394         9824 : CHIP_ERROR PayloadHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
     395              : {
     396              :     // Note: PacketHeader::EncodeBeforeData probably needs changes if you change
     397              :     // anything here.
     398         9824 :     uint16_t headerSize = EncodeSizeBytes();
     399         9824 :     VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
     400         9824 :     buf->SetStart(buf->Start() - headerSize);
     401              :     uint16_t actualEncodedHeaderSize;
     402         9824 :     ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
     403         9824 :     VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
     404         9824 :     return CHIP_NO_ERROR;
     405              : }
     406              : 
     407         9644 : CHIP_ERROR MessageAuthenticationCode::Decode(const PacketHeader & packetHeader, const uint8_t * const data, size_t size,
     408              :                                              uint16_t * decode_len)
     409              : {
     410         9644 :     const uint16_t taglen = packetHeader.MICTagLength();
     411              : 
     412         9644 :     VerifyOrReturnError(taglen != 0, CHIP_ERROR_WRONG_ENCRYPTION_TYPE_FROM_PEER);
     413         9644 :     VerifyOrReturnError(size >= taglen, CHIP_ERROR_INVALID_ARGUMENT);
     414              : 
     415         9644 :     memcpy(&mTag[0], data, taglen);
     416              : 
     417         9644 :     *decode_len = taglen;
     418              : 
     419         9644 :     return CHIP_NO_ERROR;
     420              : }
     421              : 
     422         9725 : CHIP_ERROR MessageAuthenticationCode::Encode(const PacketHeader & packetHeader, uint8_t * data, size_t size,
     423              :                                              uint16_t * encode_size) const
     424              : {
     425         9725 :     uint8_t * p           = data;
     426         9725 :     const uint16_t taglen = packetHeader.MICTagLength();
     427              : 
     428         9725 :     VerifyOrReturnError(taglen != 0, CHIP_ERROR_WRONG_ENCRYPTION_TYPE);
     429         9725 :     VerifyOrReturnError(size >= taglen, CHIP_ERROR_INVALID_ARGUMENT);
     430              : 
     431         9725 :     memcpy(p, &mTag[0], taglen);
     432              : 
     433              :     // Written data size provided to caller on success
     434         9725 :     *encode_size = taglen;
     435              : 
     436         9725 :     return CHIP_NO_ERROR;
     437              : }
     438              : 
     439              : } // namespace chip
        

Generated by: LCOV version 2.0-1