Matter SDK Coverage Report
Current view: top level - transport/raw - MessageHeader.cpp (source / functions) Coverage Total Hit
Test: SHA:f84fe08d06f240e801b5d923f8a938a9938ca110 Lines: 98.8 % 166 164
Test Date: 2025-02-22 08:08:07 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       100788 : uint16_t PacketHeader::EncodeSizeBytes() const
      93              : {
      94       100788 :     size_t size = kFixedUnencryptedHeaderSizeBytes;
      95              : 
      96       100788 :     if (mSourceNodeId.HasValue())
      97              :     {
      98          355 :         size += kNodeIdSizeBytes;
      99              :     }
     100              : 
     101       100788 :     if (mDestinationNodeId.HasValue())
     102              :     {
     103          240 :         size += kNodeIdSizeBytes;
     104              :     }
     105       100548 :     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       100788 :     return static_cast<uint16_t>(size);
     113              : }
     114              : 
     115        40549 : uint16_t PayloadHeader::EncodeSizeBytes() const
     116              : {
     117        40549 :     size_t size = kEncryptedHeaderSizeBytes;
     118              : 
     119        40549 :     if (HaveVendorId())
     120              :     {
     121           90 :         size += kVendorIdSizeBytes;
     122              :     }
     123              : 
     124        40549 :     if (mAckMessageCounter.HasValue())
     125              :     {
     126        33175 :         size += kAckMessageCounterSizeBytes;
     127              :     }
     128              : 
     129              :     static_assert(kEncryptedHeaderSizeBytes + kVendorIdSizeBytes + kAckMessageCounterSizeBytes <= UINT16_MAX,
     130              :                   "Header size does not fit in uint16_t");
     131        40549 :     return static_cast<uint16_t>(size);
     132              : }
     133              : 
     134        37015 : CHIP_ERROR PacketHeader::DecodeFixedCommon(Encoding::LittleEndian::Reader & reader)
     135              : {
     136        37015 :     CHIP_ERROR err = CHIP_NO_ERROR;
     137              :     int version;
     138              : 
     139              :     uint8_t msgFlags;
     140        37015 :     SuccessOrExit(err = reader.Read8(&msgFlags).StatusCode());
     141        37010 :     version = ((msgFlags & kVersionMask) >> kVersionShift);
     142        37010 :     VerifyOrExit(version == kMsgHeaderVersion, err = CHIP_ERROR_VERSION_MISMATCH);
     143        37010 :     SetMessageFlags(msgFlags);
     144              : 
     145        37010 :     SuccessOrExit(err = reader.Read16(&mSessionId).StatusCode());
     146              : 
     147              :     uint8_t securityFlags;
     148        37000 :     SuccessOrExit(err = reader.Read8(&securityFlags).StatusCode());
     149        36995 :     SetSecurityFlags(securityFlags);
     150              : 
     151        37015 : exit:
     152              : 
     153        37015 :     return err;
     154              : }
     155              : 
     156        10084 : CHIP_ERROR PacketHeader::DecodeFixed(const System::PacketBufferHandle & buf)
     157              : {
     158        10084 :     const uint8_t * const data = buf->Start();
     159        10084 :     size_t size                = buf->DataLength();
     160        10084 :     LittleEndian::Reader reader(data, size);
     161        10084 :     return DecodeFixedCommon(reader);
     162              : }
     163              : 
     164        26931 : CHIP_ERROR PacketHeader::Decode(const uint8_t * const data, size_t size, uint16_t * decode_len)
     165              : {
     166        26931 :     CHIP_ERROR err = CHIP_NO_ERROR;
     167        26931 :     LittleEndian::Reader reader(data, size);
     168              :     // TODO: De-uint16-ify everything related to this library
     169              :     uint16_t octets_read;
     170              : 
     171        26931 :     SuccessOrExit(err = DecodeFixedCommon(reader));
     172              : 
     173        26911 :     SuccessOrExit(err = reader.Read32(&mMessageCounter).StatusCode());
     174              : 
     175        26891 :     if (mMsgFlags.Has(Header::MsgFlagValues::kSourceNodeIdPresent))
     176              :     {
     177              :         uint64_t sourceNodeId;
     178          215 :         SuccessOrExit(err = reader.Read64(&sourceNodeId).StatusCode());
     179          191 :         mSourceNodeId.SetValue(sourceNodeId);
     180              :     }
     181              :     else
     182              :     {
     183        26676 :         mSourceNodeId.ClearValue();
     184              :     }
     185              : 
     186        26867 :     if (!IsSessionTypeValid())
     187              :     {
     188              :         // Reserved.
     189            0 :         SuccessOrExit(err = CHIP_ERROR_INTERNAL);
     190              :     }
     191              : 
     192        26867 :     if (mMsgFlags.HasAll(Header::MsgFlagValues::kDestinationNodeIdPresent, Header::MsgFlagValues::kDestinationGroupIdPresent))
     193              :     {
     194              :         // Reserved.
     195            0 :         SuccessOrExit(err = CHIP_ERROR_INTERNAL);
     196              :     }
     197        26867 :     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          143 :         SuccessOrExit(err = reader.Read64(&destinationNodeId).StatusCode());
     204          135 :         mDestinationNodeId.SetValue(destinationNodeId);
     205          135 :         mDestinationGroupId.ClearValue();
     206              :     }
     207        26724 :     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        26709 :         mDestinationNodeId.ClearValue();
     221        26709 :         mDestinationGroupId.ClearValue();
     222              :     }
     223              : 
     224        26857 :     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        26857 :     octets_read = static_cast<uint16_t>(reader.OctetsRead());
     235        26857 :     *decode_len = octets_read;
     236              : 
     237        26931 : exit:
     238              : 
     239        26931 :     return err;
     240              : }
     241              : 
     242        10092 : CHIP_ERROR PacketHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
     243              : {
     244        10092 :     uint16_t headerSize = 0;
     245        10092 :     ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
     246        10092 :     buf->ConsumeHead(headerSize);
     247        10092 :     return CHIP_NO_ERROR;
     248              : }
     249              : 
     250        10089 : CHIP_ERROR PayloadHeader::Decode(const uint8_t * const data, size_t size, uint16_t * decode_len)
     251              : {
     252        10089 :     CHIP_ERROR err = CHIP_NO_ERROR;
     253        10089 :     LittleEndian::Reader reader(data, size);
     254              :     uint8_t header;
     255              :     uint16_t octets_read;
     256              : 
     257        10089 :     SuccessOrExit(err = reader.Read8(&header).Read8(&mMessageType).Read16(&mExchangeID).StatusCode());
     258              : 
     259        10085 :     mExchangeFlags.SetRaw(header);
     260              : 
     261              :     VendorId vendor_id;
     262        10085 :     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        10063 :         vendor_id = VendorId::Common;
     271              :     }
     272              : 
     273              :     uint16_t protocol_id;
     274        10085 :     SuccessOrExit(err = reader.Read16(&protocol_id).StatusCode());
     275              : 
     276        10083 :     mProtocolID = Protocols::Id(vendor_id, protocol_id);
     277              : 
     278        10083 :     if (mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_AckMsg))
     279              :     {
     280              :         uint32_t ack_message_counter;
     281         8263 :         SuccessOrExit(err = reader.Read32(&ack_message_counter).StatusCode());
     282         8263 :         mAckMessageCounter.SetValue(ack_message_counter);
     283              :     }
     284              :     else
     285              :     {
     286         1820 :         mAckMessageCounter.ClearValue();
     287              :     }
     288              : 
     289        10083 :     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        10083 :     octets_read = static_cast<uint16_t>(reader.OctetsRead());
     300        10083 :     *decode_len = octets_read;
     301              : 
     302        10089 : exit:
     303              : 
     304        10089 :     return err;
     305              : }
     306              : 
     307        10070 : CHIP_ERROR PayloadHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
     308              : {
     309        10070 :     uint16_t headerSize = 0;
     310        10070 :     ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
     311        10070 :     buf->ConsumeHead(headerSize);
     312        10070 :     return CHIP_NO_ERROR;
     313              : }
     314              : 
     315        30280 : CHIP_ERROR PacketHeader::Encode(uint8_t * data, size_t size, uint16_t * encode_size) const
     316              : {
     317        30280 :     VerifyOrReturnError(size >= EncodeSizeBytes(), CHIP_ERROR_INVALID_ARGUMENT);
     318        30238 :     VerifyOrReturnError(!(mDestinationNodeId.HasValue() && mDestinationGroupId.HasValue()), CHIP_ERROR_INTERNAL);
     319        30237 :     VerifyOrReturnError(encode_size != nullptr, CHIP_ERROR_INTERNAL);
     320        30237 :     VerifyOrReturnError(IsSessionTypeValid(), CHIP_ERROR_INTERNAL);
     321              : 
     322        30237 :     Header::MsgFlags messageFlags = mMsgFlags;
     323        30237 :     messageFlags.Set(Header::MsgFlagValues::kSourceNodeIdPresent, mSourceNodeId.HasValue())
     324        30237 :         .Set(Header::MsgFlagValues::kDestinationNodeIdPresent, mDestinationNodeId.HasValue())
     325        30237 :         .Set(Header::MsgFlagValues::kDestinationGroupIdPresent, mDestinationGroupId.HasValue());
     326              : 
     327        30237 :     uint8_t msgFlags = (kMsgHeaderVersion << kVersionShift) | (messageFlags.Raw() & kMsgFlagsMask);
     328              : 
     329        30237 :     uint8_t * p = data;
     330        30237 :     Write8(p, msgFlags);
     331        30237 :     LittleEndian::Write16(p, mSessionId);
     332        30237 :     Write8(p, mSecFlags.Raw());
     333        30237 :     LittleEndian::Write32(p, mMessageCounter);
     334        30237 :     if (mSourceNodeId.HasValue())
     335              :     {
     336           91 :         LittleEndian::Write64(p, mSourceNodeId.Value());
     337              :     }
     338        30237 :     if (mDestinationNodeId.HasValue())
     339              :     {
     340           63 :         LittleEndian::Write64(p, mDestinationNodeId.Value());
     341              :     }
     342        30174 :     else if (mDestinationGroupId.HasValue())
     343              :     {
     344           10 :         LittleEndian::Write16(p, mDestinationGroupId.Value());
     345              :     }
     346              : 
     347              :     // Written data size provided to caller on success
     348        30237 :     VerifyOrReturnError(p - data == EncodeSizeBytes(), CHIP_ERROR_INTERNAL);
     349        30237 :     *encode_size = static_cast<uint16_t>(p - data);
     350              : 
     351        30237 :     return CHIP_NO_ERROR;
     352              : }
     353              : 
     354        10172 : CHIP_ERROR PacketHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
     355              : {
     356              :     // Note: PayloadHeader::EncodeBeforeData probably needs changes if you
     357              :     // change anything here.
     358        10172 :     uint16_t headerSize = EncodeSizeBytes();
     359        10172 :     VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
     360        10172 :     buf->SetStart(buf->Start() - headerSize);
     361              :     uint16_t actualEncodedHeaderSize;
     362        10172 :     ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
     363        10172 :     VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
     364        10172 :     return CHIP_NO_ERROR;
     365              : }
     366              : 
     367        10171 : CHIP_ERROR PayloadHeader::Encode(uint8_t * data, size_t size, uint16_t * encode_size) const
     368              : {
     369        10171 :     VerifyOrReturnError(size >= EncodeSizeBytes(), CHIP_ERROR_INVALID_ARGUMENT);
     370              : 
     371        10165 :     uint8_t * p          = data;
     372        10165 :     const uint8_t header = mExchangeFlags.Raw();
     373              : 
     374        10165 :     Write8(p, header);
     375        10165 :     Write8(p, mMessageType);
     376        10165 :     LittleEndian::Write16(p, mExchangeID);
     377        10165 :     if (HaveVendorId())
     378              :     {
     379           21 :         LittleEndian::Write16(p, to_underlying(mProtocolID.GetVendorId()));
     380              :     }
     381        10165 :     LittleEndian::Write16(p, mProtocolID.GetProtocolId());
     382        10165 :     if (mAckMessageCounter.HasValue())
     383              :     {
     384         8304 :         LittleEndian::Write32(p, mAckMessageCounter.Value());
     385              :     }
     386              : 
     387              :     // Written data size provided to caller on success
     388        10165 :     VerifyOrReturnError(p - data == EncodeSizeBytes(), CHIP_ERROR_INTERNAL);
     389        10165 :     *encode_size = static_cast<uint16_t>(p - data);
     390              : 
     391        10165 :     return CHIP_NO_ERROR;
     392              : }
     393              : 
     394        10163 : CHIP_ERROR PayloadHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
     395              : {
     396              :     // Note: PacketHeader::EncodeBeforeData probably needs changes if you change
     397              :     // anything here.
     398        10163 :     uint16_t headerSize = EncodeSizeBytes();
     399        10163 :     VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
     400        10163 :     buf->SetStart(buf->Start() - headerSize);
     401              :     uint16_t actualEncodedHeaderSize;
     402        10163 :     ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
     403        10163 :     VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
     404        10163 :     return CHIP_NO_ERROR;
     405              : }
     406              : 
     407         9980 : CHIP_ERROR MessageAuthenticationCode::Decode(const PacketHeader & packetHeader, const uint8_t * const data, size_t size,
     408              :                                              uint16_t * decode_len)
     409              : {
     410         9980 :     const uint16_t taglen = packetHeader.MICTagLength();
     411              : 
     412         9980 :     VerifyOrReturnError(taglen != 0, CHIP_ERROR_WRONG_ENCRYPTION_TYPE_FROM_PEER);
     413         9980 :     VerifyOrReturnError(size >= taglen, CHIP_ERROR_INVALID_ARGUMENT);
     414              : 
     415         9980 :     memcpy(&mTag[0], data, taglen);
     416              : 
     417         9980 :     *decode_len = taglen;
     418              : 
     419         9980 :     return CHIP_NO_ERROR;
     420              : }
     421              : 
     422        10062 : CHIP_ERROR MessageAuthenticationCode::Encode(const PacketHeader & packetHeader, uint8_t * data, size_t size,
     423              :                                              uint16_t * encode_size) const
     424              : {
     425        10062 :     uint8_t * p           = data;
     426        10062 :     const uint16_t taglen = packetHeader.MICTagLength();
     427              : 
     428        10062 :     VerifyOrReturnError(taglen != 0, CHIP_ERROR_WRONG_ENCRYPTION_TYPE);
     429        10062 :     VerifyOrReturnError(size >= taglen, CHIP_ERROR_INVALID_ARGUMENT);
     430              : 
     431        10062 :     memcpy(p, &mTag[0], taglen);
     432              : 
     433              :     // Written data size provided to caller on success
     434        10062 :     *encode_size = taglen;
     435              : 
     436        10062 :     return CHIP_NO_ERROR;
     437              : }
     438              : 
     439              : } // namespace chip
        

Generated by: LCOV version 2.0-1