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