From b19b2cfa75fb786966b9afcc1ec5fad4a26014e3 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 20 Jul 2023 10:07:09 -0700 Subject: [PATCH] [mle] define separate `TxChallenge` and `RxChallenge` types (#9304) This commit defines two types to track challenge or response TLV data in MLE messages: - `TxChallenge` represents the maximum-sized challenge data to include and send in MLE messages. OpenThread always uses the maximum size of 8 bytes for challenge data in the messages it sends. - `RxChallenge` represents variable-length challenge data read from a received MLE message. The two separate types help to simplify their use in code. --- src/core/thread/mle.cpp | 82 ++++++++++------------------ src/core/thread/mle.hpp | 95 ++++++++------------------------ src/core/thread/mle_router.cpp | 77 +++++++++++++------------- src/core/thread/mle_router.hpp | 10 ++-- src/core/thread/mle_types.cpp | 32 +++++++++++ src/core/thread/mle_types.hpp | 99 +++++++++++++++++++++++++++++++++- src/core/thread/topology.cpp | 11 ---- src/core/thread/topology.hpp | 30 +++-------- 8 files changed, 230 insertions(+), 206 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index f33cf451c..1779a9dbe 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1801,7 +1801,7 @@ Error Mle::SendChildIdRequest(void) } VerifyOrExit((message = NewMleMessage(kCommandChildIdRequest)) != nullptr, error = kErrorNoBufs); - SuccessOrExit(error = message->AppendResponseTlv(mParentCandidate.mChallenge)); + SuccessOrExit(error = message->AppendResponseTlv(mParentCandidate.mRxChallenge)); SuccessOrExit(error = message->AppendLinkFrameCounterTlv()); SuccessOrExit(error = message->AppendMleFrameCounterTlv()); SuccessOrExit(error = message->AppendModeTlv(mDeviceMode)); @@ -2139,7 +2139,7 @@ exit: return error; } -Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const Challenge &aChallenge) +Error Mle::SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge) { Error error = kErrorNone; Ip6::Address destination; @@ -3118,7 +3118,7 @@ void Mle::HandleParentResponse(RxInfo &aRxInfo) { Error error = kErrorNone; int8_t rss = aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss(); - Challenge response; + RxChallenge response; uint16_t version; uint16_t sourceAddress; LeaderData leaderData; @@ -3288,7 +3288,7 @@ void Mle::HandleParentResponse(RxInfo &aRxInfo) #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE // Challenge - SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(mParentCandidate.mChallenge)); + SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(mParentCandidate.mRxChallenge)); InitNeighbor(mParentCandidate, aRxInfo); mParentCandidate.SetRloc16(sourceAddress); @@ -3447,11 +3447,11 @@ exit: void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo) { - Error error = kErrorNone; - uint16_t sourceAddress; - Challenge challenge; - TlvList requestedTlvList; - TlvList tlvList; + Error error = kErrorNone; + uint16_t sourceAddress; + RxChallenge challenge; + TlvList requestedTlvList; + TlvList tlvList; // Source Address SuccessOrExit(error = Tlv::Find(aRxInfo.mMessage, sourceAddress)); @@ -3467,7 +3467,7 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo) tlvList.Add(Tlv::kLinkFrameCounter); break; case kErrorNotFound: - challenge.mLength = 0; + challenge.Clear(); break; default: ExitNow(error = kErrorParse); @@ -3531,7 +3531,7 @@ void Mle::HandleChildUpdateRequest(RxInfo &aRxInfo) ProcessKeySequence(aRxInfo); #if OPENTHREAD_CONFIG_MULTI_RADIO - if ((aRxInfo.mNeighbor != nullptr) && (challenge.mLength != 0)) + if ((aRxInfo.mNeighbor != nullptr) && !challenge.IsEmpty()) { aRxInfo.mNeighbor->ClearLastRxFragmentTag(); } @@ -3545,14 +3545,14 @@ exit: void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo) { - Error error = kErrorNone; - uint8_t status; - uint8_t mode; - Challenge response; - uint32_t linkFrameCounter; - uint32_t mleFrameCounter; - uint16_t sourceAddress; - uint32_t timeout; + Error error = kErrorNone; + uint8_t status; + uint8_t mode; + RxChallenge response; + uint32_t linkFrameCounter; + uint32_t mleFrameCounter; + uint16_t sourceAddress; + uint32_t timeout; Log(kMessageReceive, kTypeChildUpdateResponseOfParent, aRxInfo.mMessageInfo.GetPeerAddr()); @@ -3561,7 +3561,7 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo) case kErrorNone: break; case kErrorNotFound: - response.mLength = 0; + response.Clear(); break; default: ExitNow(error = kErrorParse); @@ -3681,7 +3681,7 @@ void Mle::HandleChildUpdateResponse(RxInfo &aRxInfo) OT_ASSERT(false); } - aRxInfo.mClass = (response.mLength == 0) ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage; + aRxInfo.mClass = response.IsEmpty() ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage; exit: @@ -4413,20 +4413,6 @@ void Mle::TlvList::AddElementsFrom(const TlvList &aTlvList) } } -//--------------------------------------------------------------------------------------------------------------------- -// Challenge - -void Mle::Challenge::GenerateRandom(void) -{ - mLength = kMaxChallengeSize; - IgnoreError(Random::Crypto::FillBuffer(mBuffer, mLength)); -} - -bool Mle::Challenge::Matches(const uint8_t *aBuffer, uint8_t aLength) const -{ - return (mLength == aLength) && (memcmp(mBuffer, aBuffer, aLength) == 0); -} - //--------------------------------------------------------------------------------------------------------------------- // DelayedResponseMetadata @@ -4529,19 +4515,14 @@ Error Mle::TxMessage::AppendModeTlv(DeviceMode aMode) { return Tlv::Append(*this, aTimeout); } -Error Mle::TxMessage::AppendChallengeTlv(const Challenge &aChallenge) +Error Mle::TxMessage::AppendChallengeTlv(const TxChallenge &aChallenge) { - return Tlv::Append(*this, aChallenge.mBuffer, aChallenge.mLength); + return Tlv::Append(*this, &aChallenge, sizeof(aChallenge)); } -Error Mle::TxMessage::AppendChallengeTlv(const uint8_t *aChallenge, uint8_t aChallengeLength) +Error Mle::TxMessage::AppendResponseTlv(const RxChallenge &aResponse) { - return Tlv::Append(*this, aChallenge, aChallengeLength); -} - -Error Mle::TxMessage::AppendResponseTlv(const Challenge &aResponse) -{ - return Tlv::Append(*this, aResponse.mBuffer, aResponse.mLength); + return Tlv::Append(*this, aResponse.GetBytes(), aResponse.GetLength()); } Error Mle::TxMessage::AppendLinkFrameCounterTlv(void) @@ -4960,30 +4941,25 @@ Error Mle::TxMessage::AppendPendingDatasetTlv(void) //--------------------------------------------------------------------------------------------------------------------- // RxMessage -Error Mle::RxMessage::ReadChallengeOrResponse(uint8_t aTlvType, Challenge &aBuffer) const +Error Mle::RxMessage::ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const { Error error; uint16_t offset; uint16_t length; SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, aTlvType, offset, length)); - VerifyOrExit(length >= kMinChallengeSize, error = kErrorParse); - - length = Min(length, kMaxChallengeSize); - - ReadBytes(offset, aBuffer.mBuffer, length); - aBuffer.mLength = static_cast(length); + error = aRxChallenge.ReadFrom(*this, offset, length); exit: return error; } -Error Mle::RxMessage::ReadChallengeTlv(Challenge &aChallenge) const +Error Mle::RxMessage::ReadChallengeTlv(RxChallenge &aChallenge) const { return ReadChallengeOrResponse(Tlv::kChallenge, aChallenge); } -Error Mle::RxMessage::ReadResponseTlv(Challenge &aResponse) const +Error Mle::RxMessage::ReadResponseTlv(RxChallenge &aResponse) const { return ReadChallengeOrResponse(Tlv::kResponse, aResponse); } diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 9ebb07dd2..29a69b911 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -881,45 +881,6 @@ protected: void AddElementsFrom(const TlvList &aTlvList); }; - /** - * Represents a Challenge (or Response) data. - * - */ - struct Challenge - { - uint8_t mBuffer[kMaxChallengeSize]; ///< Buffer containing the challenge/response byte sequence. - uint8_t mLength; ///< Challenge length (in bytes). - - /** - * Generates a cryptographically secure random sequence to populate the challenge data. - * - */ - void GenerateRandom(void); - - /** - * Indicates whether the Challenge matches a given buffer. - * - * @param[in] aBuffer A pointer to a buffer to compare with the Challenge. - * @param[in] aLength Length of @p aBuffer (in bytes). - * - * @retval TRUE If the Challenge matches the given buffer. - * @retval FALSE If the Challenge does not match the given buffer. - * - */ - bool Matches(const uint8_t *aBuffer, uint8_t aLength) const; - - /** - * Indicates whether two Challenge data byte sequences are equal or not. - * - * @param[in] aOther Another Challenge data to compare. - * - * @retval TRUE If the two Challenges match. - * @retval FALSE If the two Challenges do not match. - * - */ - bool operator==(const Challenge &aOther) const { return Matches(aOther.mBuffer, aOther.mLength); } - }; - /** * Represents an MLE Tx message. * @@ -958,18 +919,6 @@ protected: */ Error AppendTimeoutTlv(uint32_t aTimeout); - /** - * Appends a Challenge TLV to the message. - * - * @param[in] aChallenge A pointer to the Challenge value. - * @param[in] aChallengeLength The length of the Challenge value in bytes. - * - * @retval kErrorNone Successfully appended the Challenge TLV. - * @retval kErrorNoBufs Insufficient buffers available to append the Challenge TLV. - * - */ - Error AppendChallengeTlv(const uint8_t *aChallenge, uint8_t aChallengeLength); - /** * Appends a Challenge TLV to the message. * @@ -979,18 +928,18 @@ protected: * @retval kErrorNoBufs Insufficient buffers available to append the Challenge TLV. * */ - Error AppendChallengeTlv(const Challenge &aChallenge); + Error AppendChallengeTlv(const TxChallenge &aChallenge); /** * Appends a Response TLV to the message. * - * @param[in] aResponse A reference to the Response data. + * @param[in] aResponse The Response data. * * @retval kErrorNone Successfully appended the Response TLV. * @retval kErrorNoBufs Insufficient buffers available to append the Response TLV. * */ - Error AppendResponseTlv(const Challenge &aResponse); + Error AppendResponseTlv(const RxChallenge &aResponse); /** * Appends a Link Frame Counter TLV to the message. @@ -1299,26 +1248,26 @@ protected: /** * Reads Challenge TLV from the message. * - * @param[out] aChallenge A reference to the Challenge data where to output the read value. + * @param[out] aChallenge A `RxChallenge` to output the read challenge data. * * @retval kErrorNone Successfully read the Challenge TLV. * @retval kErrorNotFound Challenge TLV was not found in the message. * @retval kErrorParse Challenge TLV was found but could not be parsed. * */ - Error ReadChallengeTlv(Challenge &aChallenge) const; + Error ReadChallengeTlv(RxChallenge &aChallenge) const; /** * Reads Response TLV from the message. * - * @param[out] aResponse A reference to the Response data where to output the read value. + * @param[out] aResponse A `RxChallenge` to output the read challenge data. * * @retval kErrorNone Successfully read the Response TLV. * @retval kErrorNotFound Response TLV was not found in the message. * @retval kErrorParse Response TLV was found but could not be parsed. * */ - Error ReadResponseTlv(Challenge &aResponse) const; + Error ReadResponseTlv(RxChallenge &aResponse) const; /** * Reads Link and MLE Frame Counters from the message. @@ -1391,7 +1340,7 @@ protected: #endif private: - Error ReadChallengeOrResponse(uint8_t aTlvType, Challenge &aBuffer) const; + Error ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const; }; /** @@ -1563,14 +1512,14 @@ protected: /** * Generates an MLE Child Update Response message. * - * @param[in] aTlvList A list of requested TLV types. - * @param[in] aChallenge The Challenge for the response. + * @param[in] aTlvList A list of requested TLV types. + * @param[in] aChallenge The challenge data to include in response. * * @retval kErrorNone Successfully generated an MLE Child Update Response message. * @retval kErrorNoBufs Insufficient buffers to generate the MLE Child Update Response message. * */ - Error SendChildUpdateResponse(const TlvList &aTlvList, const Challenge &aChallenge); + Error SendChildUpdateResponse(const TlvList &aTlvList, const RxChallenge &aChallenge); /** * Sets the RLOC16 assigned to the Thread interface. @@ -1898,16 +1847,16 @@ private: void Clear(void); void CopyTo(Parent &aParent) const; - Challenge mChallenge; - int8_t mPriority; - uint8_t mLinkQuality3; - uint8_t mLinkQuality2; - uint8_t mLinkQuality1; - uint16_t mSedBufferSize; - uint8_t mSedDatagramCount; - uint8_t mLinkMargin; - LeaderData mLeaderData; - bool mIsSingleton; + RxChallenge mRxChallenge; + int8_t mPriority; + uint8_t mLinkQuality3; + uint8_t mLinkQuality2; + uint8_t mLinkQuality1; + uint16_t mSedBufferSize; + uint8_t mSedDatagramCount; + uint8_t mLinkMargin; + LeaderData mLeaderData; + bool mIsSingleton; }; #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE @@ -2068,7 +2017,7 @@ private: MessageQueue mDelayedResponses; - Challenge mParentRequestChallenge; + TxChallenge mParentRequestChallenge; AttachMode mAttachMode; ParentCandidate mParentCandidate; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 51698982e..7b5817537 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -610,12 +610,11 @@ Error MleRouter::SendLinkRequest(Neighbor *aNeighbor) if (!aNeighbor->IsStateValid()) { aNeighbor->GenerateChallenge(); - SuccessOrExit(error = - message->AppendChallengeTlv(aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize())); + SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge())); } else { - Challenge challenge; + TxChallenge challenge; challenge.GenerateRandom(); SuccessOrExit(error = message->AppendChallengeTlv(challenge)); @@ -635,13 +634,13 @@ exit: void MleRouter::HandleLinkRequest(RxInfo &aRxInfo) { - Error error = kErrorNone; - Neighbor *neighbor = nullptr; - Challenge challenge; - uint16_t version; - LeaderData leaderData; - uint16_t sourceAddress; - TlvList requestedTlvList; + Error error = kErrorNone; + Neighbor *neighbor = nullptr; + RxChallenge challenge; + uint16_t version; + LeaderData leaderData; + uint16_t sourceAddress; + TlvList requestedTlvList; Log(kMessageReceive, kTypeLinkRequest, aRxInfo.mMessageInfo.GetPeerAddr()); @@ -741,7 +740,7 @@ exit: Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor, const TlvList &aRequestedTlvList, - const Challenge &aChallenge) + const RxChallenge &aChallenge) { static const uint8_t kRouterTlvs[] = {Tlv::kLinkMargin}; @@ -794,7 +793,7 @@ Error MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo, { aNeighbor->GenerateChallenge(); - SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge(), aNeighbor->GetChallengeSize())); + SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge())); SuccessOrExit(error = message->AppendTlvRequestTlv(kRouterTlvs)); aNeighbor->SetLastHeard(TimerMilli::GetNow()); aNeighbor->SetState(Neighbor::kStateLinkRequest); @@ -848,7 +847,7 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest) Router *router; Neighbor::State neighborState; uint16_t version; - Challenge response; + RxChallenge response; uint16_t sourceAddress; uint32_t linkFrameCounter; uint32_t mleFrameCounter; @@ -877,7 +876,7 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest) switch (neighborState) { case Neighbor::kStateLinkRequest: - VerifyOrExit(response.Matches(router->GetChallenge(), router->GetChallengeSize()), error = kErrorSecurity); + VerifyOrExit(response == router->GetChallenge(), error = kErrorSecurity); break; case Neighbor::kStateInvalid: @@ -1030,8 +1029,8 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest) if (aRequest) { - Challenge challenge; - TlvList requestedTlvList; + RxChallenge challenge; + TlvList requestedTlvList; // Challenge SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge)); @@ -1388,7 +1387,7 @@ void MleRouter::HandleParentRequest(RxInfo &aRxInfo) Mac::ExtAddress extAddr; uint16_t version; uint8_t scanMask; - Challenge challenge; + RxChallenge challenge; Child *child; uint8_t modeBitmask; DeviceMode mode; @@ -1756,7 +1755,7 @@ exit: return; } -void MleRouter::SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest) +void MleRouter::SendParentResponse(Child *aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest) { Error error = kErrorNone; Ip6::Address destination; @@ -1785,7 +1784,7 @@ void MleRouter::SendParentResponse(Child *aChild, const Challenge &aChallenge, b #endif aChild->GenerateChallenge(); - SuccessOrExit(error = message->AppendChallengeTlv(aChild->GetChallenge(), aChild->GetChallengeSize())); + SuccessOrExit(error = message->AppendChallengeTlv(aChild->GetChallenge())); SuccessOrExit(error = message->AppendLinkMarginTlv(aChild->GetLinkInfo().GetLinkMargin())); SuccessOrExit(error = message->AppendConnectivityTlv()); SuccessOrExit(error = message->AppendVersionTlv()); @@ -2040,7 +2039,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo) Error error = kErrorNone; Mac::ExtAddress extAddr; uint16_t version; - Challenge response; + RxChallenge response; uint32_t linkFrameCounter; uint32_t mleFrameCounter; uint8_t modeBitmask; @@ -2071,7 +2070,7 @@ void MleRouter::HandleChildIdRequest(RxInfo &aRxInfo) // Response SuccessOrExit(error = aRxInfo.mMessage.ReadResponseTlv(response)); - VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity); + VerifyOrExit(response == child->GetChallenge(), error = kErrorSecurity); // Remove existing MLE messages Get().RemoveMessages(*child, Message::kSubTypeMleGeneral); @@ -2224,7 +2223,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo) Mac::ExtAddress extAddr; uint8_t modeBitmask; DeviceMode mode; - Challenge challenge; + RxChallenge challenge; LeaderData leaderData; uint32_t timeout; uint16_t supervisionInterval; @@ -2247,7 +2246,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo) tlvList.Add(Tlv::kResponse); break; case kErrorNotFound: - challenge.mLength = 0; + challenge.Clear(); break; default: ExitNow(error = kErrorParse); @@ -2287,7 +2286,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo) // Parent MUST include Leader Data TLV in Child Update Response tlvList.Add(Tlv::kLeaderData); - if (challenge.mLength != 0) + if (!challenge.IsEmpty()) { tlvList.Add(Tlv::kMleFrameCounter); tlvList.Add(Tlv::kLinkFrameCounter); @@ -2432,7 +2431,7 @@ void MleRouter::HandleChildUpdateRequest(RxInfo &aRxInfo) // from a detached child trying to restore its link with its // parent which is indicated by the presence of Challenge TLV in // the message. - if (challenge.mLength != 0) + if (!challenge.IsEmpty()) { child->ClearLastRxFragmentTag(); } @@ -2448,15 +2447,15 @@ exit: void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo) { - Error error = kErrorNone; - uint16_t sourceAddress; - uint32_t timeout; - Challenge response; - uint8_t status; - uint32_t linkFrameCounter; - uint32_t mleFrameCounter; - LeaderData leaderData; - Child *child; + Error error = kErrorNone; + uint16_t sourceAddress; + uint32_t timeout; + RxChallenge response; + uint8_t status; + uint32_t linkFrameCounter; + uint32_t mleFrameCounter; + LeaderData leaderData; + Child *child; if ((aRxInfo.mNeighbor == nullptr) || IsActiveRouter(aRxInfo.mNeighbor->GetRloc16()) || !Get().Contains(*aRxInfo.mNeighbor)) @@ -2471,11 +2470,11 @@ void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo) switch (aRxInfo.mMessage.ReadResponseTlv(response)) { case kErrorNone: - VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = kErrorSecurity); + VerifyOrExit(response == child->GetChallenge(), error = kErrorSecurity); break; case kErrorNotFound: VerifyOrExit(child->IsStateValid(), error = kErrorSecurity); - response.mLength = 0; + response.Clear(); break; default: ExitNow(error = kErrorNone); @@ -2594,7 +2593,7 @@ void MleRouter::HandleChildUpdateResponse(RxInfo &aRxInfo) child->SetKeySequence(aRxInfo.mKeySequence); child->GetLinkInfo().AddRss(aRxInfo.mMessageInfo.GetThreadLinkInfo()->GetRss()); - aRxInfo.mClass = (response.mLength == 0) ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage; + aRxInfo.mClass = response.IsEmpty() ? RxInfo::kPeerMessage : RxInfo::kAuthoritativeMessage; exit: LogProcessError(kTypeChildUpdateResponseOfChild, error); @@ -3040,7 +3039,7 @@ Error MleRouter::SendChildUpdateRequest(Child &aChild) { SuccessOrExit(error = message->AppendTlvRequestTlv(kTlvs)); aChild.GenerateChallenge(); - SuccessOrExit(error = message->AppendChallengeTlv(aChild.GetChallenge(), aChild.GetChallengeSize())); + SuccessOrExit(error = message->AppendChallengeTlv(aChild.GetChallenge())); } destination.SetToLinkLocalAddress(aChild.GetExtAddress()); @@ -3062,7 +3061,7 @@ exit: void MleRouter::SendChildUpdateResponse(Child *aChild, const Ip6::MessageInfo &aMessageInfo, const TlvList &aTlvList, - const Challenge &aChallenge) + const RxChallenge &aChallenge) { Error error = kErrorNone; TxMessage *message; diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index e7caafe2d..801722b8f 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -617,14 +617,14 @@ private: Error SendLinkAccept(const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor, const TlvList &aRequestedTlvList, - const Challenge &aChallenge); - void SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest); + const RxChallenge &aChallenge); + void SendParentResponse(Child *aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest); Error SendChildIdResponse(Child &aChild); Error SendChildUpdateRequest(Child &aChild); void SendChildUpdateResponse(Child *aChild, const Ip6::MessageInfo &aMessageInfo, const TlvList &aTlvList, - const Challenge &aChallenge); + const RxChallenge &aChallenge); void SendDataResponse(const Ip6::Address &aDestination, const TlvList &aTlvList, uint16_t aDelay, @@ -668,8 +668,8 @@ private: ChildTable mChildTable; RouterTable mRouterTable; - uint8_t mChallengeTimeout; - Challenge mChallenge; + uint8_t mChallengeTimeout; + TxChallenge mChallenge; uint16_t mNextChildId; uint8_t mNetworkIdTimeout; diff --git a/src/core/thread/mle_types.cpp b/src/core/thread/mle_types.cpp index f762b1a35..c278d1bde 100644 --- a/src/core/thread/mle_types.cpp +++ b/src/core/thread/mle_types.cpp @@ -35,6 +35,8 @@ #include "common/array.hpp" #include "common/code_utils.hpp" +#include "common/message.hpp" +#include "common/random.hpp" namespace ot { namespace Mle { @@ -150,6 +152,36 @@ uint8_t RouterIdSet::GetNumberOfAllocatedIds(void) const return count; } +//--------------------------------------------------------------------------------------------------------------------- +// TxChallenge + +void TxChallenge::GenerateRandom(void) { IgnoreError(Random::Crypto::Fill(*this)); } + +//--------------------------------------------------------------------------------------------------------------------- +// RxChallenge + +Error RxChallenge::ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength) +{ + Error error = kErrorNone; + + Clear(); + + aLength = Min(aLength, kMaxChallengeSize); + VerifyOrExit(kMinChallengeSize <= aLength, error = kErrorParse); + + SuccessOrExit(error = aMessage.Read(aOffset, mArray.GetArrayBuffer(), aLength)); + mArray.SetLength(static_cast(aLength)); + +exit: + return error; +} + +bool RxChallenge::operator==(const TxChallenge &aTxChallenge) const +{ + return (mArray.GetLength() == kMaxChallengeSize) && + (memcmp(mArray.GetArrayBuffer(), aTxChallenge.m8, kMaxChallengeSize) == 0); +} + //--------------------------------------------------------------------------------------------------------------------- const char *RoleToString(DeviceRole aRole) diff --git a/src/core/thread/mle_types.hpp b/src/core/thread/mle_types.hpp index 4ed90cadf..c959f9a56 100644 --- a/src/core/thread/mle_types.hpp +++ b/src/core/thread/mle_types.hpp @@ -45,6 +45,7 @@ #include #endif +#include "common/array.hpp" #include "common/as_core_type.hpp" #include "common/clearable.hpp" #include "common/code_utils.hpp" @@ -57,6 +58,9 @@ #include "thread/network_data_types.hpp" namespace ot { + +class Message; + namespace Mle { /** @@ -130,8 +134,8 @@ constexpr uint16_t kMaxChildId = 511; ///< Maximum Child ID constexpr uint8_t kRouterIdOffset = 10; ///< Bit offset of Router ID in RLOC16 constexpr uint8_t kRlocPrefixLength = 14; ///< Prefix length of RLOC in bytes -constexpr uint16_t kMinChallengeSize = 4; ///< Minimum Challenge size in bytes. -constexpr uint16_t kMaxChallengeSize = 8; ///< Maximum Challenge size in bytes. +constexpr uint8_t kMinChallengeSize = 4; ///< Minimum Challenge size in bytes. +constexpr uint8_t kMaxChallengeSize = 8; ///< Maximum Challenge size in bytes. /* * Routing Protocol Constants @@ -574,6 +578,97 @@ private: uint8_t mRouterIdSet[BitVectorBytes(Mle::kMaxRouterId + 1)]; } OT_TOOL_PACKED_END; +class RxChallenge; + +/** + * Represents a max-sized challenge data to send in MLE message. + * + * OpenThread always uses max size challenge when sending MLE messages. + * + */ +class TxChallenge : public Clearable +{ + friend class RxChallenge; + +public: + /** + * Generates a cryptographically secure random sequence to populate the challenge data. + * + */ + void GenerateRandom(void); + +private: + uint8_t m8[kMaxChallengeSize]; +}; + +/** + * Represents a received Challenge data from an MLE message. + * + */ +class RxChallenge +{ +public: + /** + * Clears the challenge. + * + */ + void Clear(void) { mArray.Clear(); } + + /** + * Indicates whether or not the challenge data is empty. + * + * @retval TRUE The challenge is empty. + * @retval FALSE The challenge is not empty. + * + */ + bool IsEmpty(void) const { return mArray.GetLength() == 0; } + + /** + * Gets a pointer to challenge data bytes. + * + * @return A pointer to the challenge data bytes. + * + */ + const uint8_t *GetBytes(void) const { return mArray.GetArrayBuffer(); } + + /** + * Gets the length of challenge data. + * + * @returns The length of challenge data in bytes. + * + */ + uint8_t GetLength(void) const { return mArray.GetLength(); } + + /** + * Reads the challenge bytes from given message. + * + * If the given @p aLength is longer than `kMaxChallengeSize`, only `kMaxChallengeSize` bytes will be read. + * + * @param[in] aMessage The message to read the challenge from. + * @param[in] aOffset The offset in @p aMessage to read from. + * @param[in] aLength Number of bytes to read. + * + * @retval kErrorNone Successfully read the challenge data from @p aMessage. + * @retval kErrorParse Not enough bytes to read, or invalid @p aLength (smaller than `kMinChallgeSize`). + * + */ + Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength); + + /** + * Compares the `RxChallenge` with a given `TxChallenge`. + * + * @param[in] aTxChallenge The `TxChallenge` to compare with. + * + * @retval TRUE The two challenges are equal. + * @retval FALSE The two challenges are not equal. + * + */ + bool operator==(const TxChallenge &aTxChallenge) const; + +private: + Array mArray; +}; + /** * Represents a MLE Key Material * diff --git a/src/core/thread/topology.cpp b/src/core/thread/topology.cpp index ebb6c94dd..68b58006e 100644 --- a/src/core/thread/topology.cpp +++ b/src/core/thread/topology.cpp @@ -196,12 +196,6 @@ bool Neighbor::IsLastRxFragmentTagSet(void) const } #endif -void Neighbor::GenerateChallenge(void) -{ - IgnoreError( - Random::Crypto::FillBuffer(mValidPending.mPending.mChallenge, sizeof(mValidPending.mPending.mChallenge))); -} - #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss) { @@ -492,11 +486,6 @@ exit: } #endif -void Child::GenerateChallenge(void) -{ - IgnoreError(Random::Crypto::FillBuffer(mAttachChallenge, sizeof(mAttachChallenge))); -} - #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE bool Child::HasMlrRegisteredAddress(const Ip6::Address &aAddress) const { diff --git a/src/core/thread/topology.hpp b/src/core/thread/topology.hpp index 31f1f20e4..e91670438 100644 --- a/src/core/thread/topology.hpp +++ b/src/core/thread/topology.hpp @@ -652,7 +652,7 @@ public: * Generates a new challenge value for MLE Link Request/Response exchanges. * */ - void GenerateChallenge(void); + void GenerateChallenge(void) { mValidPending.mPending.mChallenge.GenerateRandom(); } /** * Returns the current challenge value for MLE Link Request/Response exchanges. @@ -660,15 +660,7 @@ public: * @returns The current challenge value. * */ - const uint8_t *GetChallenge(void) const { return mValidPending.mPending.mChallenge; } - - /** - * Returns the size (bytes) of the challenge value for MLE Link Request/Response exchanges. - * - * @returns The size (bytes) of the challenge value for MLE Link Request/Response exchanges. - * - */ - uint8_t GetChallengeSize(void) const { return sizeof(mValidPending.mPending.mChallenge); } + const Mle::TxChallenge &GetChallenge(void) const { return mValidPending.mPending.mChallenge; } #if OPENTHREAD_CONFIG_UPTIME_ENABLE /** @@ -819,7 +811,7 @@ private: } mValid; struct { - uint8_t mChallenge[Mle::kMaxChallengeSize]; ///< The challenge value + Mle::TxChallenge mChallenge; ///< The challenge value } mPending; } mValidPending; @@ -1183,7 +1175,7 @@ public: * Generates a new challenge value to use during a child attach. * */ - void GenerateChallenge(void); + void GenerateChallenge(void) { mAttachChallenge.GenerateRandom(); } /** * Gets the current challenge value used during attach. @@ -1191,15 +1183,7 @@ public: * @returns The current challenge value. * */ - const uint8_t *GetChallenge(void) const { return mAttachChallenge; } - - /** - * Gets the challenge size (bytes) used during attach. - * - * @returns The challenge size (bytes). - * - */ - uint8_t GetChallengeSize(void) const { return sizeof(mAttachChallenge); } + const Mle::TxChallenge &GetChallenge(void) const { return mAttachChallenge; } /** * Clears the requested TLV list. @@ -1355,8 +1339,8 @@ private: union { - uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs - uint8_t mAttachChallenge[Mle::kMaxChallengeSize]; ///< The challenge value + uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs + Mle::TxChallenge mAttachChallenge; ///< The challenge value }; uint16_t mSupervisionInterval; // Supervision interval for the child (in sec).