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