From 5c722a770c6f3a0627c93ec5ae3bb3e13e491bbe Mon Sep 17 00:00:00 2001 From: Jintao Lin Date: Tue, 23 Jun 2020 03:23:16 +0800 Subject: [PATCH] [simulation] support transmit security at simulation radio (#5118) This commit adds transmit security support for simulation radio so that security Enh-ACK could be handled at radio layer. This commit also fixes issue #5041. --- examples/platforms/simulation/radio.c | 124 ++++++++++++++++++++++--- examples/platforms/utils/mac_frame.cpp | 43 +++++++++ examples/platforms/utils/mac_frame.h | 60 ++++++++++++ src/core/mac/mac_frame.cpp | 3 - 4 files changed, 213 insertions(+), 17 deletions(-) diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c index 1829f4143..028b910fc 100644 --- a/examples/platforms/simulation/radio.c +++ b/examples/platforms/simulation/radio.c @@ -117,7 +117,18 @@ static bool sSrcMatchEnabled = false; static bool sRadioCoexEnabled = true; #endif -otRadioCaps gRadioCaps = OT_RADIO_CAPS_NONE; +otRadioCaps gRadioCaps = +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + OT_RADIO_CAPS_TRANSMIT_SEC; +#else + OT_RADIO_CAPS_NONE; +#endif + +static uint32_t sMacFrameCounter; +static uint8_t sKeyId; +static struct otMacKey sPrevKey; +static struct otMacKey sCurrKey; +static struct otMacKey sNextKey; static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin) { @@ -543,12 +554,66 @@ static void radioComputeCrc(struct RadioMessage *aMessage, uint16_t aLength) aMessage->mPsdu[crc_offset + 1] = crc >> 8; } +static otError radioProcessTransmitSecurity(otRadioFrame *aFrame) +{ + otError error = OT_ERROR_NONE; +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + struct otMacKey *key = NULL; + uint8_t keyId; + + otEXPECT(otMacFrameIsSecurityEnabled(aFrame) && otMacFrameIsKeyIdMode1(aFrame) && + !aFrame->mInfo.mTxInfo.mIsSecurityProcessed); + + if (otMacFrameIsAck(aFrame)) + { + keyId = otMacFrameGetKeyId(aFrame); + + otEXPECT_ACTION(keyId != 0, error = OT_ERROR_FAILED); + + if (keyId == sKeyId) + { + key = &sCurrKey; + } + else if (keyId == sKeyId - 1) + { + key = &sPrevKey; + } + else if (keyId == sKeyId + 1) + { + key = &sNextKey; + } + else + { + error = OT_ERROR_SECURITY; + otEXPECT(false); + } + } + else + { + key = &sCurrKey; + keyId = sKeyId; + } + + aFrame->mInfo.mTxInfo.mAesKey = key; + + if (!aFrame->mInfo.mTxInfo.mIsARetx) + { + otMacFrameSetKeyId(aFrame, keyId); + otMacFrameSetFrameCounter(aFrame, sMacFrameCounter++); + } +#else + otEXPECT(!aFrame->mInfo.mTxInfo.mIsSecurityProcessed); +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + + otMacFrameProcessTransmitAesCcm(aFrame, &sExtAddress); + +exit: + return error; +} + void radioSendMessage(otInstance *aInstance) { -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT - bool notifyFrameUpdated = false; - -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE +#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) { uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset; @@ -562,19 +627,12 @@ void radioSendMessage(otInstance *aInstance) time = time >> 8; *(++timeIe) = (uint8_t)(time & 0xff); } - - notifyFrameUpdated = true; } -#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - - if (notifyFrameUpdated) - { - otMacFrameProcessTransmitAesCcm(&sTransmitFrame, &sExtAddress); - } -#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE sTransmitMessage.mChannel = sTransmitFrame.mChannel; + otEXPECT(radioProcessTransmitSecurity(&sTransmitFrame) == OT_ERROR_NONE); otPlatRadioTxStarted(aInstance, &sTransmitFrame); radioComputeCrc(&sTransmitMessage, sTransmitFrame.mLength); radioTransmit(&sTransmitMessage, &sTransmitFrame); @@ -602,6 +660,8 @@ void radioSendMessage(otInstance *aInstance) // Wait for echo radio in virtual time mode. sTxWait = true; #endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME +exit: + return; } bool platformRadioIsTransmitPending(void) @@ -754,6 +814,7 @@ void radioSendAck(void) { otEXPECT(otMacFrameGenerateEnhAck(&sReceiveFrame, sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending, NULL, 0, &sAckFrame) == OT_ERROR_NONE); + otEXPECT(radioProcessTransmitSecurity(&sAckFrame) == OT_ERROR_NONE); } else #endif @@ -791,6 +852,13 @@ void radioProcessFrame(otInstance *aInstance) if (otMacFrameIsAckRequested(&sReceiveFrame)) { radioSendAck(); +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + if (otMacFrameIsSecurityEnabled(&sAckFrame)) + { + sReceiveFrame.mInfo.mRxInfo.mAckedWithSecEnhAck = true; + sReceiveFrame.mInfo.mRxInfo.mAckFrameCounter = otMacFrameGetFrameCounter(&sAckFrame); + } +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 } exit: @@ -947,3 +1015,31 @@ exit: return error; } #endif + +void otPlatRadioSetMacKey(otInstance * aInstance, + uint8_t aKeyIdMode, + uint8_t aKeyId, + const otMacKey *aPrevKey, + const otMacKey *aCurrKey, + const otMacKey *aNextKey) +{ + OT_UNUSED_VARIABLE(aInstance); + OT_UNUSED_VARIABLE(aKeyIdMode); + + otEXPECT(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL); + + sKeyId = aKeyId; + memcpy(sPrevKey.m8, aPrevKey->m8, OT_MAC_KEY_SIZE); + memcpy(sCurrKey.m8, aCurrKey->m8, OT_MAC_KEY_SIZE); + memcpy(sNextKey.m8, aNextKey->m8, OT_MAC_KEY_SIZE); + +exit: + return; +} + +void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter) +{ + OT_UNUSED_VARIABLE(aInstance); + + sMacFrameCounter = aMacFrameCounter; +} diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index fe81247a2..7a3272832 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -159,3 +159,46 @@ void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCsl static_cast(aFrame)->SetCslIe(aCslPeriod, aCslPhase); } #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + +bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame) +{ + return static_cast(aFrame)->GetSecurityEnabled(); +} + +bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame) +{ + uint8_t keyIdMode; + otError error; + + error = static_cast(aFrame)->GetKeyIdMode(keyIdMode); + + return (error == OT_ERROR_NONE) ? (keyIdMode == Mac::Frame::kKeyIdMode1) : false; +} + +uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame) +{ + uint8_t keyId = 0; + + IgnoreError(static_cast(aFrame)->GetKeyId(keyId)); + + return keyId; +} + +void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId) +{ + static_cast(aFrame)->SetKeyId(aKeyId); +} + +uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame) +{ + uint32_t frameCounter = UINT32_MAX; + + IgnoreError(static_cast(aFrame)->GetFrameCounter(frameCounter)); + + return frameCounter; +} + +void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter) +{ + static_cast(aFrame)->SetFrameCounter(aFrameCounter); +} diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h index aa53f462e..f7fff115f 100644 --- a/examples/platforms/utils/mac_frame.h +++ b/examples/platforms/utils/mac_frame.h @@ -211,6 +211,66 @@ otError otMacFrameGenerateEnhAck(const otRadioFrame *aFrame, */ void otMacFrameSetCslIe(otRadioFrame *aFrame, uint16_t aCslPeriod, uint16_t aCslPhase); +/** + * Tell if the security of @p aFrame is enabled. + * + * @param[in] aFrame A pointer to the frame. + * + * @retval true The frame has security enabled. + * @retval false The frame does not have security enabled. + * + */ +bool otMacFrameIsSecurityEnabled(otRadioFrame *aFrame); + +/** + * Tell if the key ID mode of @p aFrame is 1. + * + * @param[in] aFrame A pointer to the frame. + * + * @retval true The frame key ID mode is 1. + * @retval false The frame security is not enabled or key ID mode is not 1. + * + */ +bool otMacFrameIsKeyIdMode1(otRadioFrame *aFrame); + +/** + * Get the key ID of @p aFrame. + * + * @param[in] aFrame A pointer to the frame. + * + * @returns The key ID of the frame with key ID mode 1. Returns 0 if failed. + * + */ +uint8_t otMacFrameGetKeyId(otRadioFrame *aFrame); + +/** + * Set key ID to @p aFrame with key ID mode 1. + * + * @param[inout] aFrame A pointer to the frame to be modified. + * @param[in] aKeyId Key ID to be set to the frame. + * + */ +void otMacFrameSetKeyId(otRadioFrame *aFrame, uint8_t aKeyId); + +/** + * Get the frame counter of @p aFrame. + * + * @param[in] aFrame A pointer to the frame. + * + * @returns The frame counter of the frame. Returns UINT32_MAX if failed. + * + */ +uint32_t otMacFrameGetFrameCounter(otRadioFrame *aFrame); + +/** + * Set frame counter to @p aFrame. + * + * @param[inout] aFrame A pointer to the frame to be modified. + * @param[in] aFrameCounter Frame counter to be set to the frame. + * + */ +void otMacFrameSetFrameCounter(otRadioFrame *aFrame, uint32_t aFrameCounter); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index e47a635ea..51d42de4c 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -1092,7 +1092,6 @@ otError TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, con PanId panId; uint8_t footerLength; uint8_t securityControlField; - uint32_t frameCounter; uint8_t keyId; mChannel = aFrame.mChannel; @@ -1170,11 +1169,9 @@ otError TxFrame::GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, con if (aFrame.GetSecurityEnabled()) { SuccessOrExit(error = aFrame.GetSecurityControlField(securityControlField)); - SuccessOrExit(error = aFrame.GetFrameCounter(frameCounter)); SuccessOrExit(error = aFrame.GetKeyId(keyId)); SetSecurityControlField(securityControlField); - SetFrameCounter(frameCounter); SetKeyId(keyId); }