mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 07:37:46 +00:00
[radio] process tx AES without otInstance (#4318)
`otPlatRadioFrameUpdated()` is declared not to access any state within OpenThread. However, the current implementation does read the extended address. This commit moves the AES process into `Mac::TxFrame`, which is free of `otInstance` and eliminates the current deep callback stacks when the radio driver wants to process tx AES from interrupt context.
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
#include "utils/mac_frame.h"
|
||||
|
||||
#include <platform-config.h>
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
@@ -84,6 +85,7 @@ enum
|
||||
|
||||
static bool sDisabled;
|
||||
|
||||
static otExtAddress sExtAddress;
|
||||
static otError sReceiveError = OT_ERROR_NONE;
|
||||
static otRadioFrame sReceivedFrames[NRF_802154_RX_BUFFERS];
|
||||
static otRadioFrame sTransmitFrame;
|
||||
@@ -221,6 +223,11 @@ void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aE
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
for (size_t i = 0; i < sizeof(*aExtAddress); i++)
|
||||
{
|
||||
sExtAddress.m8[i] = aExtAddress->m8[sizeof(*aExtAddress) - 1 - i];
|
||||
}
|
||||
|
||||
nrf_802154_extended_address_set(aExtAddress->m8);
|
||||
}
|
||||
|
||||
@@ -921,7 +928,7 @@ void nrf_802154_tx_started(const uint8_t *aFrame)
|
||||
|
||||
if (notifyFrameUpdated)
|
||||
{
|
||||
otPlatRadioFrameUpdated(sInstance, &sTransmitFrame);
|
||||
otMacFrameProcessTransmitAesCcm(&sTransmitFrame, &sExtAddress);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -545,7 +545,7 @@ void radioSendMessage(otInstance *aInstance)
|
||||
|
||||
if (notifyFrameUpdated)
|
||||
{
|
||||
otPlatRadioFrameUpdated(aInstance, &sTransmitFrame);
|
||||
otMacFrameProcessTransmitAesCcm(&sTransmitFrame, &sExtAddress);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
|
||||
@@ -115,3 +115,8 @@ uint8_t otMacFrameGetSequence(const otRadioFrame *aFrame)
|
||||
{
|
||||
return static_cast<const Mac::Frame *>(aFrame)->GetSequence();
|
||||
}
|
||||
|
||||
void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress)
|
||||
{
|
||||
static_cast<Mac::TxFrame *>(aFrame)->ProcessTransmitAesCcm(*static_cast<const Mac::ExtAddress *>(aExtAddress));
|
||||
}
|
||||
|
||||
@@ -140,6 +140,16 @@ otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddre
|
||||
*/
|
||||
uint8_t otMacFrameGetSequence(const otRadioFrame *aFrame);
|
||||
|
||||
/**
|
||||
* This function performs AES CCM on the frame which is going to be sent.
|
||||
*
|
||||
* @param[in] aFrame A pointer to the MAC frame buffer that is going to be sent.
|
||||
* @param[in] aExtAddress A pointer to the extended address, which will be used to generate nonce
|
||||
* for AES CCM computation.
|
||||
*
|
||||
*/
|
||||
void otMacFrameProcessTransmitAesCcm(otRadioFrame *aFrame, const otExtAddress *aExtAddress);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -610,21 +610,6 @@ extern void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, otRad
|
||||
*/
|
||||
extern void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError);
|
||||
|
||||
/**
|
||||
* The radio driver calls this method to notify OpenThread to process transmit security for the frame,
|
||||
* this happens when the frame includes Header IE(s) that were updated before transmission.
|
||||
*
|
||||
* This function is used when feature `OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT` is enabled.
|
||||
*
|
||||
* @note This function can be called from interrupt context and it would only read/write data passed in
|
||||
* via @p aFrame, but would not read/write any state within OpenThread.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aFrame The radio frame which needs to process transmit security.
|
||||
*
|
||||
*/
|
||||
extern void otPlatRadioFrameUpdated(otInstance *aInstance, otRadioFrame *aFrame);
|
||||
|
||||
/**
|
||||
* Get the most recent RSSI measurement.
|
||||
*
|
||||
|
||||
+1
-26
@@ -879,31 +879,6 @@ bool Mac::IsJoinable(void) const
|
||||
return (numUnsecurePorts != 0);
|
||||
}
|
||||
|
||||
void Mac::ProcessTransmitAesCcm(TxFrame &aFrame, const ExtAddress *aExtAddress)
|
||||
{
|
||||
uint32_t frameCounter = 0;
|
||||
uint8_t securityLevel;
|
||||
uint8_t nonce[KeyManager::kNonceSize];
|
||||
uint8_t tagLength;
|
||||
Crypto::AesCcm aesCcm;
|
||||
otError error;
|
||||
|
||||
aFrame.GetSecurityLevel(securityLevel);
|
||||
aFrame.GetFrameCounter(frameCounter);
|
||||
|
||||
KeyManager::GenerateNonce(*aExtAddress, frameCounter, securityLevel, nonce);
|
||||
|
||||
aesCcm.SetKey(aFrame.GetAesKey(), 16);
|
||||
tagLength = aFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
|
||||
error = aesCcm.Init(aFrame.GetHeaderLength(), aFrame.GetPayloadLength(), tagLength, nonce, sizeof(nonce));
|
||||
assert(error == OT_ERROR_NONE);
|
||||
|
||||
aesCcm.Header(aFrame.GetHeader(), aFrame.GetHeaderLength());
|
||||
aesCcm.Payload(aFrame.GetPayload(), aFrame.GetPayload(), aFrame.GetPayloadLength(), true);
|
||||
aesCcm.Finalize(aFrame.GetFooter(), &tagLength);
|
||||
}
|
||||
|
||||
void Mac::ProcessTransmitSecurity(TxFrame &aFrame, bool aProcessAesCcm)
|
||||
{
|
||||
KeyManager & keyManager = Get<KeyManager>();
|
||||
@@ -966,7 +941,7 @@ void Mac::ProcessTransmitSecurity(TxFrame &aFrame, bool aProcessAesCcm)
|
||||
|
||||
if (aProcessAesCcm)
|
||||
{
|
||||
ProcessTransmitAesCcm(aFrame, extAddress);
|
||||
aFrame.ProcessTransmitAesCcm(*extAddress);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
@@ -613,16 +613,6 @@ public:
|
||||
*/
|
||||
bool IsEnabled(void) const { return mEnabled; }
|
||||
|
||||
/**
|
||||
* This method performs AES CCM on the frame which is going to be sent.
|
||||
*
|
||||
* @param[in] aFrame A reference to the MAC frame buffer that is going to be sent.
|
||||
* @param[in] aExtAddress A pointer to the extended address, which will be used to generate nonce
|
||||
* for AES CCM computation.
|
||||
*
|
||||
*/
|
||||
static void ProcessTransmitAesCcm(TxFrame &aFrame, const ExtAddress *aExtAddress);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "crypto/aes_ccm.hpp"
|
||||
#include "thread/key_manager.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Mac {
|
||||
@@ -998,6 +1000,40 @@ void TxFrame::CopyFrom(const TxFrame &aFromFrame)
|
||||
#endif
|
||||
}
|
||||
|
||||
void TxFrame::ProcessTransmitAesCcm(const ExtAddress &aExtAddress)
|
||||
{
|
||||
#if OPENTHREAD_RADIO
|
||||
OT_UNUSED_VARIABLE(aExtAddress);
|
||||
#else
|
||||
uint32_t frameCounter = 0;
|
||||
uint8_t securityLevel;
|
||||
uint8_t nonce[KeyManager::kNonceSize];
|
||||
uint8_t tagLength;
|
||||
Crypto::AesCcm aesCcm;
|
||||
otError error;
|
||||
|
||||
VerifyOrExit(GetSecurityEnabled());
|
||||
|
||||
SuccessOrExit(error = GetSecurityLevel(securityLevel));
|
||||
SuccessOrExit(error = GetFrameCounter(frameCounter));
|
||||
|
||||
KeyManager::GenerateNonce(aExtAddress, frameCounter, securityLevel, nonce);
|
||||
|
||||
aesCcm.SetKey(GetAesKey(), 16);
|
||||
tagLength = GetFooterLength() - Frame::kFcsSize;
|
||||
|
||||
error = aesCcm.Init(GetHeaderLength(), GetPayloadLength(), tagLength, nonce, sizeof(nonce));
|
||||
assert(error == OT_ERROR_NONE);
|
||||
|
||||
aesCcm.Header(GetHeader(), GetHeaderLength());
|
||||
aesCcm.Payload(GetPayload(), GetPayload(), GetPayloadLength(), true);
|
||||
aesCcm.Finalize(GetFooter(), &tagLength);
|
||||
|
||||
exit:
|
||||
return;
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
|
||||
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_NOTE) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
|
||||
|
||||
@@ -1095,6 +1095,14 @@ public:
|
||||
*/
|
||||
void CopyFrom(const TxFrame &aFromFrame);
|
||||
|
||||
/**
|
||||
* This method performs AES CCM on the frame which is going to be sent.
|
||||
*
|
||||
* @param[in] aExtAddress A reference to the extended address, which will be used to generate nonce
|
||||
* for AES CCM computation.
|
||||
*
|
||||
*/
|
||||
void ProcessTransmitAesCcm(const ExtAddress &aExtAddress);
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
/**
|
||||
* This method sets the Time IE offset.
|
||||
|
||||
@@ -558,13 +558,6 @@ exit:
|
||||
return swEnergyScan;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void SubMac::HandleFrameUpdated(TxFrame &aFrame)
|
||||
{
|
||||
mCallbacks.FrameUpdated(aFrame);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SubMac::SetState(State aState)
|
||||
{
|
||||
if (mState != aState)
|
||||
|
||||
@@ -167,20 +167,6 @@ public:
|
||||
*
|
||||
*/
|
||||
void EnergyScanDone(int8_t aMaxRssi);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
/**
|
||||
* The method notifies user of `SubMac` to process transmit security for the frame, which happens when the
|
||||
* frame includes Header IE(s) that were updated before transmission.
|
||||
*
|
||||
* @note This function can be called from interrupt context and it would only read/write data passed in
|
||||
* via @p aFrame, but would not read/write any state within OpenThread.
|
||||
*
|
||||
* @param[in] aFrame The frame which needs to process transmit security.
|
||||
*
|
||||
*/
|
||||
void FrameUpdated(TxFrame &aFrame);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -393,9 +379,6 @@ private:
|
||||
void HandleTransmitStarted(TxFrame &aFrame);
|
||||
void HandleTransmitDone(TxFrame &aTxFrame, RxFrame *aAckFrame, otError aError);
|
||||
void HandleEnergyScanDone(int8_t aMaxRssi);
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void HandleFrameUpdated(TxFrame &aFrame);
|
||||
#endif
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
@@ -104,22 +104,6 @@ void SubMac::Callbacks::EnergyScanDone(int8_t aMaxRssi)
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void SubMac::Callbacks::FrameUpdated(TxFrame &aFrame)
|
||||
{
|
||||
/**
|
||||
* This function will be called from interrupt context, it should only read/write data passed in
|
||||
* via @p aFrame, but should not read/write any state within OpenThread.
|
||||
*
|
||||
*/
|
||||
|
||||
if (aFrame.GetSecurityEnabled())
|
||||
{
|
||||
Get<Mac>().ProcessTransmitAesCcm(aFrame, &Get<Mac>().GetExtAddress());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif OPENTHREAD_RADIO
|
||||
|
||||
void SubMac::Callbacks::ReceiveDone(RxFrame *aFrame, otError aError)
|
||||
@@ -150,19 +134,6 @@ void SubMac::Callbacks::EnergyScanDone(int8_t aMaxRssi)
|
||||
Get<LinkRaw>().InvokeEnergyScanDone(aMaxRssi);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void SubMac::Callbacks::FrameUpdated(TxFrame &)
|
||||
{
|
||||
/**
|
||||
* This function will be called from interrupt context, it should only read/write data passed in
|
||||
* via @p aFrame, but should not read/write any state within OpenThread.
|
||||
*
|
||||
*/
|
||||
|
||||
// For now this functionality is not supported in Radio Only mode.
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_RADIO
|
||||
|
||||
} // namespace Mac
|
||||
|
||||
@@ -147,22 +147,6 @@ public:
|
||||
*/
|
||||
void HandleEnergyScanDone(int8_t aMaxRssi);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
/**
|
||||
* This callback method handles a "Frame Updated" event from radio platform.
|
||||
*
|
||||
* This is called to notify OpenThread to process transmit security for the frame, this happens when the frame
|
||||
* includes Header IE(s) that were updated before transmission. It is called from `otPlatRadioFrameUpdated()`.
|
||||
*
|
||||
* @note This method can be called from interrupt context and it would only read/write data passed in
|
||||
* via @p aFrame, but would not read/write any state within OpenThread.
|
||||
*
|
||||
* @param[in] aFrame The frame which needs to process transmit security.
|
||||
*
|
||||
*/
|
||||
void HandleFrameUpdated(Mac::TxFrame &aFrame);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
/**
|
||||
* This callback method handles a "Receive Done" event from radio platform when diagnostics mode is enabled.
|
||||
|
||||
@@ -58,13 +58,6 @@ void Radio::Callbacks::HandleEnergyScanDone(int8_t aMaxRssi)
|
||||
Get<Mac::SubMac>().HandleEnergyScanDone(aMaxRssi);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void Radio::Callbacks::HandleFrameUpdated(Mac::TxFrame &aFrame)
|
||||
{
|
||||
Get<Mac::SubMac>().HandleFrameUpdated(aFrame);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
void Radio::Callbacks::HandleDiagsReceiveDone(Mac::RxFrame *aFrame, otError aError)
|
||||
{
|
||||
|
||||
@@ -81,18 +81,6 @@ extern "C" void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyS
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
extern "C" void otPlatRadioFrameUpdated(otInstance *aInstance, otRadioFrame *aFrame)
|
||||
{
|
||||
Instance *instance = static_cast<Instance *>(aInstance);
|
||||
|
||||
if (instance->IsInitialized())
|
||||
{
|
||||
instance->Get<Radio::Callbacks>().HandleFrameUpdated(*static_cast<Mac::TxFrame *>(aFrame));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
extern "C" void otPlatDiagRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user