• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements IEEE 802.15.4 header generation and processing.
32  */
33 
34 #include "mac_frame.hpp"
35 
36 #include <stdio.h>
37 
38 #include "common/code_utils.hpp"
39 #include "common/debug.hpp"
40 #include "common/log.hpp"
41 #include "radio/trel_link.hpp"
42 #if !OPENTHREAD_RADIO || OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
43 #include "crypto/aes_ccm.hpp"
44 #endif
45 
46 namespace ot {
47 namespace Mac {
48 
49 using ot::Encoding::LittleEndian::ReadUint16;
50 using ot::Encoding::LittleEndian::ReadUint32;
51 using ot::Encoding::LittleEndian::WriteUint16;
52 using ot::Encoding::LittleEndian::WriteUint32;
53 
Init(uint16_t aId,uint8_t aLen)54 void HeaderIe::Init(uint16_t aId, uint8_t aLen)
55 {
56     Init();
57     SetId(aId);
58     SetLength(aLen);
59 }
60 
InitMacHeader(uint16_t aFcf,uint8_t aSecurityControl)61 void Frame::InitMacHeader(uint16_t aFcf, uint8_t aSecurityControl)
62 {
63     mLength = CalculateAddrFieldSize(aFcf);
64 
65     OT_ASSERT(mLength != kInvalidSize);
66 
67     WriteUint16(aFcf, mPsdu);
68 
69     if (aFcf & kFcfSecurityEnabled)
70     {
71         mPsdu[mLength] = aSecurityControl;
72 
73         mLength += CalculateSecurityHeaderSize(aSecurityControl);
74         mLength += CalculateMicSize(aSecurityControl);
75     }
76 
77     if ((aFcf & kFcfFrameTypeMask) == kFcfFrameMacCmd)
78     {
79         mLength += kCommandIdSize;
80     }
81 
82     mLength += GetFcsSize();
83 }
84 
GetFrameControlField(void) const85 uint16_t Frame::GetFrameControlField(void) const
86 {
87     return ReadUint16(mPsdu);
88 }
89 
ValidatePsdu(void) const90 Error Frame::ValidatePsdu(void) const
91 {
92     Error   error = kErrorNone;
93     uint8_t index = FindPayloadIndex();
94 
95     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
96     VerifyOrExit((index + GetFooterLength()) <= mLength, error = kErrorParse);
97 
98 exit:
99     return error;
100 }
101 
SetAckRequest(bool aAckRequest)102 void Frame::SetAckRequest(bool aAckRequest)
103 {
104     if (aAckRequest)
105     {
106         mPsdu[0] |= kFcfAckRequest;
107     }
108     else
109     {
110         mPsdu[0] &= ~kFcfAckRequest;
111     }
112 }
113 
SetFramePending(bool aFramePending)114 void Frame::SetFramePending(bool aFramePending)
115 {
116     if (aFramePending)
117     {
118         mPsdu[0] |= kFcfFramePending;
119     }
120     else
121     {
122         mPsdu[0] &= ~kFcfFramePending;
123     }
124 }
125 
FindDstPanIdIndex(void) const126 uint8_t Frame::FindDstPanIdIndex(void) const
127 {
128     uint8_t index;
129 
130     VerifyOrExit(IsDstPanIdPresent(), index = kInvalidIndex);
131 
132     index = kFcfSize + kDsnSize;
133 
134 exit:
135     return index;
136 }
137 
IsDstPanIdPresent(uint16_t aFcf)138 bool Frame::IsDstPanIdPresent(uint16_t aFcf)
139 {
140     bool present = true;
141 
142 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
143     if (IsVersion2015(aFcf))
144     {
145         switch (aFcf & (kFcfDstAddrMask | kFcfSrcAddrMask | kFcfPanidCompression))
146         {
147         case (kFcfDstAddrNone | kFcfSrcAddrNone):
148         case (kFcfDstAddrExt | kFcfSrcAddrNone | kFcfPanidCompression):
149         case (kFcfDstAddrShort | kFcfSrcAddrNone | kFcfPanidCompression):
150         case (kFcfDstAddrNone | kFcfSrcAddrExt):
151         case (kFcfDstAddrNone | kFcfSrcAddrShort):
152         case (kFcfDstAddrNone | kFcfSrcAddrExt | kFcfPanidCompression):
153         case (kFcfDstAddrNone | kFcfSrcAddrShort | kFcfPanidCompression):
154         case (kFcfDstAddrExt | kFcfSrcAddrExt | kFcfPanidCompression):
155             present = false;
156             break;
157         default:
158             break;
159         }
160     }
161     else
162 #endif
163     {
164         present = IsDstAddrPresent(aFcf);
165     }
166 
167     return present;
168 }
169 
GetDstPanId(PanId & aPanId) const170 Error Frame::GetDstPanId(PanId &aPanId) const
171 {
172     Error   error = kErrorNone;
173     uint8_t index = FindDstPanIdIndex();
174 
175     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
176     aPanId = ReadUint16(&mPsdu[index]);
177 
178 exit:
179     return error;
180 }
181 
SetDstPanId(PanId aPanId)182 void Frame::SetDstPanId(PanId aPanId)
183 {
184     uint8_t index = FindDstPanIdIndex();
185 
186     OT_ASSERT(index != kInvalidIndex);
187     WriteUint16(aPanId, &mPsdu[index]);
188 }
189 
FindDstAddrIndex(void) const190 uint8_t Frame::FindDstAddrIndex(void) const
191 {
192     return kFcfSize + kDsnSize + (IsDstPanIdPresent() ? sizeof(PanId) : 0);
193 }
194 
GetDstAddr(Address & aAddress) const195 Error Frame::GetDstAddr(Address &aAddress) const
196 {
197     Error   error = kErrorNone;
198     uint8_t index = FindDstAddrIndex();
199 
200     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
201 
202     switch (GetFrameControlField() & kFcfDstAddrMask)
203     {
204     case kFcfDstAddrShort:
205         aAddress.SetShort(ReadUint16(&mPsdu[index]));
206         break;
207 
208     case kFcfDstAddrExt:
209         aAddress.SetExtended(&mPsdu[index], ExtAddress::kReverseByteOrder);
210         break;
211 
212     default:
213         aAddress.SetNone();
214         break;
215     }
216 
217 exit:
218     return error;
219 }
220 
SetDstAddr(ShortAddress aShortAddress)221 void Frame::SetDstAddr(ShortAddress aShortAddress)
222 {
223     OT_ASSERT((GetFrameControlField() & kFcfDstAddrMask) == kFcfDstAddrShort);
224     WriteUint16(aShortAddress, &mPsdu[FindDstAddrIndex()]);
225 }
226 
SetDstAddr(const ExtAddress & aExtAddress)227 void Frame::SetDstAddr(const ExtAddress &aExtAddress)
228 {
229     uint8_t index = FindDstAddrIndex();
230 
231     OT_ASSERT((GetFrameControlField() & kFcfDstAddrMask) == kFcfDstAddrExt);
232     OT_ASSERT(index != kInvalidIndex);
233 
234     aExtAddress.CopyTo(&mPsdu[index], ExtAddress::kReverseByteOrder);
235 }
236 
SetDstAddr(const Address & aAddress)237 void Frame::SetDstAddr(const Address &aAddress)
238 {
239     switch (aAddress.GetType())
240     {
241     case Address::kTypeShort:
242         SetDstAddr(aAddress.GetShort());
243         break;
244 
245     case Address::kTypeExtended:
246         SetDstAddr(aAddress.GetExtended());
247         break;
248 
249     default:
250         OT_ASSERT(false);
251         OT_UNREACHABLE_CODE(break);
252     }
253 }
254 
FindSrcPanIdIndex(void) const255 uint8_t Frame::FindSrcPanIdIndex(void) const
256 {
257     uint8_t  index = 0;
258     uint16_t fcf   = GetFrameControlField();
259 
260     VerifyOrExit(IsSrcPanIdPresent(), index = kInvalidIndex);
261 
262     index += kFcfSize + kDsnSize;
263 
264     if (IsDstPanIdPresent(fcf))
265     {
266         index += sizeof(PanId);
267     }
268 
269     switch (fcf & kFcfDstAddrMask)
270     {
271     case kFcfDstAddrShort:
272         index += sizeof(ShortAddress);
273         break;
274 
275     case kFcfDstAddrExt:
276         index += sizeof(ExtAddress);
277         break;
278     }
279 
280 exit:
281     return index;
282 }
283 
IsSrcPanIdPresent(uint16_t aFcf)284 bool Frame::IsSrcPanIdPresent(uint16_t aFcf)
285 {
286     bool srcPanIdPresent = false;
287 
288     if ((aFcf & kFcfSrcAddrMask) != kFcfSrcAddrNone && (aFcf & kFcfPanidCompression) == 0)
289     {
290 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
291         // Handle a special case in IEEE 802.15.4-2015, when Pan ID Compression is 0, but Src Pan ID is not present:
292         //  Dest Address:       Extended
293         //  Source Address:     Extended
294         //  Dest Pan ID:        Present
295         //  Src Pan ID:         Not Present
296         //  Pan ID Compression: 0
297         if (!IsVersion2015(aFcf) || (aFcf & kFcfDstAddrMask) != kFcfDstAddrExt ||
298             (aFcf & kFcfSrcAddrMask) != kFcfSrcAddrExt)
299 #endif
300         {
301             srcPanIdPresent = true;
302         }
303     }
304 
305     return srcPanIdPresent;
306 }
307 
GetSrcPanId(PanId & aPanId) const308 Error Frame::GetSrcPanId(PanId &aPanId) const
309 {
310     Error   error = kErrorNone;
311     uint8_t index = FindSrcPanIdIndex();
312 
313     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
314     aPanId = ReadUint16(&mPsdu[index]);
315 
316 exit:
317     return error;
318 }
319 
SetSrcPanId(PanId aPanId)320 Error Frame::SetSrcPanId(PanId aPanId)
321 {
322     Error   error = kErrorNone;
323     uint8_t index = FindSrcPanIdIndex();
324 
325     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
326     WriteUint16(aPanId, &mPsdu[index]);
327 
328 exit:
329     return error;
330 }
331 
FindSrcAddrIndex(void) const332 uint8_t Frame::FindSrcAddrIndex(void) const
333 {
334     uint8_t  index = 0;
335     uint16_t fcf   = GetFrameControlField();
336 
337     index += kFcfSize + kDsnSize;
338 
339     if (IsDstPanIdPresent(fcf))
340     {
341         index += sizeof(PanId);
342     }
343 
344     switch (fcf & kFcfDstAddrMask)
345     {
346     case kFcfDstAddrShort:
347         index += sizeof(ShortAddress);
348         break;
349 
350     case kFcfDstAddrExt:
351         index += sizeof(ExtAddress);
352         break;
353     }
354 
355     if (IsSrcPanIdPresent(fcf))
356     {
357         index += sizeof(PanId);
358     }
359 
360     return index;
361 }
362 
GetSrcAddr(Address & aAddress) const363 Error Frame::GetSrcAddr(Address &aAddress) const
364 {
365     Error    error = kErrorNone;
366     uint8_t  index = FindSrcAddrIndex();
367     uint16_t fcf   = GetFrameControlField();
368 
369     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
370 
371     switch (fcf & kFcfSrcAddrMask)
372     {
373     case kFcfSrcAddrShort:
374         aAddress.SetShort(ReadUint16(&mPsdu[index]));
375         break;
376 
377     case kFcfSrcAddrExt:
378         aAddress.SetExtended(&mPsdu[index], ExtAddress::kReverseByteOrder);
379         break;
380 
381     default:
382         aAddress.SetNone();
383         break;
384     }
385 
386 exit:
387     return error;
388 }
389 
SetSrcAddr(ShortAddress aShortAddress)390 void Frame::SetSrcAddr(ShortAddress aShortAddress)
391 {
392     uint8_t index = FindSrcAddrIndex();
393 
394     OT_ASSERT((GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrShort);
395     OT_ASSERT(index != kInvalidIndex);
396 
397     WriteUint16(aShortAddress, &mPsdu[index]);
398 }
399 
SetSrcAddr(const ExtAddress & aExtAddress)400 void Frame::SetSrcAddr(const ExtAddress &aExtAddress)
401 {
402     uint8_t index = FindSrcAddrIndex();
403 
404     OT_ASSERT((GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrExt);
405     OT_ASSERT(index != kInvalidIndex);
406 
407     aExtAddress.CopyTo(&mPsdu[index], ExtAddress::kReverseByteOrder);
408 }
409 
SetSrcAddr(const Address & aAddress)410 void Frame::SetSrcAddr(const Address &aAddress)
411 {
412     switch (aAddress.GetType())
413     {
414     case Address::kTypeShort:
415         SetSrcAddr(aAddress.GetShort());
416         break;
417 
418     case Address::kTypeExtended:
419         SetSrcAddr(aAddress.GetExtended());
420         break;
421 
422     default:
423         OT_ASSERT(false);
424     }
425 }
426 
GetSecurityControlField(uint8_t & aSecurityControlField) const427 Error Frame::GetSecurityControlField(uint8_t &aSecurityControlField) const
428 {
429     Error   error = kErrorNone;
430     uint8_t index = FindSecurityHeaderIndex();
431 
432     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
433 
434     aSecurityControlField = mPsdu[index];
435 
436 exit:
437     return error;
438 }
439 
SetSecurityControlField(uint8_t aSecurityControlField)440 void Frame::SetSecurityControlField(uint8_t aSecurityControlField)
441 {
442     uint8_t index = FindSecurityHeaderIndex();
443 
444     OT_ASSERT(index != kInvalidIndex);
445 
446     mPsdu[index] = aSecurityControlField;
447 }
448 
FindSecurityHeaderIndex(void) const449 uint8_t Frame::FindSecurityHeaderIndex(void) const
450 {
451     uint8_t index;
452 
453     VerifyOrExit(kFcfSize < mLength, index = kInvalidIndex);
454     VerifyOrExit(GetSecurityEnabled(), index = kInvalidIndex);
455     index = SkipAddrFieldIndex();
456 
457 exit:
458     return index;
459 }
460 
GetSecurityLevel(uint8_t & aSecurityLevel) const461 Error Frame::GetSecurityLevel(uint8_t &aSecurityLevel) const
462 {
463     Error   error = kErrorNone;
464     uint8_t index = FindSecurityHeaderIndex();
465 
466     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
467 
468     aSecurityLevel = mPsdu[index] & kSecLevelMask;
469 
470 exit:
471     return error;
472 }
473 
GetKeyIdMode(uint8_t & aKeyIdMode) const474 Error Frame::GetKeyIdMode(uint8_t &aKeyIdMode) const
475 {
476     Error   error = kErrorNone;
477     uint8_t index = FindSecurityHeaderIndex();
478 
479     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
480 
481     aKeyIdMode = mPsdu[index] & kKeyIdModeMask;
482 
483 exit:
484     return error;
485 }
486 
GetFrameCounter(uint32_t & aFrameCounter) const487 Error Frame::GetFrameCounter(uint32_t &aFrameCounter) const
488 {
489     Error   error = kErrorNone;
490     uint8_t index = FindSecurityHeaderIndex();
491 
492     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
493 
494     // Security Control
495     index += kSecurityControlSize;
496 
497     aFrameCounter = ReadUint32(&mPsdu[index]);
498 
499 exit:
500     return error;
501 }
502 
SetFrameCounter(uint32_t aFrameCounter)503 void Frame::SetFrameCounter(uint32_t aFrameCounter)
504 {
505     uint8_t index = FindSecurityHeaderIndex();
506 
507     OT_ASSERT(index != kInvalidIndex);
508 
509     // Security Control
510     index += kSecurityControlSize;
511 
512     WriteUint32(aFrameCounter, &mPsdu[index]);
513 
514     static_cast<Mac::TxFrame *>(this)->SetIsHeaderUpdated(true);
515 }
516 
GetKeySource(void) const517 const uint8_t *Frame::GetKeySource(void) const
518 {
519     uint8_t index = FindSecurityHeaderIndex();
520 
521     OT_ASSERT(index != kInvalidIndex);
522 
523     return &mPsdu[index + kSecurityControlSize + kFrameCounterSize];
524 }
525 
GetKeySourceLength(uint8_t aKeyIdMode)526 uint8_t Frame::GetKeySourceLength(uint8_t aKeyIdMode)
527 {
528     uint8_t len = 0;
529 
530     switch (aKeyIdMode)
531     {
532     case kKeyIdMode0:
533         len = kKeySourceSizeMode0;
534         break;
535 
536     case kKeyIdMode1:
537         len = kKeySourceSizeMode1;
538         break;
539 
540     case kKeyIdMode2:
541         len = kKeySourceSizeMode2;
542         break;
543 
544     case kKeyIdMode3:
545         len = kKeySourceSizeMode3;
546         break;
547     }
548 
549     return len;
550 }
551 
SetKeySource(const uint8_t * aKeySource)552 void Frame::SetKeySource(const uint8_t *aKeySource)
553 {
554     uint8_t keySourceLength;
555     uint8_t index = FindSecurityHeaderIndex();
556 
557     OT_ASSERT(index != kInvalidIndex);
558 
559     keySourceLength = GetKeySourceLength(mPsdu[index] & kKeyIdModeMask);
560 
561     memcpy(&mPsdu[index + kSecurityControlSize + kFrameCounterSize], aKeySource, keySourceLength);
562 }
563 
GetKeyId(uint8_t & aKeyId) const564 Error Frame::GetKeyId(uint8_t &aKeyId) const
565 {
566     Error   error = kErrorNone;
567     uint8_t keySourceLength;
568     uint8_t index = FindSecurityHeaderIndex();
569 
570     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
571 
572     keySourceLength = GetKeySourceLength(mPsdu[index] & kKeyIdModeMask);
573 
574     aKeyId = mPsdu[index + kSecurityControlSize + kFrameCounterSize + keySourceLength];
575 
576 exit:
577     return error;
578 }
579 
SetKeyId(uint8_t aKeyId)580 void Frame::SetKeyId(uint8_t aKeyId)
581 {
582     uint8_t keySourceLength;
583     uint8_t index = FindSecurityHeaderIndex();
584 
585     OT_ASSERT(index != kInvalidIndex);
586 
587     keySourceLength = GetKeySourceLength(mPsdu[index] & kKeyIdModeMask);
588 
589     mPsdu[index + kSecurityControlSize + kFrameCounterSize + keySourceLength] = aKeyId;
590 }
591 
GetCommandId(uint8_t & aCommandId) const592 Error Frame::GetCommandId(uint8_t &aCommandId) const
593 {
594     Error   error = kErrorNone;
595     uint8_t index = FindPayloadIndex();
596 
597     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
598 
599     aCommandId = mPsdu[IsVersion2015() ? index : (index - 1)];
600 
601 exit:
602     return error;
603 }
604 
SetCommandId(uint8_t aCommandId)605 Error Frame::SetCommandId(uint8_t aCommandId)
606 {
607     Error   error = kErrorNone;
608     uint8_t index = FindPayloadIndex();
609 
610     VerifyOrExit(index != kInvalidIndex, error = kErrorParse);
611 
612     mPsdu[IsVersion2015() ? index : (index - 1)] = aCommandId;
613 
614 exit:
615     return error;
616 }
617 
IsDataRequestCommand(void) const618 bool Frame::IsDataRequestCommand(void) const
619 {
620     bool    isDataRequest = false;
621     uint8_t commandId;
622 
623     VerifyOrExit(GetType() == kFcfFrameMacCmd);
624     SuccessOrExit(GetCommandId(commandId));
625     isDataRequest = (commandId == kMacCmdDataRequest);
626 
627 exit:
628     return isDataRequest;
629 }
630 
GetHeaderLength(void) const631 uint8_t Frame::GetHeaderLength(void) const
632 {
633     return static_cast<uint8_t>(GetPayload() - mPsdu);
634 }
635 
GetFooterLength(void) const636 uint8_t Frame::GetFooterLength(void) const
637 {
638     uint8_t footerLength = static_cast<uint8_t>(GetFcsSize());
639     uint8_t index        = FindSecurityHeaderIndex();
640 
641     VerifyOrExit(index != kInvalidIndex);
642     footerLength += CalculateMicSize(mPsdu[index]);
643 
644 exit:
645     return footerLength;
646 }
647 
CalculateMicSize(uint8_t aSecurityControl)648 uint8_t Frame::CalculateMicSize(uint8_t aSecurityControl)
649 {
650     uint8_t micSize = 0;
651 
652     switch (aSecurityControl & kSecLevelMask)
653     {
654     case kSecNone:
655     case kSecEnc:
656         micSize = kMic0Size;
657         break;
658 
659     case kSecMic32:
660     case kSecEncMic32:
661         micSize = kMic32Size;
662         break;
663 
664     case kSecMic64:
665     case kSecEncMic64:
666         micSize = kMic64Size;
667         break;
668 
669     case kSecMic128:
670     case kSecEncMic128:
671         micSize = kMic128Size;
672         break;
673     }
674 
675     return micSize;
676 }
677 
GetMaxPayloadLength(void) const678 uint16_t Frame::GetMaxPayloadLength(void) const
679 {
680     return GetMtu() - (GetHeaderLength() + GetFooterLength());
681 }
682 
GetPayloadLength(void) const683 uint16_t Frame::GetPayloadLength(void) const
684 {
685     return mLength - (GetHeaderLength() + GetFooterLength());
686 }
687 
SetPayloadLength(uint16_t aLength)688 void Frame::SetPayloadLength(uint16_t aLength)
689 {
690     mLength = GetHeaderLength() + GetFooterLength() + aLength;
691 }
692 
SkipSecurityHeaderIndex(void) const693 uint8_t Frame::SkipSecurityHeaderIndex(void) const
694 {
695     uint8_t index = SkipAddrFieldIndex();
696 
697     VerifyOrExit(index != kInvalidIndex);
698 
699     if (GetSecurityEnabled())
700     {
701         uint8_t securityControl;
702         uint8_t headerSize;
703 
704         VerifyOrExit(index < mLength, index = kInvalidIndex);
705         securityControl = mPsdu[index];
706 
707         headerSize = CalculateSecurityHeaderSize(securityControl);
708         VerifyOrExit(headerSize != kInvalidSize, index = kInvalidIndex);
709 
710         index += headerSize;
711 
712         VerifyOrExit(index <= mLength, index = kInvalidIndex);
713     }
714 
715 exit:
716     return index;
717 }
718 
CalculateSecurityHeaderSize(uint8_t aSecurityControl)719 uint8_t Frame::CalculateSecurityHeaderSize(uint8_t aSecurityControl)
720 {
721     uint8_t size = kSecurityControlSize + kFrameCounterSize;
722 
723     VerifyOrExit((aSecurityControl & kSecLevelMask) != kSecNone, size = kInvalidSize);
724 
725     switch (aSecurityControl & kKeyIdModeMask)
726     {
727     case kKeyIdMode0:
728         size += kKeySourceSizeMode0;
729         break;
730 
731     case kKeyIdMode1:
732         size += kKeySourceSizeMode1 + kKeyIndexSize;
733         break;
734 
735     case kKeyIdMode2:
736         size += kKeySourceSizeMode2 + kKeyIndexSize;
737         break;
738 
739     case kKeyIdMode3:
740         size += kKeySourceSizeMode3 + kKeyIndexSize;
741         break;
742     }
743 
744 exit:
745     return size;
746 }
747 
SkipAddrFieldIndex(void) const748 uint8_t Frame::SkipAddrFieldIndex(void) const
749 {
750     uint8_t index;
751 
752     VerifyOrExit(kFcfSize + kDsnSize + GetFcsSize() <= mLength, index = kInvalidIndex);
753 
754     index = CalculateAddrFieldSize(GetFrameControlField());
755 
756 exit:
757     return index;
758 }
759 
CalculateAddrFieldSize(uint16_t aFcf)760 uint8_t Frame::CalculateAddrFieldSize(uint16_t aFcf)
761 {
762     uint8_t size = kFcfSize + kDsnSize;
763 
764     // This static method calculates the size (number of bytes) of
765     // Address header field for a given Frame Control `aFcf` value.
766     // The size includes the Frame Control and Sequence Number fields
767     // along with Destination and Source PAN ID and Short/Extended
768     // Addresses. If the `aFcf` is not valid, this method returns
769     // `kInvalidSize`.
770 
771     if (IsDstPanIdPresent(aFcf))
772     {
773         size += sizeof(PanId);
774     }
775 
776     switch (aFcf & kFcfDstAddrMask)
777     {
778     case kFcfDstAddrNone:
779         break;
780 
781     case kFcfDstAddrShort:
782         size += sizeof(ShortAddress);
783         break;
784 
785     case kFcfDstAddrExt:
786         size += sizeof(ExtAddress);
787         break;
788 
789     default:
790         ExitNow(size = kInvalidSize);
791     }
792 
793     if (IsSrcPanIdPresent(aFcf))
794     {
795         size += sizeof(PanId);
796     }
797 
798     switch (aFcf & kFcfSrcAddrMask)
799     {
800     case kFcfSrcAddrNone:
801         break;
802 
803     case kFcfSrcAddrShort:
804         size += sizeof(ShortAddress);
805         break;
806 
807     case kFcfSrcAddrExt:
808         size += sizeof(ExtAddress);
809         break;
810 
811     default:
812         ExitNow(size = kInvalidSize);
813     }
814 
815 exit:
816     return size;
817 }
818 
FindPayloadIndex(void) const819 uint8_t Frame::FindPayloadIndex(void) const
820 {
821     // We use `uint16_t` for `index` to handle its potential roll-over
822     // while parsing and verifying Header IE(s).
823 
824     uint16_t index = SkipSecurityHeaderIndex();
825 
826     VerifyOrExit(index != kInvalidIndex);
827 
828 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
829     if (IsIePresent())
830     {
831         uint8_t footerLength = GetFooterLength();
832 
833         do
834         {
835             const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
836 
837             index += sizeof(HeaderIe);
838             VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
839 
840             index += ie->GetLength();
841             VerifyOrExit(index + footerLength <= mLength, index = kInvalidIndex);
842 
843             if (ie->GetId() == Termination2Ie::kHeaderIeId)
844             {
845                 break;
846             }
847 
848             // If the `index + footerLength == mLength`, we exit the `while()`
849             // loop. This covers the case where frame contains one or more
850             // Header IEs but no data payload. In this case, spec does not
851             // require Header IE termination to be included (it is optional)
852             // since the end of frame can be determined from frame length and
853             // footer length.
854 
855         } while (index + footerLength < mLength);
856 
857         // Assume no Payload IE in current implementation
858     }
859 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
860 
861     if (!IsVersion2015() && (GetFrameControlField() & kFcfFrameTypeMask) == kFcfFrameMacCmd)
862     {
863         index += kCommandIdSize;
864     }
865 
866 exit:
867     return static_cast<uint8_t>(index);
868 }
869 
GetPayload(void) const870 const uint8_t *Frame::GetPayload(void) const
871 {
872     uint8_t        index = FindPayloadIndex();
873     const uint8_t *payload;
874 
875     VerifyOrExit(index != kInvalidIndex, payload = nullptr);
876     payload = &mPsdu[index];
877 
878 exit:
879     return payload;
880 }
881 
GetFooter(void) const882 const uint8_t *Frame::GetFooter(void) const
883 {
884     return mPsdu + mLength - GetFooterLength();
885 }
886 
887 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
FindHeaderIeIndex(void) const888 uint8_t Frame::FindHeaderIeIndex(void) const
889 {
890     uint8_t index;
891 
892     VerifyOrExit(IsIePresent(), index = kInvalidIndex);
893 
894     index = SkipSecurityHeaderIndex();
895 
896 exit:
897     return index;
898 }
899 
900 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
AppendHeaderIeAt(uint8_t & aIndex)901 template <typename IeType> Error Frame::AppendHeaderIeAt(uint8_t &aIndex)
902 {
903     Error error = kErrorNone;
904 
905     SuccessOrExit(error = InitIeHeaderAt(aIndex, IeType::kHeaderIeId, IeType::kIeContentSize));
906 
907     InitIeContentAt<IeType>(aIndex);
908 
909 exit:
910     return error;
911 }
912 
InitIeHeaderAt(uint8_t & aIndex,uint8_t ieId,uint8_t ieContentSize)913 Error Frame::InitIeHeaderAt(uint8_t &aIndex, uint8_t ieId, uint8_t ieContentSize)
914 {
915     Error error = kErrorNone;
916 
917     if (aIndex == 0)
918     {
919         aIndex = FindHeaderIeIndex();
920     }
921 
922     VerifyOrExit(aIndex != kInvalidIndex, error = kErrorNotFound);
923 
924     reinterpret_cast<HeaderIe *>(mPsdu + aIndex)->Init(ieId, ieContentSize);
925     aIndex += sizeof(HeaderIe);
926 
927     mLength += sizeof(HeaderIe) + ieContentSize;
928 exit:
929     return error;
930 }
931 
932 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
InitIeContentAt(uint8_t & aIndex)933 template <> void Frame::InitIeContentAt<TimeIe>(uint8_t &aIndex)
934 {
935     reinterpret_cast<TimeIe *>(mPsdu + aIndex)->Init();
936     aIndex += sizeof(TimeIe);
937 }
938 #endif
939 
940 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
InitIeContentAt(uint8_t & aIndex)941 template <> void Frame::InitIeContentAt<CslIe>(uint8_t &aIndex)
942 {
943     aIndex += sizeof(CslIe);
944 }
945 #endif
946 
InitIeContentAt(uint8_t & aIndex)947 template <> void Frame::InitIeContentAt<Termination2Ie>(uint8_t &aIndex)
948 {
949     OT_UNUSED_VARIABLE(aIndex);
950 }
951 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
952 
GetHeaderIe(uint8_t aIeId) const953 const uint8_t *Frame::GetHeaderIe(uint8_t aIeId) const
954 {
955     uint8_t        index        = FindHeaderIeIndex();
956     uint8_t        payloadIndex = FindPayloadIndex();
957     const uint8_t *header       = nullptr;
958 
959     // `FindPayloadIndex()` verifies that Header IE(s) in frame (if present)
960     // are well-formed.
961 
962     VerifyOrExit((index != kInvalidIndex) && (payloadIndex != kInvalidIndex));
963 
964     while (index <= payloadIndex)
965     {
966         const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
967 
968         if (ie->GetId() == aIeId)
969         {
970             header = &mPsdu[index];
971             ExitNow();
972         }
973 
974         index += sizeof(HeaderIe) + ie->GetLength();
975     }
976 
977 exit:
978     return header;
979 }
980 
981 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
GetThreadIe(uint8_t aSubType) const982 const uint8_t *Frame::GetThreadIe(uint8_t aSubType) const
983 {
984     uint8_t        index        = FindHeaderIeIndex();
985     uint8_t        payloadIndex = FindPayloadIndex();
986     const uint8_t *header       = nullptr;
987 
988     // `FindPayloadIndex()` verifies that Header IE(s) in frame (if present)
989     // are well-formed.
990     VerifyOrExit((index != kInvalidIndex) && (payloadIndex != kInvalidIndex));
991 
992     while (index <= payloadIndex)
993     {
994         const HeaderIe *ie = reinterpret_cast<const HeaderIe *>(&mPsdu[index]);
995 
996         if (ie->GetId() == VendorIeHeader::kHeaderIeId)
997         {
998             const VendorIeHeader *vendorIe =
999                 reinterpret_cast<const VendorIeHeader *>(reinterpret_cast<const uint8_t *>(ie) + sizeof(HeaderIe));
1000             if (vendorIe->GetVendorOui() == ThreadIe::kVendorOuiThreadCompanyId && vendorIe->GetSubType() == aSubType)
1001             {
1002                 header = &mPsdu[index];
1003                 ExitNow();
1004             }
1005         }
1006 
1007         index += sizeof(HeaderIe) + ie->GetLength();
1008     }
1009 
1010 exit:
1011     return header;
1012 }
1013 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1014 
1015 #endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1016 
1017 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
SetCslIe(uint16_t aCslPeriod,uint16_t aCslPhase)1018 void Frame::SetCslIe(uint16_t aCslPeriod, uint16_t aCslPhase)
1019 {
1020     uint8_t *cur = GetHeaderIe(CslIe::kHeaderIeId);
1021     CslIe *  csl;
1022 
1023     VerifyOrExit(cur != nullptr);
1024 
1025     csl = reinterpret_cast<CslIe *>(cur + sizeof(HeaderIe));
1026     csl->SetPeriod(aCslPeriod);
1027     csl->SetPhase(aCslPhase);
1028 exit:
1029     return;
1030 }
1031 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1032 
1033 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
SetEnhAckProbingIe(const uint8_t * aValue,uint8_t aLen)1034 void Frame::SetEnhAckProbingIe(const uint8_t *aValue, uint8_t aLen)
1035 {
1036     uint8_t *cur = GetThreadIe(ThreadIe::kEnhAckProbingIe);
1037 
1038     OT_ASSERT(cur != nullptr);
1039 
1040     memcpy(cur + sizeof(HeaderIe) + sizeof(VendorIeHeader), aValue, aLen);
1041 }
1042 #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1043 
1044 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
GetTimeIe(void) const1045 const TimeIe *Frame::GetTimeIe(void) const
1046 {
1047     const TimeIe * timeIe = nullptr;
1048     const uint8_t *cur    = nullptr;
1049 
1050     cur = GetHeaderIe(VendorIeHeader::kHeaderIeId);
1051     VerifyOrExit(cur != nullptr);
1052 
1053     cur += sizeof(HeaderIe);
1054 
1055     timeIe = reinterpret_cast<const TimeIe *>(cur);
1056     VerifyOrExit(timeIe->GetVendorOui() == TimeIe::kVendorOuiNest, timeIe = nullptr);
1057     VerifyOrExit(timeIe->GetSubType() == TimeIe::kVendorIeTime, timeIe = nullptr);
1058 
1059 exit:
1060     return timeIe;
1061 }
1062 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1063 
1064 #if OPENTHREAD_CONFIG_MULTI_RADIO
GetMtu(void) const1065 uint16_t Frame::GetMtu(void) const
1066 {
1067     uint16_t mtu = 0;
1068 
1069     switch (GetRadioType())
1070     {
1071 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1072     case kRadioTypeIeee802154:
1073         mtu = OT_RADIO_FRAME_MAX_SIZE;
1074         break;
1075 #endif
1076 
1077 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
1078     case kRadioTypeTrel:
1079         mtu = Trel::Link::kMtuSize;
1080         break;
1081 #endif
1082     }
1083 
1084     return mtu;
1085 }
1086 
GetFcsSize(void) const1087 uint8_t Frame::GetFcsSize(void) const
1088 {
1089     uint8_t fcsSize = 0;
1090 
1091     switch (GetRadioType())
1092     {
1093 #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
1094     case kRadioTypeIeee802154:
1095         fcsSize = k154FcsSize;
1096         break;
1097 #endif
1098 
1099 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
1100     case kRadioTypeTrel:
1101         fcsSize = Trel::Link::kFcsSize;
1102         break;
1103 #endif
1104     }
1105 
1106     return fcsSize;
1107 }
1108 
1109 #elif OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
GetMtu(void) const1110 uint16_t Frame::GetMtu(void) const
1111 {
1112     return Trel::Link::kMtuSize;
1113 }
1114 
GetFcsSize(void) const1115 uint8_t Frame::GetFcsSize(void) const
1116 {
1117     return Trel::Link::kFcsSize;
1118 }
1119 #endif
1120 
1121 // Explicit instantiation
1122 #if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
1123 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1124 template Error Frame::AppendHeaderIeAt<TimeIe>(uint8_t &aIndex);
1125 #endif
1126 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
1127 template Error Frame::AppendHeaderIeAt<CslIe>(uint8_t &aIndex);
1128 #endif
1129 template Error Frame::AppendHeaderIeAt<Termination2Ie>(uint8_t &aIndex);
1130 #endif
1131 
CopyFrom(const TxFrame & aFromFrame)1132 void TxFrame::CopyFrom(const TxFrame &aFromFrame)
1133 {
1134     uint8_t *      psduBuffer   = mPsdu;
1135     otRadioIeInfo *ieInfoBuffer = mInfo.mTxInfo.mIeInfo;
1136 #if OPENTHREAD_CONFIG_MULTI_RADIO
1137     uint8_t radioType = mRadioType;
1138 #endif
1139 
1140     memcpy(this, &aFromFrame, sizeof(Frame));
1141 
1142     // Set the original buffer pointers (and link type) back on
1143     // the frame (which were overwritten by above `memcpy()`).
1144 
1145     mPsdu                 = psduBuffer;
1146     mInfo.mTxInfo.mIeInfo = ieInfoBuffer;
1147 
1148 #if OPENTHREAD_CONFIG_MULTI_RADIO
1149     mRadioType = radioType;
1150 #endif
1151 
1152     memcpy(mPsdu, aFromFrame.mPsdu, aFromFrame.mLength);
1153 
1154     // mIeInfo may be null when TIME_SYNC is not enabled.
1155 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1156     memcpy(mInfo.mTxInfo.mIeInfo, aFromFrame.mInfo.mTxInfo.mIeInfo, sizeof(otRadioIeInfo));
1157 #endif
1158 
1159 #if OPENTHREAD_CONFIG_MULTI_RADIO
1160     if (mRadioType != aFromFrame.GetRadioType())
1161     {
1162         // Frames associated with different radio link types can have
1163         // different FCS size. We adjust the PSDU length after the
1164         // copy to account for this.
1165 
1166         SetLength(aFromFrame.GetPsduLength() - aFromFrame.GetFcsSize() + GetFcsSize());
1167     }
1168 #endif
1169 }
1170 
ProcessTransmitAesCcm(const ExtAddress & aExtAddress)1171 void TxFrame::ProcessTransmitAesCcm(const ExtAddress &aExtAddress)
1172 {
1173 #if OPENTHREAD_RADIO && !OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
1174     OT_UNUSED_VARIABLE(aExtAddress);
1175 #else
1176     uint32_t       frameCounter = 0;
1177     uint8_t        securityLevel;
1178     uint8_t        nonce[Crypto::AesCcm::kNonceSize];
1179     uint8_t        tagLength;
1180     Crypto::AesCcm aesCcm;
1181 
1182     VerifyOrExit(GetSecurityEnabled());
1183 
1184     SuccessOrExit(GetSecurityLevel(securityLevel));
1185     SuccessOrExit(GetFrameCounter(frameCounter));
1186 
1187     Crypto::AesCcm::GenerateNonce(aExtAddress, frameCounter, securityLevel, nonce);
1188 
1189     aesCcm.SetKey(GetAesKey());
1190     tagLength = GetFooterLength() - GetFcsSize();
1191 
1192     aesCcm.Init(GetHeaderLength(), GetPayloadLength(), tagLength, nonce, sizeof(nonce));
1193     aesCcm.Header(GetHeader(), GetHeaderLength());
1194     aesCcm.Payload(GetPayload(), GetPayload(), GetPayloadLength(), Crypto::AesCcm::kEncrypt);
1195     aesCcm.Finalize(GetFooter());
1196 
1197     SetIsSecurityProcessed(true);
1198 
1199 exit:
1200     return;
1201 #endif // OPENTHREAD_RADIO && !OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_SECURITY_ENABLE
1202 }
1203 
GenerateImmAck(const RxFrame & aFrame,bool aIsFramePending)1204 void TxFrame::GenerateImmAck(const RxFrame &aFrame, bool aIsFramePending)
1205 {
1206     uint16_t fcf = kFcfFrameAck | aFrame.GetVersion();
1207 
1208     mChannel = aFrame.mChannel;
1209     memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo));
1210 
1211     if (aIsFramePending)
1212     {
1213         fcf |= kFcfFramePending;
1214     }
1215     WriteUint16(fcf, mPsdu);
1216 
1217     mPsdu[kSequenceIndex] = aFrame.GetSequence();
1218 
1219     mLength = kImmAckLength;
1220 }
1221 
1222 #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
GenerateEnhAck(const RxFrame & aFrame,bool aIsFramePending,const uint8_t * aIeData,uint8_t aIeLength)1223 Error TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength)
1224 {
1225     Error error = kErrorNone;
1226 
1227     uint16_t fcf = kFcfFrameAck | kFcfFrameVersion2015 | kFcfSrcAddrNone;
1228     Address  address;
1229     PanId    panId;
1230     uint8_t  footerLength;
1231     uint8_t  securityControlField;
1232     uint8_t  keyId;
1233 
1234     mChannel = aFrame.mChannel;
1235     memset(&mInfo.mTxInfo, 0, sizeof(mInfo.mTxInfo));
1236 
1237     // Set frame control field
1238     if (aIsFramePending)
1239     {
1240         fcf |= kFcfFramePending;
1241     }
1242 
1243     if (aFrame.GetSecurityEnabled())
1244     {
1245         fcf |= kFcfSecurityEnabled;
1246     }
1247 
1248     if (aFrame.IsPanIdCompressed())
1249     {
1250         fcf |= kFcfPanidCompression;
1251     }
1252 
1253     // Destination address mode
1254     if ((aFrame.GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrExt)
1255     {
1256         fcf |= kFcfDstAddrExt;
1257     }
1258     else if ((aFrame.GetFrameControlField() & kFcfSrcAddrMask) == kFcfSrcAddrShort)
1259     {
1260         fcf |= kFcfDstAddrShort;
1261     }
1262     else
1263     {
1264         fcf |= kFcfDstAddrNone;
1265     }
1266 
1267     if (aIeLength > 0)
1268     {
1269         fcf |= kFcfIePresent;
1270     }
1271 
1272     WriteUint16(fcf, mPsdu);
1273 
1274     // Set sequence number
1275     mPsdu[kSequenceIndex] = aFrame.GetSequence();
1276 
1277     if (IsDstPanIdPresent())
1278     {
1279         // Set address field
1280         if (aFrame.IsSrcPanIdPresent())
1281         {
1282             SuccessOrExit(error = aFrame.GetSrcPanId(panId));
1283         }
1284         else if (aFrame.IsDstPanIdPresent())
1285         {
1286             SuccessOrExit(error = aFrame.GetDstPanId(panId));
1287         }
1288         else
1289         {
1290             ExitNow(error = kErrorParse);
1291         }
1292 
1293         SetDstPanId(panId);
1294     }
1295 
1296     if (aFrame.IsSrcAddrPresent())
1297     {
1298         SuccessOrExit(error = aFrame.GetSrcAddr(address));
1299         SetDstAddr(address);
1300     }
1301 
1302     // At this time the length of ACK hasn't been determined, set it to
1303     // `kMaxPsduSize` to call methods that check frame length
1304     mLength = kMaxPsduSize;
1305 
1306     // Set security header
1307     if (aFrame.GetSecurityEnabled())
1308     {
1309         SuccessOrExit(error = aFrame.GetSecurityControlField(securityControlField));
1310         SuccessOrExit(error = aFrame.GetKeyId(keyId));
1311 
1312         SetSecurityControlField(securityControlField);
1313         SetKeyId(keyId);
1314     }
1315 
1316     // Set header IE
1317     if (aIeLength > 0)
1318     {
1319         OT_ASSERT(aIeData != nullptr);
1320         memcpy(&mPsdu[FindHeaderIeIndex()], aIeData, aIeLength);
1321     }
1322 
1323     // Set frame length
1324     footerLength = GetFooterLength();
1325     OT_ASSERT(footerLength != kInvalidIndex);
1326     mLength = SkipSecurityHeaderIndex() + aIeLength + footerLength;
1327 
1328 exit:
1329     return error;
1330 }
1331 #endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
1332 
ProcessReceiveAesCcm(const ExtAddress & aExtAddress,const KeyMaterial & aMacKey)1333 Error RxFrame::ProcessReceiveAesCcm(const ExtAddress &aExtAddress, const KeyMaterial &aMacKey)
1334 {
1335 #if OPENTHREAD_RADIO
1336     OT_UNUSED_VARIABLE(aExtAddress);
1337     OT_UNUSED_VARIABLE(aMacKey);
1338 
1339     return kErrorNone;
1340 #else
1341     Error          error        = kErrorSecurity;
1342     uint32_t       frameCounter = 0;
1343     uint8_t        securityLevel;
1344     uint8_t        nonce[Crypto::AesCcm::kNonceSize];
1345     uint8_t        tag[kMaxMicSize];
1346     uint8_t        tagLength;
1347     Crypto::AesCcm aesCcm;
1348 
1349     VerifyOrExit(GetSecurityEnabled(), error = kErrorNone);
1350 
1351     SuccessOrExit(GetSecurityLevel(securityLevel));
1352     SuccessOrExit(GetFrameCounter(frameCounter));
1353 
1354     Crypto::AesCcm::GenerateNonce(aExtAddress, frameCounter, securityLevel, nonce);
1355 
1356     aesCcm.SetKey(aMacKey);
1357     tagLength = GetFooterLength() - GetFcsSize();
1358 
1359     aesCcm.Init(GetHeaderLength(), GetPayloadLength(), tagLength, nonce, sizeof(nonce));
1360     aesCcm.Header(GetHeader(), GetHeaderLength());
1361 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1362     aesCcm.Payload(GetPayload(), GetPayload(), GetPayloadLength(), Crypto::AesCcm::kDecrypt);
1363 #else
1364     // For fuzz tests, execute AES but do not alter the payload
1365     uint8_t fuzz[OT_RADIO_FRAME_MAX_SIZE];
1366     aesCcm.Payload(fuzz, GetPayload(), GetPayloadLength(), Crypto::AesCcm::kDecrypt);
1367 #endif
1368     aesCcm.Finalize(tag);
1369 
1370 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1371     VerifyOrExit(memcmp(tag, GetFooter(), tagLength) == 0);
1372 #endif
1373 
1374     error = kErrorNone;
1375 
1376 exit:
1377     return error;
1378 #endif // OPENTHREAD_RADIO
1379 }
1380 
1381 // LCOV_EXCL_START
1382 
1383 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
1384 
ToInfoString(void) const1385 Frame::InfoString Frame::ToInfoString(void) const
1386 {
1387     InfoString string;
1388     uint8_t    commandId, type;
1389     Address    src, dst;
1390 
1391     string.Append("len:%d, seqnum:%d, type:", mLength, GetSequence());
1392 
1393     type = GetType();
1394 
1395     switch (type)
1396     {
1397     case kFcfFrameBeacon:
1398         string.Append("Beacon");
1399         break;
1400 
1401     case kFcfFrameData:
1402         string.Append("Data");
1403         break;
1404 
1405     case kFcfFrameAck:
1406         string.Append("Ack");
1407         break;
1408 
1409     case kFcfFrameMacCmd:
1410         if (GetCommandId(commandId) != kErrorNone)
1411         {
1412             commandId = 0xff;
1413         }
1414 
1415         switch (commandId)
1416         {
1417         case kMacCmdDataRequest:
1418             string.Append("Cmd(DataReq)");
1419             break;
1420 
1421         case kMacCmdBeaconRequest:
1422             string.Append("Cmd(BeaconReq)");
1423             break;
1424 
1425         default:
1426             string.Append("Cmd(%d)", commandId);
1427             break;
1428         }
1429 
1430         break;
1431 
1432     default:
1433         string.Append("%d", type);
1434         break;
1435     }
1436 
1437     IgnoreError(GetSrcAddr(src));
1438     IgnoreError(GetDstAddr(dst));
1439 
1440     string.Append(", src:%s, dst:%s, sec:%s, ackreq:%s", src.ToString().AsCString(), dst.ToString().AsCString(),
1441                   ToYesNo(GetSecurityEnabled()), ToYesNo(GetAckRequest()));
1442 
1443 #if OPENTHREAD_CONFIG_MULTI_RADIO
1444     string.Append(", radio:%s", RadioTypeToString(GetRadioType()));
1445 #endif
1446 
1447     return string;
1448 }
1449 
1450 #endif // #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
1451 
1452 // LCOV_EXCL_STOP
1453 
1454 } // namespace Mac
1455 } // namespace ot
1456