[border-agent] support multiple parallel sessions (#11212)

This commit updates the `BorderAgent` implementation to support
multiple parallel sessions using PSKc. It adds new public OT APIs to
iterate over all sessions, along with related CLI commands. The nexus
`test_border_agent` is updated to cover multi-session behavior and
the new session iteration APIs.
This commit is contained in:
Abtin Keshavarzian
2025-02-12 11:04:13 -08:00
committed by GitHub
parent 1b9b73f2b7
commit 15a789267d
9 changed files with 527 additions and 161 deletions
+270 -79
View File
@@ -36,16 +36,21 @@
namespace ot {
namespace Nexus {
using BorderAgent = MeshCoP::BorderAgent;
using BorderAgent = MeshCoP::BorderAgent;
using EphemeralKeyManager = ot::MeshCoP::BorderAgent::EphemeralKeyManager;
void TestBorderAgent(void)
{
Core nexus;
Node &node0 = nexus.CreateNode();
Node &node1 = nexus.CreateNode();
Ip6::SockAddr sockAddr;
Pskc pskc;
Coap::Message *message;
Core nexus;
Node &node0 = nexus.CreateNode();
Node &node1 = nexus.CreateNode();
Node &node2 = nexus.CreateNode();
Node &node3 = nexus.CreateNode();
Ip6::SockAddr sockAddr;
Pskc pskc;
Coap::Message *message;
BorderAgent::SessionIterator iter;
BorderAgent::SessionInfo sessionInfo;
Log("------------------------------------------------------------------------------------------------------");
Log("TestBorderAgent");
@@ -54,7 +59,7 @@ void TestBorderAgent(void)
// Form the topology:
// - node0 leader acting as Border Agent,
// - node1 staying disconnected (acting as candidate)
// - node1-3 stay disconnected (acting as candidate)
node0.Form();
nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
@@ -64,10 +69,18 @@ void TestBorderAgent(void)
node1.Get<Mac::Mac>().SetPanId(node0.Get<Mac::Mac>().GetPanId());
node1.Get<ThreadNetif>().Up();
SuccessOrQuit(node2.Get<Mac::Mac>().SetPanChannel(node0.Get<Mac::Mac>().GetPanChannel()));
node2.Get<Mac::Mac>().SetPanId(node0.Get<Mac::Mac>().GetPanId());
node2.Get<ThreadNetif>().Up();
SuccessOrQuit(node3.Get<Mac::Mac>().SetPanChannel(node0.Get<Mac::Mac>().GetPanChannel()));
node3.Get<Mac::Mac>().SetPanId(node0.Get<Mac::Mac>().GetPanId());
node3.Get<ThreadNetif>().Up();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check Border Agent initial state");
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
SuccessOrQuit(node0.Get<Ip6::Filter>().AddUnsecurePort(node0.Get<BorderAgent>().GetUdpPort()));
@@ -87,9 +100,15 @@ void TestBorderAgent(void)
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcSecureSessionSuccesses == 1);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Disconnect from candidate side");
@@ -98,7 +117,10 @@ void TestBorderAgent(void)
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
iter.Init(node0.GetInstance());
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Establish a secure connection again");
@@ -110,9 +132,15 @@ void TestBorderAgent(void)
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcSecureSessionSuccesses == 2);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Send `Commissioner Petition` TMF command to become full commissioner");
@@ -123,19 +151,29 @@ void TestBorderAgent(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateAccepted);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcSecureSessionSuccesses == 2);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcCommissionerPetitions == 1);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Send `Commissioner Keep Alive` and check timeout behavior");
nexus.AdvanceTime(30 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateAccepted);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(sessionInfo.mIsCommissioner);
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerKeepAlive);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(Tlv::Append<MeshCoP::StateTlv>(*message, MeshCoP::StateTlv::kAccept));
@@ -146,16 +184,18 @@ void TestBorderAgent(void)
nexus.AdvanceTime(49 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateAccepted);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
Log(" Wait for additional 5 seconds (ensuring TIMEOUT_LEAD_PET and session disconnect guard time expires)");
nexus.AdvanceTime(5 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Establish a secure session again and petition to become commissioner");
@@ -163,7 +203,6 @@ void TestBorderAgent(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
message = node1.Get<Tmf::SecureAgent>().NewPriorityConfirmablePostMessage(kUriCommissionerPetition);
VerifyOrQuit(message != nullptr);
@@ -172,12 +211,145 @@ void TestBorderAgent(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateAccepted);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcSecureSessionSuccesses == 3);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcCommissionerPetitions == 2);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Establish two more secure sessions while the first session is still active");
SuccessOrQuit(node2.Get<Tmf::SecureAgent>().SetPsk(pskc.m8, Pskc::kSize));
SuccessOrQuit(node2.Get<Tmf::SecureAgent>().Open());
SuccessOrQuit(node2.Get<Tmf::SecureAgent>().Connect(sockAddr));
SuccessOrQuit(node3.Get<Tmf::SecureAgent>().SetPsk(pskc.m8, Pskc::kSize));
SuccessOrQuit(node3.Get<Tmf::SecureAgent>().Open());
SuccessOrQuit(node3.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node3.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcSecureSessionSuccesses == 5);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mPskcCommissionerPetitions == 2);
iter.Init(node0.GetInstance());
for (uint8_t numSessions = 0; numSessions < 3; numSessions++)
{
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
if (node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)))
{
VerifyOrQuit(sessionInfo.mIsCommissioner);
}
else
{
VerifyOrQuit(node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)) ||
node3.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(!sessionInfo.mIsCommissioner);
}
}
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Disconnect from candidate side on node 1");
node1.Get<Tmf::SecureAgent>().Close();
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node3.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
for (uint8_t numSessions = 0; numSessions < 2; numSessions++)
{
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)) ||
node3.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
}
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Connect again from node 1 after 25 seconds");
nexus.AdvanceTime(25 * Time::kOneSecondInMsec);
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Open());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node3.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
for (uint8_t numSessions = 0; numSessions < 3; numSessions++)
{
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)) ||
node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)) ||
node3.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
}
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Wait for the first two sessions to timeout, check that only the recent node1 session is connected");
nexus.AdvanceTime(28 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(!node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(!node3.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node1.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Wait for the node1 session to also timeout, validate that its disconnected");
nexus.AdvanceTime(25 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(!node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(!node3.Get<Tmf::SecureAgent>().IsConnected());
iter.Init(node0.GetInstance());
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
}
//----------------------------------------------------------------------------------------------------------------------
static bool sEphemeralKeyCallbackCalled = false;
void HandleEphemeralKeyChange(void *aContext)
@@ -188,7 +360,7 @@ void HandleEphemeralKeyChange(void *aContext)
node = reinterpret_cast<Node *>(aContext);
Log(" EphemeralKeyCallback() state:%s",
BorderAgent::EphemeralKeyManager::StateToString(node->Get<BorderAgent::EphemeralKeyManager>().GetState()));
EphemeralKeyManager::StateToString(node->Get<EphemeralKeyManager>().GetState()));
sEphemeralKeyCallbackCalled = true;
}
@@ -201,13 +373,15 @@ void TestBorderAgentEphemeralKey(void)
static constexpr uint16_t kEphemeralKeySize = sizeof(kEphemeralKey) - 1;
static constexpr uint16_t kUdpPort = 49155;
Core nexus;
Node &node0 = nexus.CreateNode();
Node &node1 = nexus.CreateNode();
Node &node2 = nexus.CreateNode();
Ip6::SockAddr sockAddr;
Ip6::SockAddr baSockAddr;
Pskc pskc;
Core nexus;
Node &node0 = nexus.CreateNode();
Node &node1 = nexus.CreateNode();
Node &node2 = nexus.CreateNode();
Ip6::SockAddr sockAddr;
Ip6::SockAddr baSockAddr;
Pskc pskc;
BorderAgent::SessionIterator iter;
BorderAgent::SessionInfo sessionInfo;
Log("------------------------------------------------------------------------------------------------------");
Log("TestBorderAgentEphemeralKey");
@@ -245,15 +419,15 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check Border Agent ephemeral key feature enabled");
node0.Get<MeshCoP::BorderAgent::EphemeralKeyManager>().SetEnabled(false);
VerifyOrQuit(node0.Get<MeshCoP::BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateDisabled);
VerifyOrQuit(node0.Get<MeshCoP::BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0,
kUdpPort) == kErrorInvalidState);
node0.Get<EphemeralKeyManager>().SetEnabled(false);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateDisabled);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort) ==
kErrorInvalidState);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcInvalidBaStateErrors == 1);
node0.Get<MeshCoP::BorderAgent::EphemeralKeyManager>().SetEnabled(true);
VerifyOrQuit(node0.Get<MeshCoP::BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
node0.Get<EphemeralKeyManager>().SetEnabled(true);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check Border Agent ephemeral key initial state");
@@ -264,12 +438,12 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Set and start ephemeral key on Border Agent");
node0.Get<BorderAgent::EphemeralKeyManager>().SetCallback(HandleEphemeralKeyChange, &node0);
node0.Get<EphemeralKeyManager>().SetCallback(HandleEphemeralKeyChange, &node0);
SuccessOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 1);
SuccessOrQuit(node0.Get<Ip6::Filter>().AddUnsecurePort(kUdpPort));
@@ -293,7 +467,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateConnected);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 1);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcSecureSessionSuccesses == 1);
@@ -310,7 +484,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 1);
@@ -322,11 +496,10 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Start using ephemeral key again with short timeout (20 seconds) and establish a connection");
SuccessOrQuit(
node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, 20 * Time::kOneSecondInMsec, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, 20 * Time::kOneSecondInMsec, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Open());
SuccessOrQuit(node1.Get<Tmf::SecureAgent>().Connect(sockAddr));
@@ -334,7 +507,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(2 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateConnected);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 2);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcSecureSessionSuccesses == 2);
@@ -346,7 +519,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(25 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 2);
@@ -357,16 +530,16 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Start using ephemeral key without any candidate connecting, check timeout");
SuccessOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
Log(" Wait more than 120 seconds (default ephemeral key timeout)");
sEphemeralKeyCallbackCalled = false;
nexus.AdvanceTime(122 * Time::kOneSecondInMsec);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 3);
@@ -377,10 +550,10 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check that ephemeral key use is stopped after max failed connection attempts");
SuccessOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
SuccessOrQuit(
node1.Get<Tmf::SecureAgent>().SetPsk(reinterpret_cast<const uint8_t *>(kEphemeralKey), kEphemeralKeySize - 2));
@@ -394,7 +567,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
}
Log(" Attempt 10 (final attempt) to connect with the wrong key, check that ephemeral key use is stopped");
@@ -404,7 +577,7 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 4);
@@ -418,10 +591,10 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Validate that disabling ephemeral key will stop and disconnect an active session");
SuccessOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
SuccessOrQuit(
node1.Get<Tmf::SecureAgent>().SetPsk(reinterpret_cast<const uint8_t *>(kEphemeralKey), kEphemeralKeySize));
@@ -432,18 +605,18 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateConnected);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
sEphemeralKeyCallbackCalled = false;
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateConnected);
node0.Get<BorderAgent::EphemeralKeyManager>().SetEnabled(false);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateConnected);
node0.Get<EphemeralKeyManager>().SetEnabled(false);
nexus.AdvanceTime(0);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateDisabled);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateDisabled);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
@@ -459,16 +632,16 @@ void TestBorderAgentEphemeralKey(void)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check ephemeral key can be used along with PSKc");
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
SuccessOrQuit(node0.Get<Ip6::Filter>().AddUnsecurePort(node0.Get<BorderAgent>().GetUdpPort()));
node0.Get<BorderAgent::EphemeralKeyManager>().SetEnabled(true);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
node0.Get<EphemeralKeyManager>().SetEnabled(true);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
SuccessOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
SuccessOrQuit(node0.Get<EphemeralKeyManager>().Start(kEphemeralKey, /* aTimeout */ 0, kUdpPort));
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStarted);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetUdpPort() == kUdpPort);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStarted);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetUdpPort() == kUdpPort);
Log(" Establish a secure session using PSKc (from node2)");
@@ -483,7 +656,13 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
Log(" Establish a secure session using ephemeral key (from node1)");
@@ -497,18 +676,18 @@ void TestBorderAgentEphemeralKey(void)
nexus.AdvanceTime(1 * Time::kOneSecondInMsec);
VerifyOrQuit(node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateConnected);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
Log(" Stop the secure session using ephemeral key");
node0.Get<BorderAgent::EphemeralKeyManager>().Stop();
node0.Get<EphemeralKeyManager>().Stop();
sEphemeralKeyCallbackCalled = false;
nexus.AdvanceTime(0);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
VerifyOrQuit(sEphemeralKeyCallbackCalled);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 6);
@@ -521,27 +700,39 @@ void TestBorderAgentEphemeralKey(void)
Log(" Check the BA session using PSKc is still connected");
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
nexus.AdvanceTime(3 * Time::kOneSecondInMsec);
VerifyOrQuit(!node1.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node2.Get<Tmf::SecureAgent>().IsConnected());
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().GetState() == BorderAgent::kStateStopped);
VerifyOrQuit(node0.Get<BorderAgent>().GetState() == BorderAgent::kStateConnected);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateStopped);
iter.Init(node0.GetInstance());
SuccessOrQuit(iter.GetNextSessionInfo(sessionInfo));
VerifyOrQuit(sessionInfo.mIsConnected);
VerifyOrQuit(!sessionInfo.mIsCommissioner);
VerifyOrQuit(node2.Get<ThreadNetif>().HasUnicastAddress(AsCoreType(&sessionInfo.mPeerSockAddr.mAddress)));
VerifyOrQuit(iter.GetNextSessionInfo(sessionInfo) == kErrorNotFound);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Log("Check proper error is returned with invalid ephemeral key (too short or long)");
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kTooShortEphemeralKey, /* aTimeout */ 0,
kUdpPort) == kErrorInvalidArgs);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().Start(kTooShortEphemeralKey, /* aTimeout */ 0, kUdpPort) ==
kErrorInvalidArgs);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 6);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcInvalidArgsErrors == 1);
VerifyOrQuit(node0.Get<BorderAgent::EphemeralKeyManager>().Start(kTooLongEphemeralKey, /* aTimeout */ 0,
kUdpPort) == kErrorInvalidArgs);
VerifyOrQuit(node0.Get<EphemeralKeyManager>().Start(kTooLongEphemeralKey, /* aTimeout */ 0, kUdpPort) ==
kErrorInvalidArgs);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcActivations == 6);
VerifyOrQuit(node0.Get<BorderAgent>().GetCounters().mEpskcInvalidArgsErrors == 2);
}