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