[key-manager] update how the "Key Switch Guard Timer" is reset (#10347)

This commit updates the resetting of the Key Switch Guard Timer. It is
now reset under two conditions:

- The device itself triggers a key rotation and moves to the next key
  sequence after the rotation time has passed since the last switch.
- The device receives a MAC or MLE message with an incoming key index
  matching the next key index. Regarding MLE messages, this rule is
  applied regardless of the message being classified as Authoritative
  or Peer.
This commit is contained in:
Abtin Keshavarzian
2024-06-12 10:56:00 -07:00
committed by Jonathan Hui
parent 185b0e18e7
commit 9c1f1f3dfb
5 changed files with 52 additions and 30 deletions
+2 -1
View File
@@ -275,7 +275,8 @@ uint32_t otThreadGetKeySequenceCounter(otInstance *aInstance)
void otThreadSetKeySequenceCounter(otInstance *aInstance, uint32_t aKeySequenceCounter)
{
AsCoreType(aInstance).Get<KeyManager>().SetCurrentKeySequence(aKeySequenceCounter, KeyManager::kForceUpdate);
AsCoreType(aInstance).Get<KeyManager>().SetCurrentKeySequence(
aKeySequenceCounter, KeyManager::kForceUpdate | KeyManager::kGuardTimerUnchanged);
}
uint16_t otThreadGetKeySwitchGuardTime(otInstance *aInstance)
+1 -1
View File
@@ -1641,7 +1641,7 @@ Error Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Neig
if (keySequence > keyManager.GetCurrentKeySequence())
{
keyManager.SetCurrentKeySequence(keySequence, KeyManager::kApplyKeySwitchGuard);
keyManager.SetCurrentKeySequence(keySequence, KeyManager::kApplySwitchGuard | KeyManager::kResetGuardTimer);
}
}
+8 -4
View File
@@ -368,11 +368,11 @@ void KeyManager::UpdateKeyMaterial(void)
#endif
}
void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence, KeySequenceUpdateMode aUpdateMode)
void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence, KeySeqUpdateFlags aFlags)
{
VerifyOrExit(aKeySequence != mKeySequence, Get<Notifier>().SignalIfFirst(kEventThreadKeySeqCounterChanged));
if (aUpdateMode == kApplyKeySwitchGuard)
if (aFlags & kApplySwitchGuard)
{
VerifyOrExit(mKeySwitchGuardTimer == 0);
}
@@ -384,7 +384,11 @@ void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence, KeySequenceUpdateM
mMleFrameCounter = 0;
ResetKeyRotationTimer();
mKeySwitchGuardTimer = mKeySwitchGuardTime;
if (aFlags & kResetGuardTimer)
{
mKeySwitchGuardTimer = mKeySwitchGuardTime;
}
Get<Notifier>().Signal(kEventThreadKeySeqCounterChanged);
@@ -528,7 +532,7 @@ void KeyManager::CheckForKeyRotation(void)
{
if (mHoursSinceKeyRotation >= mSecurityPolicy.mRotationTime)
{
SetCurrentKeySequence(mKeySequence + 1, kForceUpdate);
SetCurrentKeySequence(mKeySequence + 1, kForceUpdate | kResetGuardTimer);
}
}
+17 -11
View File
@@ -221,16 +221,24 @@ class KeyManager : public InstanceLocator, private NonCopyable
{
public:
/**
* Determines whether to apply or ignore key switch guard when updating the key sequence.
* Defines bit-flag constants specifying how to handle key sequence update used in `KeySeqUpdateFlags`.
*
*/
enum KeySeqUpdateFlag : uint8_t
{
kApplySwitchGuard = (1 << 0), ///< Apply key switch guard check.
kForceUpdate = (0 << 0), ///< Ignore key switch guard check and forcibly update.
kResetGuardTimer = (1 << 1), ///< On key seq change, reset the guard timer.
kGuardTimerUnchanged = (0 << 1), ///< On key seq change, leave guard timer unchanged.
};
/**
* Represents a combination of `KeySeqUpdateFlag` bits.
*
* Used as input by `SetCurrentKeySequence()`.
*
*/
enum KeySequenceUpdateMode : uint8_t
{
kApplyKeySwitchGuard, ///< Apply key switch guard check before setting the new key sequence.
kForceUpdate, ///< Ignore key switch guard check and forcibly update the key sequence to new value.
};
typedef uint8_t KeySeqUpdateFlags;
/**
* Initializes the object.
@@ -342,14 +350,12 @@ public:
/**
* Sets the current key sequence value.
*
* If @p aMode is `kApplyKeySwitchGuard`, the current key switch guard timer is checked and only if it is zero, key
* sequence will be updated.
*
* @param[in] aKeySequence The key sequence value.
* @param[in] aUpdateMode Whether or not to apply the key switch guard.
* @param[in] aFlags Specify behavior when updating the key sequence, i.e., whether or not to apply the
* key switch guard or reset guard timer upon change.
*
*/
void SetCurrentKeySequence(uint32_t aKeySequence, KeySequenceUpdateMode aUpdateMode);
void SetCurrentKeySequence(uint32_t aKeySequence, KeySeqUpdateFlags aFlags);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
+24 -13
View File
@@ -371,7 +371,8 @@ void Mle::Restore(void)
SuccessOrExit(Get<Settings>().Read(networkInfo));
Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence(), KeyManager::kForceUpdate);
Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence(),
KeyManager::kForceUpdate | KeyManager::kGuardTimerUnchanged);
Get<KeyManager>().SetMleFrameCounter(networkInfo.GetMleFrameCounter());
Get<KeyManager>().SetAllMacFrameCounters(networkInfo.GetMacFrameCounter(), /* aSetIfLarger */ false);
@@ -2721,33 +2722,43 @@ void Mle::ProcessKeySequence(RxInfo &aRxInfo)
// neighbor.
// Otherwise larger key seq MUST NOT be adopted.
bool isNextKeySeq;
KeyManager::KeySeqUpdateFlags flags = 0;
VerifyOrExit(aRxInfo.mKeySequence > Get<KeyManager>().GetCurrentKeySequence());
isNextKeySeq = (aRxInfo.mKeySequence - Get<KeyManager>().GetCurrentKeySequence() == 1);
switch (aRxInfo.mClass)
{
case RxInfo::kAuthoritativeMessage:
Get<KeyManager>().SetCurrentKeySequence(aRxInfo.mKeySequence, KeyManager::kForceUpdate);
flags = KeyManager::kForceUpdate;
break;
case RxInfo::kPeerMessage:
if ((aRxInfo.mNeighbor != nullptr) && aRxInfo.mNeighbor->IsStateValid())
VerifyOrExit(aRxInfo.IsNeighborStateValid());
if (!isNextKeySeq)
{
if (aRxInfo.mKeySequence - Get<KeyManager>().GetCurrentKeySequence() == 1)
{
Get<KeyManager>().SetCurrentKeySequence(aRxInfo.mKeySequence, KeyManager::kApplyKeySwitchGuard);
}
else
{
LogInfo("Large key seq jump in peer class msg from 0x%04x ", aRxInfo.mNeighbor->GetRloc16());
ReestablishLinkWithNeighbor(*aRxInfo.mNeighbor);
}
LogInfo("Large key seq jump in peer class msg from 0x%04x ", aRxInfo.mNeighbor->GetRloc16());
ReestablishLinkWithNeighbor(*aRxInfo.mNeighbor);
ExitNow();
}
flags = KeyManager::kApplySwitchGuard;
break;
case RxInfo::kUnknown:
break;
ExitNow();
}
if (isNextKeySeq)
{
flags |= KeyManager::kResetGuardTimer;
}
Get<KeyManager>().SetCurrentKeySequence(aRxInfo.mKeySequence, flags);
exit:
return;
}