[sub-mac] redo security processing for every (re)transmission (#13093)

Retransmissions of frames containing time-dependent header Information
Elements (IEs), such as CSL or Time Sync, require updates to these
IEs to reflect the exact time of sending. If the frame counter is not
incremented for these retransmissions, it leads to nonce reuse in
AES-CCM encryption, which is a security vulnerability.

This commit addresses this issue by ensuring that every transmission
attempt (initial or retry) uses a fresh frame counter:
- Deferred security processing from `SubMac::Send()` to
  `SubMac::BeginTransmit()`.
- Upon retransmission in `SubMac::HandleTransmitDone()`, the frame is
  restored to plaintext via `TxFrame::DecryptTransmitAesCcm()` and
  security flags are cleared.
- This allows time-dependent IEs to be updated and a new frame counter
  to be assigned for every attempt.

Added a Nexus test case `retransmission_security` to verify that both
CSL and standard MAC retransmissions use incrementing frame counters
and updated CSL phases.
This commit is contained in:
Yakun Xu
2026-05-26 10:36:55 -07:00
committed by GitHub
parent 5783555d4c
commit 06e210fe89
11 changed files with 414 additions and 3 deletions
+10 -2
View File
@@ -404,6 +404,12 @@ exit:
otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext)
{
otError error = OT_ERROR_NONE;
aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime;
VerifyOrExit(!otMacFrameIsSecurityEnabled(aFrame) || !aFrame->mInfo.mTxInfo.mIsSecurityProcessed);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (aRadioContext->mCslPresent) // CSL IE should be filled for every transmit attempt
{
@@ -413,8 +419,10 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
otMacFrameUpdateTimeIe(aFrame, aRadioTime, aRadioContext);
#endif
aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime;
return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext);
error = otMacFrameProcessTransmitSecurity(aFrame, aRadioContext);
exit:
return error;
}
bool otMacFrameSrcAddrMatchCslReceiverPeer(const otRadioFrame *aFrame, const otRadioContext *aRadioContext)