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 defines CHIP binary header encode/decode.
29 #include <type_traits>
31 #include <core/CHIPError.h>
32 #include <core/Optional.h>
33 #include <protocols/Protocols.h>
34 #include <support/BitFlags.h>
35 #include <system/SystemPacketBuffer.h>
39 /// Convenience type to make it clear a number represents a node id.
40 typedef uint64_t NodeId;
42 static constexpr NodeId kUndefinedNodeId = 0ULL;
43 static constexpr NodeId kAnyNodeId = 0xFFFFFFFFFFFFFFFFULL;
44 static constexpr size_t kMaxTagLen = 16;
46 typedef int PacketHeaderFlags;
50 enum class EncryptionType
59 * The CHIP Exchange header flag bits.
61 enum class ExFlagValues : uint8_t
63 /// Set when current message is sent by the initiator of an exchange.
64 kExchangeFlag_Initiator = 0x01,
66 /// Set when current message is an acknowledgment for a previously received message.
67 kExchangeFlag_AckMsg = 0x02,
69 /// Set when current message is requesting an acknowledgment from the recipient.
70 kExchangeFlag_NeedsAck = 0x04,
72 /// Set when a vendor id is prepended to the Message Protocol Id field.
73 kExchangeFlag_VendorIdPresent = 0x10,
76 enum class InternalFlagValues : uint8_t
78 // Header flag indicates that the peer's group key message counter is not synchronized.
79 kPeerGroupMsgIdNotSynchronized = 0x01,
82 enum class FlagValues : uint16_t
84 /// Header flag specifying that a destination node id is included in the header.
85 kDestinationNodeIdPresent = 0x0100,
87 /// Header flag specifying that a source node id is included in the header.
88 kSourceNodeIdPresent = 0x0200,
90 /// Header flag specifying that it is a control message for secure session.
91 kSecureSessionControlMessage = 0x0800,
93 /// Header flag specifying that it is a encrypted message.
98 using Flags = BitFlags<FlagValues>;
99 using ExFlags = BitFlags<ExFlagValues>;
100 using InternalFlags = BitFlags<InternalFlagValues>;
102 // Header is a 16-bit value of the form
103 // | 4 bit | 4 bit |8 bit Security Flags|
104 // +---------+-------+--------------------|
105 // | version | Flags | P | C |Reserved| E |
107 // | +----------------Control message (TODO: Implement this)
108 // +--------------------Privacy enhancements (TODO: Implement this)
109 static constexpr uint16_t kFlagsMask = 0x0F01;
111 } // namespace Header
114 * Handles encoding/decoding of CHIP packet message headers.
116 * Packet headers are **UNENCRYPTED** and are placed at the start of
123 * Gets the message id set in the header.
125 * Message IDs are expecte to monotonically increase by one for each mesage
126 * that has been sent.
128 uint32_t GetMessageId() const { return mMessageId; }
131 * Gets the source node id in the current message.
133 * NOTE: the source node id is optional and may be missing.
135 const Optional<NodeId> & GetSourceNodeId() const { return mSourceNodeId; }
138 * Gets the destination node id in the current message.
140 * NOTE: the destination node id is optional and may be missing.
142 const Optional<NodeId> & GetDestinationNodeId() const { return mDestinationNodeId; }
144 uint16_t GetEncryptionKeyID() const { return mEncryptionKeyID; }
146 Header::Flags & GetFlags() { return mFlags; }
147 const Header::Flags & GetFlags() const { return mFlags; }
149 /** Check if it's a secure session control message. */
150 bool IsSecureSessionControlMsg() const { return mFlags.Has(Header::FlagValues::kSecureSessionControlMessage); }
152 /** Check if the peer's group key message counter is not synchronized. */
153 bool IsPeerGroupMsgIdNotSynchronized() const
155 return mInternalFlags.Has(Header::InternalFlagValues::kPeerGroupMsgIdNotSynchronized);
158 Header::EncryptionType GetEncryptionType() const { return mEncryptionType; }
160 PacketHeader & SetSecureSessionControlMsg(bool value)
162 mFlags.Set(Header::FlagValues::kSecureSessionControlMessage, value);
166 PacketHeader & SetPeerGroupMsgIdNotSynchronized(bool value)
168 mInternalFlags.Set(Header::InternalFlagValues::kPeerGroupMsgIdNotSynchronized, value);
172 PacketHeader & SetSourceNodeId(NodeId id)
174 mSourceNodeId.SetValue(id);
175 mFlags.Set(Header::FlagValues::kSourceNodeIdPresent);
179 PacketHeader & SetSourceNodeId(Optional<NodeId> id)
182 mFlags.Set(Header::FlagValues::kSourceNodeIdPresent, id.HasValue());
186 PacketHeader & ClearSourceNodeId()
188 mSourceNodeId.ClearValue();
189 mFlags.Clear(Header::FlagValues::kSourceNodeIdPresent);
193 PacketHeader & SetDestinationNodeId(NodeId id)
195 mDestinationNodeId.SetValue(id);
196 mFlags.Set(Header::FlagValues::kDestinationNodeIdPresent);
200 PacketHeader & SetDestinationNodeId(Optional<NodeId> id)
202 mDestinationNodeId = id;
203 mFlags.Set(Header::FlagValues::kDestinationNodeIdPresent, id.HasValue());
207 PacketHeader & ClearDestinationNodeId()
209 mDestinationNodeId.ClearValue();
210 mFlags.Clear(Header::FlagValues::kDestinationNodeIdPresent);
214 PacketHeader & SetEncryptionKeyID(uint16_t id)
216 mEncryptionKeyID = id;
220 PacketHeader & SetMessageId(uint32_t id)
226 PacketHeader & SetEncryptionType(Header::EncryptionType type)
228 mEncryptionType = type;
233 * A call to `Encode` will require at least this many bytes on the current
234 * object to be successful.
236 * @return the number of bytes needed in a buffer to be able to Encode.
238 uint16_t EncodeSizeBytes() const;
241 * Decodes a header from the given buffer.
243 * @param data - the buffer to read from
244 * @param size - bytes available in the buffer
245 * @param decode_size - number of bytes read from the buffer to decode the
248 * @return CHIP_NO_ERROR on success.
251 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
252 * CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
254 CHIP_ERROR Decode(const uint8_t * data, uint16_t size, uint16_t * decode_size);
257 * A version of Decode that uses the type system to determine available
260 template <uint16_t N>
261 inline CHIP_ERROR Decode(const uint8_t (&data)[N], uint16_t * decode_size)
263 return Decode(data, N, decode_size);
267 * A version of Decode that decodes from the start of a PacketBuffer and
268 * consumes the bytes we decoded from.
270 CHIP_ERROR DecodeAndConsume(const System::PacketBufferHandle & buf);
273 * Encodes a header into the given buffer.
275 * @param data - the buffer to write to
276 * @param size - space available in the buffer (in bytes)
277 * @param encode_size - number of bytes written to the buffer.
279 * @return CHIP_NO_ERROR on success.
282 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
284 CHIP_ERROR Encode(uint8_t * data, uint16_t size, uint16_t * encode_size) const;
287 * A version of Encode that uses the type system to determine available
291 inline CHIP_ERROR Encode(uint8_t (&data)[N], uint16_t * encode_size) const
293 return Encode(data, N, encode_size);
297 * A version of Encode that encodes into a PacketBuffer before the
298 * PacketBuffer's current data.
300 CHIP_ERROR EncodeBeforeData(const System::PacketBufferHandle & buf) const;
303 * A version of Encode that encodes into a PacketBuffer at the start of the
304 * current data space. This assumes that someone has already preallocated
305 * space for the header.
307 inline CHIP_ERROR EncodeAtStart(const System::PacketBufferHandle & buf, uint16_t * encode_size) const
309 return Encode(buf->Start(), buf->DataLength(), encode_size);
313 /// Represents the current encode/decode header version
314 static constexpr int kHeaderVersion = 2;
316 /// Value expected to be incremented for each message sent.
317 uint32_t mMessageId = 0;
319 /// What node the message originated from
320 Optional<NodeId> mSourceNodeId;
322 /// Intended recipient of the message.
323 Optional<NodeId> mDestinationNodeId;
325 /// Encryption Key ID
326 uint16_t mEncryptionKeyID = 0;
328 /// Message flags read from the message.
329 Header::Flags mFlags;
331 /// Message flags not encoded into the packet sent over wire.
332 Header::InternalFlags mInternalFlags;
334 /// Represents encryption type used for encrypting current packet
335 Header::EncryptionType mEncryptionType = Header::EncryptionType::kAESCCMTagLen16;
339 * Handles encoding/decoding of CHIP payload headers.
341 * Payload headers are **ENCRYPTED** and are placed at the start of
342 * an encrypted message payload.
347 PayloadHeader & operator=(const PayloadHeader &) = default;
350 * Gets the vendor id in the current message.
352 * NOTE: the vendor id is optional and may be missing.
354 const Optional<uint16_t> & GetVendorId() const { return mVendorId; }
356 /** Get the Session ID from this header. */
357 uint16_t GetExchangeID() const { return mExchangeID; }
359 /** Get the Protocol ID from this header. */
360 uint16_t GetProtocolID() const { return mProtocolID; }
362 /** Get the secure msg type from this header. */
363 uint8_t GetMessageType() const { return mMessageType; }
365 /** Check whether the header has a given secure message type */
366 bool HasMessageType(uint8_t type) const { return mMessageType == type; }
367 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
368 bool HasMessageType(MessageType type) const
370 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
371 return mProtocolID == Protocols::MessageTypeTraits<MessageType>::ProtocolId && HasMessageType(static_cast<uint8_t>(type));
375 * Gets the Acknowledged Message Counter from this header.
377 * NOTE: the Acknowledged Message Counter is optional and may be missing.
379 const Optional<uint32_t> & GetAckId() const { return mAckId; }
381 /** Set the vendor id for this header. */
382 PayloadHeader & SetVendorId(uint16_t id)
384 mVendorId.SetValue(id);
385 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_VendorIdPresent);
390 /** Set the vendor id for this header. */
391 PayloadHeader & SetVendorId(Optional<uint16_t> id)
394 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_VendorIdPresent, id.HasValue());
399 /** Clear the vendor id for this header. */
400 PayloadHeader & ClearVendorId()
402 mVendorId.ClearValue();
408 * Set the message type for this header. This requires setting the protocol
409 * id as well, because the meaning of a message type is only relevant given
410 * a specific protocol.
412 * This should only be used for cases when we don't have a strongly typed
413 * message type and hence can't automatically determine the protocol from
416 PayloadHeader & SetMessageType(uint16_t protocol, uint8_t type)
418 mProtocolID = protocol;
423 /** Set the secure message type, with the protocol id derived from the
425 template <typename MessageType, typename = std::enable_if_t<std::is_enum<MessageType>::value>>
426 PayloadHeader & SetMessageType(MessageType type)
428 static_assert(std::is_same<std::underlying_type_t<MessageType>, uint8_t>::value, "Enum is wrong size; cast is not safe");
429 mMessageType = static_cast<uint8_t>(type);
430 mProtocolID = Protocols::MessageTypeTraits<MessageType>::ProtocolId;
434 /** Set the security session ID for this header. */
435 PayloadHeader & SetExchangeID(uint16_t id)
441 /** Set the Initiator flag bit. */
442 PayloadHeader & SetInitiator(bool inInitiator)
444 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_Initiator, inInitiator);
448 PayloadHeader & SetAckId(uint32_t id)
451 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_AckMsg);
455 /** Set the AckMsg flag bit. */
456 PayloadHeader & SetAckId(Optional<uint32_t> id)
459 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_AckMsg, id.HasValue());
463 /** Set the NeedsAck flag bit. */
464 PayloadHeader & SetNeedsAck(bool inNeedsAck)
466 mExchangeFlags.Set(Header::ExFlagValues::kExchangeFlag_NeedsAck, inNeedsAck);
471 * Determine whether the initiator of the exchange.
473 * @return Returns 'true' if it is the initiator, else 'false'.
476 bool IsInitiator() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_Initiator); }
479 * Determine whether the current message is an acknowledgment for a previously received message.
481 * @return Returns 'true' if current message is an acknowledgment, else 'false'.
484 bool IsAckMsg() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_AckMsg); }
487 * Determine whether current message is requesting an acknowledgment from the recipient.
489 * @return Returns 'true' if the current message is requesting an acknowledgment from the recipient, else 'false'.
492 bool NeedsAck() const { return mExchangeFlags.Has(Header::ExFlagValues::kExchangeFlag_NeedsAck); }
495 * A call to `Encode` will require at least this many bytes on the current
496 * object to be successful.
498 * @return the number of bytes needed in a buffer to be able to Encode.
500 uint16_t EncodeSizeBytes() const;
503 * Decodes the encrypted header fields from the given buffer.
505 * @param data - the buffer to read from
506 * @param size - bytes available in the buffer
507 * @param decode_size - number of bytes read from the buffer to decode the
510 * @return CHIP_NO_ERROR on success.
513 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
514 * CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
516 CHIP_ERROR Decode(const uint8_t * data, uint16_t size, uint16_t * decode_size);
519 * A version of Decode that uses the type system to determine available
522 template <uint16_t N>
523 inline CHIP_ERROR Decode(const uint8_t (&data)[N], uint16_t * decode_size)
525 return Decode(data, N, decode_size);
529 * A version of Decode that decodes from the start of a PacketBuffer and
530 * consumes the bytes we decoded from.
532 CHIP_ERROR DecodeAndConsume(const System::PacketBufferHandle & buf);
535 * Encodes the encrypted part of the header into the given buffer.
537 * @param data - the buffer to write to
538 * @param size - space available in the buffer (in bytes)
539 * @param encode_size - number of bytes written to the buffer.
541 * @return CHIP_NO_ERROR on success.
544 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
546 CHIP_ERROR Encode(uint8_t * data, uint16_t size, uint16_t * encode_size) const;
549 * A version of Encode that uses the type system to determine available
552 template <uint16_t N>
553 inline CHIP_ERROR Encode(uint8_t (&data)[N], uint16_t * decode_size) const
555 return Encode(data, N, decode_size);
559 * A version of Encode that encodes into a PacketBuffer before the
560 * PacketBuffer's current data.
562 CHIP_ERROR EncodeBeforeData(const System::PacketBufferHandle & buf) const;
565 * A version of Encode that encodes into a PacketBuffer at the start of the
566 * current data space. This assumes that someone has already preallocated
567 * space for the header.
569 inline CHIP_ERROR EncodeAtStart(const System::PacketBufferHandle & buf, uint16_t * encode_size) const
571 return Encode(buf->Start(), buf->DataLength(), encode_size);
575 /// Packet type (application data, security control packets, e.g. pairing,
576 /// configuration, rekey etc)
577 uint8_t mMessageType = 0;
579 /// Security session identifier
580 uint16_t mExchangeID = 0;
582 /// Vendor identifier
583 Optional<uint16_t> mVendorId;
585 /// Protocol identifier
586 uint16_t mProtocolID = 0;
588 /// Bit flag indicators for CHIP Exchange header
589 Header::ExFlags mExchangeFlags;
591 /// Message counter of a previous message that is being acknowledged by the current message
592 Optional<uint32_t> mAckId;
595 /** Handles encoding/decoding of CHIP message headers */
596 class MessageAuthenticationCode
599 const uint8_t * GetTag() const { return &mTag[0]; }
601 /** Set the message auth tag for this header. */
602 MessageAuthenticationCode & SetTag(PacketHeader * header, Header::EncryptionType encType, uint8_t * tag, size_t len)
604 const size_t tagLen = TagLenForEncryptionType(encType);
605 if (tagLen > 0 && tagLen <= kMaxTagLen && len == tagLen)
607 header->SetEncryptionType(encType);
608 memcpy(&mTag, tag, tagLen);
615 * Decodes the Message Authentication Tag from the given buffer.
617 * @param packetHeader - header containing encryption information
618 * @param data - the buffer to read from
619 * @param size - bytes available in the buffer
620 * @param decode_size - number of bytes read from the buffer to decode the
623 * @return CHIP_NO_ERROR on success.
626 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
627 * CHIP_ERROR_VERSION_MISMATCH if header version is not supported.
629 CHIP_ERROR Decode(const PacketHeader & packetHeader, const uint8_t * data, uint16_t size, uint16_t * decode_size);
632 * Encodes the Messae Authentication Tag into the given buffer.
634 * @param packetHeader - header containing encryption information
635 * @param data - the buffer to write to
636 * @param size - space available in the buffer (in bytes)
637 * @param encode_size - number of bytes written to the buffer.
639 * @return CHIP_NO_ERROR on success.
642 * CHIP_ERROR_INVALID_ARGUMENT on insufficient buffer size
644 CHIP_ERROR Encode(const PacketHeader & packetHeader, uint8_t * data, uint16_t size, uint16_t * encode_size) const;
646 static uint16_t TagLenForEncryptionType(Header::EncryptionType encType);
649 /// Message authentication tag generated at encryption of the message.
650 uint8_t mTag[kMaxTagLen];