3 * Copyright (c) 2020-2021 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * This file contains the implementation the chip message header
21 * encode/decode classes.
24 #include "MessageHeader.h"
30 #include <type_traits>
32 #include <core/CHIPError.h>
33 #include <support/BufferReader.h>
34 #include <support/CodeUtils.h>
36 /**********************************************
37 * Header format (little endian):
39 * -------- Unencrypted header -----------------------------------------------------
40 * 16 bit: | VERSION: 4 bit | FLAGS: 4 bit | ENCRYPTTYPE: 4 bit | RESERVED: 4 bit |
41 * 32 bit: | MESSAGE_ID |
42 * 64 bit: | SOURCE_NODE_ID (iff source node flag is set) |
43 * 64 bit: | DEST_NODE_ID (iff destination node flag is set) |
44 * 16 bit: | Encryption Key ID |
45 * 16 bit: | Payload Length |
46 * -------- Encrypted header -------------------------------------------------------
47 * 8 bit: | Exchange Header |
48 * 8 bit: | Message Type |
49 * 16 bit: | Exchange ID |
50 * 16 bit: | Optional Vendor ID |
51 * 16 bit: | Protocol 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 |
58 **********************************************/
63 using namespace chip::Encoding;
65 /// size of the fixed portion of the header
66 constexpr size_t kFixedUnencryptedHeaderSizeBytes = 8;
68 /// size of the encrypted portion of the header
69 constexpr size_t kEncryptedHeaderSizeBytes = 6;
71 /// size of a serialized node id inside a header
72 constexpr size_t kNodeIdSizeBytes = 8;
74 /// size of a serialized vendor id inside a header
75 constexpr size_t kVendorIdSizeBytes = 2;
77 /// size of a serialized ack id inside a header
78 constexpr size_t kAckIdSizeBytes = 4;
80 /// Mask to extract just the version part from a 16bit header prefix.
81 constexpr uint16_t kVersionMask = 0xF000;
82 /// Shift to convert to/from a masked version 16bit value to a 4bit version.
83 constexpr int kVersionShift = 12;
85 /// Mask to extract just the encryption type part from a 16bit header prefix.
86 constexpr uint16_t kEncryptionTypeMask = 0xF0;
87 /// Shift to convert to/from a masked encryption type 16bit value to a 4bit encryption type.
88 constexpr int kEncryptionTypeShift = 4;
92 uint16_t PacketHeader::EncodeSizeBytes() const
94 size_t size = kFixedUnencryptedHeaderSizeBytes;
96 if (mSourceNodeId.HasValue())
98 size += kNodeIdSizeBytes;
101 if (mDestinationNodeId.HasValue())
103 size += kNodeIdSizeBytes;
106 static_assert(kFixedUnencryptedHeaderSizeBytes + kNodeIdSizeBytes + kNodeIdSizeBytes <= UINT16_MAX,
107 "Header size does not fit in uint16_t");
108 return static_cast<uint16_t>(size);
111 uint16_t PayloadHeader::EncodeSizeBytes() const
113 size_t size = kEncryptedHeaderSizeBytes;
117 size += kVendorIdSizeBytes;
120 if (mAckId.HasValue())
122 size += kAckIdSizeBytes;
125 static_assert(kEncryptedHeaderSizeBytes + kVendorIdSizeBytes + kAckIdSizeBytes <= UINT16_MAX,
126 "Header size does not fit in uint16_t");
127 return static_cast<uint16_t>(size);
130 uint16_t MessageAuthenticationCode::TagLenForEncryptionType(Header::EncryptionType encType)
134 case Header::EncryptionType::kAESCCMTagLen8:
137 case Header::EncryptionType::kAESCCMTagLen12:
140 case Header::EncryptionType::kAESCCMTagLen16:
148 CHIP_ERROR PacketHeader::Decode(const uint8_t * const data, uint16_t size, uint16_t * decode_len)
150 CHIP_ERROR err = CHIP_NO_ERROR;
151 LittleEndian::Reader reader(data, size);
153 uint16_t octets_read;
156 err = reader.Read16(&header).StatusCode();
158 version = ((header & kVersionMask) >> kVersionShift);
159 VerifyOrExit(version == kHeaderVersion, err = CHIP_ERROR_VERSION_MISMATCH);
161 mEncryptionType = static_cast<Header::EncryptionType>((header & kEncryptionTypeMask) >> kEncryptionTypeShift);
162 mFlags.SetRaw(header & Header::kFlagsMask);
164 err = reader.Read32(&mMessageId).StatusCode();
167 if (mFlags.Has(Header::FlagValues::kSourceNodeIdPresent))
169 uint64_t sourceNodeId;
170 err = reader.Read64(&sourceNodeId).StatusCode();
172 mSourceNodeId.SetValue(sourceNodeId);
176 mSourceNodeId.ClearValue();
179 if (mFlags.Has(Header::FlagValues::kDestinationNodeIdPresent))
181 uint64_t destinationNodeId;
182 err = reader.Read64(&destinationNodeId).StatusCode();
184 mDestinationNodeId.SetValue(destinationNodeId);
188 mDestinationNodeId.ClearValue();
191 err = reader.Read16(&mEncryptionKeyID).StatusCode();
194 octets_read = reader.OctetsRead();
195 VerifyOrExit(octets_read == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL);
196 *decode_len = octets_read;
203 CHIP_ERROR PacketHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
205 uint16_t headerSize = 0;
206 ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
207 buf->ConsumeHead(headerSize);
208 return CHIP_NO_ERROR;
211 CHIP_ERROR PayloadHeader::Decode(const uint8_t * const data, uint16_t size, uint16_t * decode_len)
213 CHIP_ERROR err = CHIP_NO_ERROR;
214 LittleEndian::Reader reader(data, size);
216 uint16_t octets_read;
218 err = reader.Read8(&header).Read8(&mMessageType).Read16(&mExchangeID).StatusCode();
221 mExchangeFlags.SetRaw(header);
226 uint16_t vendor_id_raw;
227 err = reader.Read16(&vendor_id_raw).StatusCode();
229 vendor_id = static_cast<VendorId>(vendor_id_raw);
233 vendor_id = VendorId::Common;
236 uint16_t protocol_id;
237 err = reader.Read16(&protocol_id).StatusCode();
240 mProtocolID = Protocols::Id(vendor_id, protocol_id);
242 if (mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_AckMsg))
245 err = reader.Read32(&ack_id).StatusCode();
247 mAckId.SetValue(ack_id);
254 octets_read = reader.OctetsRead();
255 VerifyOrExit(octets_read == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL);
256 *decode_len = octets_read;
263 CHIP_ERROR PayloadHeader::DecodeAndConsume(const System::PacketBufferHandle & buf)
265 uint16_t headerSize = 0;
266 ReturnErrorOnFailure(Decode(buf->Start(), buf->DataLength(), &headerSize));
267 buf->ConsumeHead(headerSize);
268 return CHIP_NO_ERROR;
271 CHIP_ERROR PacketHeader::Encode(uint8_t * data, uint16_t size, uint16_t * encode_size) const
273 CHIP_ERROR err = CHIP_NO_ERROR;
275 uint16_t header = kHeaderVersion << kVersionShift;
277 VerifyOrExit(size >= EncodeSizeBytes(), err = CHIP_ERROR_INVALID_ARGUMENT);
280 Header::Flags encodeFlags = mFlags;
281 encodeFlags.Set(Header::FlagValues::kSourceNodeIdPresent, mSourceNodeId.HasValue())
282 .Set(Header::FlagValues::kDestinationNodeIdPresent, mDestinationNodeId.HasValue());
284 header = header | encodeFlags.Raw();
287 header |= (static_cast<uint16_t>(static_cast<uint16_t>(mEncryptionType) << kEncryptionTypeShift) & kEncryptionTypeMask);
289 LittleEndian::Write16(p, header);
290 LittleEndian::Write32(p, mMessageId);
291 if (mSourceNodeId.HasValue())
293 LittleEndian::Write64(p, mSourceNodeId.Value());
295 if (mDestinationNodeId.HasValue())
297 LittleEndian::Write64(p, mDestinationNodeId.Value());
300 LittleEndian::Write16(p, mEncryptionKeyID);
302 // Written data size provided to caller on success
303 VerifyOrExit(p - data == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL);
304 *encode_size = static_cast<uint16_t>(p - data);
310 CHIP_ERROR PacketHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
312 // Note: PayloadHeader::EncodeBeforeData probably needs changes if you
313 // change anything here.
314 uint16_t headerSize = EncodeSizeBytes();
315 VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
316 buf->SetStart(buf->Start() - headerSize);
317 uint16_t actualEncodedHeaderSize;
318 ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
319 VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
320 return CHIP_NO_ERROR;
323 CHIP_ERROR PayloadHeader::Encode(uint8_t * data, uint16_t size, uint16_t * encode_size) const
325 CHIP_ERROR err = CHIP_NO_ERROR;
327 const uint8_t header = mExchangeFlags.Raw();
329 VerifyOrExit(size >= EncodeSizeBytes(), err = CHIP_ERROR_INVALID_ARGUMENT);
332 Write8(p, mMessageType);
333 LittleEndian::Write16(p, mExchangeID);
336 LittleEndian::Write16(p, static_cast<std::underlying_type_t<VendorId>>(mProtocolID.GetVendorId()));
338 LittleEndian::Write16(p, mProtocolID.GetProtocolId());
339 if (mAckId.HasValue())
341 LittleEndian::Write32(p, mAckId.Value());
344 // Written data size provided to caller on success
345 VerifyOrExit(p - data == EncodeSizeBytes(), err = CHIP_ERROR_INTERNAL);
346 *encode_size = static_cast<uint16_t>(p - data);
352 CHIP_ERROR PayloadHeader::EncodeBeforeData(const System::PacketBufferHandle & buf) const
354 // Note: PacketHeader::EncodeBeforeData probably needs changes if you change
356 uint16_t headerSize = EncodeSizeBytes();
357 VerifyOrReturnError(buf->EnsureReservedSize(headerSize), CHIP_ERROR_NO_MEMORY);
358 buf->SetStart(buf->Start() - headerSize);
359 uint16_t actualEncodedHeaderSize;
360 ReturnErrorOnFailure(EncodeAtStart(buf, &actualEncodedHeaderSize));
361 VerifyOrReturnError(actualEncodedHeaderSize == headerSize, CHIP_ERROR_INTERNAL);
362 return CHIP_NO_ERROR;
365 CHIP_ERROR MessageAuthenticationCode::Decode(const PacketHeader & packetHeader, const uint8_t * const data, uint16_t size,
366 uint16_t * decode_len)
368 CHIP_ERROR err = CHIP_NO_ERROR;
369 const uint8_t * p = data;
370 const uint16_t taglen = TagLenForEncryptionType(packetHeader.GetEncryptionType());
372 VerifyOrExit(taglen != 0, err = CHIP_ERROR_WRONG_ENCRYPTION_TYPE_FROM_PEER);
373 VerifyOrExit(size >= taglen, err = CHIP_ERROR_INVALID_ARGUMENT);
375 memcpy(&mTag[0], p, taglen);
377 *decode_len = taglen;
384 CHIP_ERROR MessageAuthenticationCode::Encode(const PacketHeader & packetHeader, uint8_t * data, uint16_t size,
385 uint16_t * encode_size) const
387 CHIP_ERROR err = CHIP_NO_ERROR;
389 const uint16_t taglen = TagLenForEncryptionType(packetHeader.GetEncryptionType());
391 VerifyOrExit(taglen != 0, err = CHIP_ERROR_WRONG_ENCRYPTION_TYPE);
392 VerifyOrExit(size >= taglen, err = CHIP_ERROR_INVALID_ARGUMENT);
394 memcpy(p, &mTag[0], taglen);
396 // Written data size provided to caller on success
397 *encode_size = taglen;