From 76f905bfac6034037e23f80dc31199d995e50e38 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 27 Oct 2025 10:31:04 -0700 Subject: [PATCH] [mle] reuse challenge during child role restoration (#12065) Ensure the same challenge is used for all "Child Update Request" messages sent to the parent while trying to restore the previous child role. The challenge is now generated once when the child role restoration process starts in `PrevRoleRestorer::Start`. This prevents a situation where a new challenge from a retry could invalidate a delayed but valid response from the parent that contained the previous challenge. --- src/core/thread/mle.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 2a87fcb98..af224ef29 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1194,8 +1194,17 @@ Error Mle::SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode) case kAppendZeroTimeout: break; case kAppendChallengeTlv: - case kToRestoreChildRole: mPrevRoleRestorer.GenerateRandomChallenge(); + OT_FALL_THROUGH; + + case kToRestoreChildRole: + // The challenge used for child role restoration is generated + // only once, specifically when the `mPrevRoleRestorer` state + // changes and the process starts. We reuse this single challenge + // for all "Child Update Request" retries. This prevents a new + // challenge from invalidating a potentially delayed, yet correct, + // response from the parent. + SuccessOrExit(error = message->AppendChallengeTlv(mPrevRoleRestorer.GetChallenge())); break; } @@ -4284,6 +4293,7 @@ Error Mle::PrevRoleRestorer::Start(void) VerifyOrExit(Get().mLastSavedRole == kRoleChild); VerifyOrExit(Get().mParent.IsStateValidOrRestoring()); SetState(kRestoringChildRole); + GenerateRandomChallenge(); mAttempts = kMaxChildUpdatesToRestoreRole; mTimer.Start(Get().GenerateRandomDelay(kMaxStartDelay)); error = kErrorNone;