[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:
Yakun Xu
2019-11-13 07:36:18 +01:00
committed by Jonathan Hui
parent 4758624a7a
commit b95281666d
15 changed files with 69 additions and 141 deletions
+8 -1
View File
@@ -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
+1 -1
View File
@@ -545,7 +545,7 @@ void radioSendMessage(otInstance *aInstance)
if (notifyFrameUpdated)
{
otPlatRadioFrameUpdated(aInstance, &sTransmitFrame);
otMacFrameProcessTransmitAesCcm(&sTransmitFrame, &sExtAddress);
}
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
+5
View File
@@ -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));
}
+10
View File
@@ -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
-15
View File
@@ -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
View File
@@ -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:
-10
View File
@@ -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
{
+36
View File
@@ -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)
+8
View File
@@ -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.
-7
View File
@@ -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)
-17
View File
@@ -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);
-29
View File
@@ -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
-16
View File
@@ -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.
-7
View File
@@ -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)
{
-12
View File
@@ -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)
{