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