From af2c77e1712f09cba53860dc8293c99e301bd105 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 24 Sep 2024 15:26:12 -0700 Subject: [PATCH] [border-agent] update ephemeral key connection timeout handling (#10609) This commit enhances how ephemeral key timeout is used. If the timeout expires while a commissioner or commissioner candidate is connected, the session will be terminated. The Border Agent (BA) will then stop using the ephemeral key and revert to using PSKc. The ephemeral key timeout timer starts when the ephemeral key is set on the BA. During this timeout interval, the ephemeral key can be used only once by an external commissioner to establish a secure connection. --- include/openthread/border_agent.h | 9 +++++---- include/openthread/instance.h | 2 +- src/cli/README.md | 2 +- src/core/meshcop/border_agent.cpp | 27 +++++++++++---------------- src/core/meshcop/border_agent.hpp | 9 +++++---- 5 files changed, 23 insertions(+), 26 deletions(-) diff --git a/include/openthread/border_agent.h b/include/openthread/border_agent.h index f2544c8ed..9e6e717a4 100644 --- a/include/openthread/border_agent.h +++ b/include/openthread/border_agent.h @@ -195,9 +195,10 @@ otError otBorderAgentSetId(otInstance *aInstance, const otBorderAgentId *aId); * Setting the ephemeral key again before a previously set key has timed out will replace the previously set key and * reset the timeout. * - * While the timeout interval is in effect, the ephemeral key can be used only once by an external commissioner to - * connect. Once the commissioner disconnects, the ephemeral key is cleared, and the Border Agent reverts to using - * PSKc. + * During the timeout interval, the ephemeral key can be used only once by an external commissioner to establish a + * connection. After the commissioner disconnects, the ephemeral key is cleared, and the Border Agent reverts to + * using PSKc. If the timeout expires while a commissioner is still connected, the session will be terminated, and the + * Border Agent will cease using the ephemeral key and revert to PSKc. * * @param[in] aInstance The OpenThread instance. * @param[in] aKeyString The ephemeral key string (used as PSK excluding the trailing null `\0` character). @@ -229,7 +230,7 @@ otError otBorderAgentSetEphemeralKey(otInstance *aInstance, * * If a commissioner is connected using the ephemeral key and is currently active, calling this function does not * change its state. In this case the `otBorderAgentIsEphemeralKeyActive()` will continue to return `TRUE` until the - * commissioner disconnects. + * commissioner disconnects, or the ephemeral key timeout expires. * * @param[in] aInstance The OpenThread instance. */ diff --git a/include/openthread/instance.h b/include/openthread/instance.h index a9e55198e..576ac6333 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (447) +#define OPENTHREAD_API_VERSION (448) /** * @addtogroup api-instance diff --git a/src/cli/README.md b/src/cli/README.md index 47af9a6a0..9fc707b4a 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -407,7 +407,7 @@ The `port` specifies the UDP port to use with the ephemeral key. If UDP port is Setting the ephemeral key again before a previously set one is timed out, will replace the previous one. -While the timeout interval is in effect, the ephemeral key can be used only once by an external commissioner to connect. Once the commissioner disconnects, the ephemeral key is cleared, and Border Agent reverts to using PSKc. +During the timeout interval, the ephemeral key can be used only once by an external commissioner to establish a connection. After the commissioner disconnects, the ephemeral key is cleared, and the Border Agent reverts to using PSKc. If the timeout expires while a commissioner is still connected, the session will be terminated, and the Border Agent will cease using the ephemeral key and revert to PSKc. ```bash > ba ephemeralkey set Z10X20g3J15w1000P60m16 5000 1234 diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 0b6faf4b7..f4161d2ba 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -672,11 +672,12 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent) if (mUsingEphemeralKey) { RestartAfterRemovingEphemeralKey(); + if (aEvent == SecureTransport::kDisconnectedError) { mCounters.mEpskcSecureSessionFailures++; } - if (aEvent == SecureTransport::kDisconnectedPeerClosed) + else if (aEvent == SecureTransport::kDisconnectedPeerClosed) { mCounters.mEpskcDeactivationDisconnects++; } @@ -686,6 +687,7 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent) { mState = kStateStarted; mUdpProxyPort = 0; + if (aEvent == SecureTransport::kDisconnectedError) { mCounters.mPskcSecureSessionFailures++; @@ -842,16 +844,7 @@ void BorderAgent::ClearEphemeralKey(void) LogInfo("Clearing ephemeral key"); - if (mEphemeralKeyTimer.IsRunning()) - { - mCounters.mEpskcDeactivationClears++; - } - else - { - mCounters.mEpskcDeactivationTimeouts++; - } - - mEphemeralKeyTimer.Stop(); + mCounters.mEpskcDeactivationClears++; switch (mState) { @@ -862,9 +855,10 @@ void BorderAgent::ClearEphemeralKey(void) case kStateStopped: case kStateConnected: case kStateAccepted: - // If there is an active commissioner connection, we wait till - // it gets disconnected before removing ephemeral key and - // restarting the agent. + // If a commissioner connection is currently active, we'll + // wait for it to disconnect or for the ephemeral key timeout + // or `kKeepAliveTimeout` to expire before removing the key + // and restarting the agent. break; } @@ -875,7 +869,8 @@ exit: void BorderAgent::HandleEphemeralKeyTimeout(void) { LogInfo("Ephemeral key timed out"); - ClearEphemeralKey(); + mCounters.mEpskcDeactivationTimeouts++; + RestartAfterRemovingEphemeralKey(); } void BorderAgent::InvokeEphemeralKeyCallback(void) { mEphemeralKeyCallback.InvokeIfSet(); } @@ -896,8 +891,8 @@ void BorderAgent::HandleSecureAgentStopped(void *aContext) void BorderAgent::HandleSecureAgentStopped(void) { LogInfo("Reached max allowed connection attempts with ephemeral key"); - RestartAfterRemovingEphemeralKey(); mCounters.mEpskcDeactivationMaxAttempts++; + RestartAfterRemovingEphemeralKey(); } #endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp index bd1966a5b..385bb3fbf 100644 --- a/src/core/meshcop/border_agent.hpp +++ b/src/core/meshcop/border_agent.hpp @@ -170,9 +170,10 @@ public: * Setting the ephemeral key again before a previously set one is timed out will replace the previous one and will * reset the timeout. * - * While the timeout interval is in effect, the ephemeral key can be used only once by an external commissioner to - * connect. Once the commissioner disconnects, the ephemeral key is cleared, and Border Agent reverts to using - * PSKc. + * During the timeout interval, the ephemeral key can be used only once by an external commissioner to establish a + * connection. After the commissioner disconnects, the ephemeral key is cleared, and the Border Agent reverts to + * using PSKc. If the timeout expires while a commissioner is still connected, the session will be terminated, and + * the Border Agent will cease using the ephemeral key and revert to PSKc. * * @param[in] aKeyString The ephemeral key. * @param[in] aTimeout The timeout duration in milliseconds to use the ephemeral key. @@ -197,7 +198,7 @@ public: * * If a commissioner is connected using the ephemeral key and is currently active, calling this method does not * change its state. In this case the `IsEphemeralKeyActive()` will continue to return `true` until the commissioner - * disconnects. + * disconnects, or the ephemeral key timeout expires. */ void ClearEphemeralKey(void);