Skip to content

Commit

Permalink
[border-agent] use separate DTLS transport and CoAP secure session (o…
Browse files Browse the repository at this point in the history
…penthread#11085)

This commit updates `BorderAgent` to utilize its own DTLS `Transport`
and CoAP `SecureSession`, separating it from the shared
`Tmf::SecureAgent` used by `Commissioner` and `Joiner` modules. This
change enables future support for multiple sessions within
`BorderAgent`.
  • Loading branch information
abtink authored Dec 28, 2024
1 parent 6bb4b7c commit 1024a1f
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 96 deletions.
137 changes: 81 additions & 56 deletions src/core/meshcop/border_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ BorderAgent::BorderAgent(Instance &aInstance)
, mState(kStateStopped)
, mUdpReceiver(BorderAgent::HandleUdpReceive, this)
, mTimer(aInstance)
, mDtlsTransport(aInstance, kNoLinkSecurity)
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
, mIdInitialized(false)
#endif
Expand Down Expand Up @@ -122,17 +123,20 @@ Error BorderAgent::Start(uint16_t aUdpPort, const uint8_t *aPsk, uint8_t aPskLen
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
if (mUsingEphemeralKey)
{
SuccessOrExit(error = Get<Tmf::SecureAgent>().SetMaxConnectionAttempts(kMaxEphemeralKeyConnectionAttempts,
HandleSecureAgentStopped, this));
SuccessOrExit(error = mDtlsTransport.SetMaxConnectionAttempts(kMaxEphemeralKeyConnectionAttempts,
HandleDtlsTransportClosed, this));
}
#endif

SuccessOrExit(error = Get<Tmf::SecureAgent>().Open());
SuccessOrExit(error = Get<Tmf::SecureAgent>().Bind(aUdpPort));
mCoapDtlsSession.Reset(CoapDtlsSession::Allocate(GetInstance(), mDtlsTransport));
VerifyOrExit(mCoapDtlsSession != nullptr, error = kErrorNoBufs);

SuccessOrExit(error = Get<Tmf::SecureAgent>().SetPsk(aPsk, aPskLength));
SuccessOrExit(error = mDtlsTransport.Open());
SuccessOrExit(error = mDtlsTransport.Bind(aUdpPort));

Get<Tmf::SecureAgent>().SetConnectCallback(HandleConnected, this);
SuccessOrExit(error = mDtlsTransport.SetPsk(aPsk, aPskLength));

mCoapDtlsSession->SetConnectCallback(HandleConnected, this);

mState = kStateStarted;

Expand All @@ -157,7 +161,8 @@ void BorderAgent::Stop(void)
#endif

mTimer.Stop();
Get<Tmf::SecureAgent>().Close();
mDtlsTransport.Close();
mCoapDtlsSession.Free();

mState = kStateStopped;
LogInfo("Border Agent stopped");
Expand All @@ -170,13 +175,13 @@ void BorderAgent::Disconnect(void)
{
VerifyOrExit(mState == kStateConnected || mState == kStateAccepted);

Get<Tmf::SecureAgent>().Disconnect();
mCoapDtlsSession->Disconnect();

exit:
return;
}

uint16_t BorderAgent::GetUdpPort(void) const { return Get<Tmf::SecureAgent>().GetUdpPort(); }
uint16_t BorderAgent::GetUdpPort(void) const { return mDtlsTransport.GetUdpPort(); }

void BorderAgent::HandleNotifierEvents(Events aEvents)
{
Expand Down Expand Up @@ -212,7 +217,7 @@ void BorderAgent::HandleNotifierEvents(Events aEvents)

// If there is secure session already established, it won't be impacted,
// new pskc will be applied for next connection.
SuccessOrExit(Get<Tmf::SecureAgent>().SetPsk(pskc.m8, Pskc::kSize));
SuccessOrExit(mDtlsTransport.SetPsk(pskc.m8, Pskc::kSize));
pskc.Clear();
}
}
Expand All @@ -223,9 +228,9 @@ void BorderAgent::HandleNotifierEvents(Events aEvents)

void BorderAgent::HandleTimeout(void)
{
if (Get<Tmf::SecureAgent>().IsConnected())
if (mCoapDtlsSession->IsConnected())
{
Get<Tmf::SecureAgent>().Disconnect();
mCoapDtlsSession->Disconnect();
LogWarn("Reset secure session");
}
}
Expand Down Expand Up @@ -287,14 +292,7 @@ void BorderAgent::HandleConnected(Dtls::Session::ConnectEvent aEvent)
}
}

template <>
void BorderAgent::HandleTmf<kUriCommissionerPetition>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
IgnoreError(ForwardToLeader(aMessage, aMessageInfo, kUriLeaderPetition));
}

template <>
void BorderAgent::HandleTmf<kUriCommissionerKeepAlive>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void BorderAgent::HandleTmfCommissionerKeepAlive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
VerifyOrExit(mState == kStateAccepted);

Expand Down Expand Up @@ -332,7 +330,7 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes

if (separate)
{
SuccessOrExit(error = Get<Tmf::SecureAgent>().SendAck(aMessage, aMessageInfo));
SuccessOrExit(error = mCoapDtlsSession->SendAck(aMessage, aMessageInfo));
}

forwardContext.Reset(ForwardContext::AllocateAndInit(GetInstance(), aMessage, petition, separate));
Expand Down Expand Up @@ -390,7 +388,7 @@ void BorderAgent::HandleCoapResponse(const ForwardContext &aForwardContext,
Error error;

SuccessOrExit(error = aResult);
VerifyOrExit((message = Get<Tmf::SecureAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
VerifyOrExit((message = mCoapDtlsSession->NewPriorityMessage()) != nullptr, error = kErrorNoBufs);

if (aForwardContext.IsPetition() && aResponse->GetCode() == Coap::kCodeChanged)
{
Expand Down Expand Up @@ -470,7 +468,7 @@ bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageIn

VerifyOrExit(aMessage.GetLength() > 0);

message = Get<Tmf::SecureAgent>().NewPriorityNonConfirmablePostMessage(kUriProxyRx);
message = mCoapDtlsSession->NewPriorityNonConfirmablePostMessage(kUriProxyRx);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);

offsetRange.InitFromMessageOffsetToEnd(aMessage);
Expand All @@ -487,7 +485,7 @@ bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageIn

SuccessOrExit(error = Tlv::Append<Ip6AddressTlv>(*message, aMessageInfo.GetPeerAddr()));

SuccessOrExit(error = SendMessage(*message));
SuccessOrExit(error = mCoapDtlsSession->SendMessage(*message));

LogInfo("Sent ProxyRx (c/ur) to commissioner");

Expand All @@ -506,7 +504,7 @@ Error BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const M
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, offsetRange));

SuccessOrExit(error = SendMessage(aForwardMessage));
SuccessOrExit(error = mCoapDtlsSession->SendMessage(aForwardMessage));

LogInfo("Sent to commissioner");

Expand All @@ -515,16 +513,14 @@ Error BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const M
return error;
}

Error BorderAgent::SendMessage(Coap::Message &aMessage) { return Get<Tmf::SecureAgent>().SendMessage(aMessage); }

void BorderAgent::SendErrorMessage(const ForwardContext &aForwardContext, Error aError)
{
Error error = kErrorNone;
Coap::Message *message = nullptr;

VerifyOrExit((message = Get<Tmf::SecureAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
VerifyOrExit((message = mCoapDtlsSession->NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = aForwardContext.ToHeader(*message, CoapCodeFromError(aError)));
SuccessOrExit(error = SendMessage(*message));
SuccessOrExit(error = mCoapDtlsSession->SendMessage(*message));

exit:
FreeMessageOnError(message, error);
Expand All @@ -536,7 +532,7 @@ void BorderAgent::SendErrorMessage(const Coap::Message &aRequest, bool aSeparate
Error error = kErrorNone;
Coap::Message *message = nullptr;

VerifyOrExit((message = Get<Tmf::SecureAgent>().NewPriorityMessage()) != nullptr, error = kErrorNoBufs);
VerifyOrExit((message = mCoapDtlsSession->NewPriorityMessage()) != nullptr, error = kErrorNoBufs);

if (aRequest.IsNonConfirmable() || aSeparate)
{
Expand All @@ -554,7 +550,7 @@ void BorderAgent::SendErrorMessage(const Coap::Message &aRequest, bool aSeparate

SuccessOrExit(error = message->SetTokenFromMessage(aRequest));

SuccessOrExit(error = SendMessage(*message));
SuccessOrExit(error = mCoapDtlsSession->SendMessage(*message));

exit:
FreeMessageOnError(message, error);
Expand Down Expand Up @@ -596,7 +592,7 @@ template <> void BorderAgent::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, co

VerifyOrExit(aMessage.IsNonConfirmablePostRequest(), error = kErrorDrop);

message = Get<Tmf::SecureAgent>().NewPriorityNonConfirmablePostMessage(kUriRelayRx);
message = mCoapDtlsSession->NewPriorityNonConfirmablePostMessage(kUriRelayRx);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);

SuccessOrExit(error = ForwardToCommissioner(*message, aMessage));
Expand All @@ -606,7 +602,7 @@ template <> void BorderAgent::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, co
FreeMessageOnError(message, error);
}

template <> void BorderAgent::HandleTmf<kUriProxyTx>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void BorderAgent::HandleTmfProxyTx(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);

Expand Down Expand Up @@ -643,25 +639,7 @@ template <> void BorderAgent::HandleTmf<kUriProxyTx>(Coap::Message &aMessage, co
LogWarnOnError(error, "send proxy stream");
}

template <>
void BorderAgent::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriCommissionerGet);
}

template <> void BorderAgent::HandleTmf<kUriActiveGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriActiveGet);
mCounters.mMgmtActiveGets++;
}

template <> void BorderAgent::HandleTmf<kUriPendingGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriPendingGet);
mCounters.mMgmtPendingGets++;
}

template <> void BorderAgent::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void BorderAgent::HandleTmfRelayTx(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);

Expand Down Expand Up @@ -710,10 +688,12 @@ void BorderAgent::HandleTmfDatasetGet(Coap::Message &aMessage, const Ip6::Messag
{
case kUriActiveGet:
response = Get<ActiveDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
mCounters.mMgmtActiveGets++;
break;

case kUriPendingGet:
response = Get<PendingDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
mCounters.mMgmtPendingGets++;
break;

case kUriCommissionerGet:
Expand All @@ -726,7 +706,7 @@ void BorderAgent::HandleTmfDatasetGet(Coap::Message &aMessage, const Ip6::Messag

VerifyOrExit(response != nullptr, error = kErrorParse);

SuccessOrExit(error = Get<Tmf::SecureAgent>().SendMessage(*response));
SuccessOrExit(error = mCoapDtlsSession->SendMessage(*response));

LogInfo("Sent %s response to non-active commissioner", PathForUri(aUri));

Expand Down Expand Up @@ -846,12 +826,12 @@ void BorderAgent::RestartAfterRemovingEphemeralKey(void)
IgnoreError(Start(mOldUdpPort));
}

void BorderAgent::HandleSecureAgentStopped(void *aContext)
void BorderAgent::HandleDtlsTransportClosed(void *aContext)
{
reinterpret_cast<BorderAgent *>(aContext)->HandleSecureAgentStopped();
reinterpret_cast<BorderAgent *>(aContext)->HandleDtlsTransportClosed();
}

void BorderAgent::HandleSecureAgentStopped(void)
void BorderAgent::HandleDtlsTransportClosed(void)
{
LogInfo("Reached max allowed connection attempts with ephemeral key");
mCounters.mEpskcDeactivationMaxAttempts++;
Expand All @@ -860,6 +840,51 @@ void BorderAgent::HandleSecureAgentStopped(void)

#endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE

//----------------------------------------------------------------------------------------------------------------------
// `BorderAgent::CoapDtlsSession

bool BorderAgent::CoapDtlsSession::HandleResource(CoapBase &aCoapBase,
const char *aUriPath,
Coap::Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<CoapDtlsSession &>(aCoapBase).HandleResource(aUriPath, aMessage, aMessageInfo);
}

bool BorderAgent::CoapDtlsSession::HandleResource(const char *aUriPath,
Coap::Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
bool didHandle = true;
Uri uri = UriFromPath(aUriPath);

switch (uri)
{
case kUriCommissionerPetition:
IgnoreError(Get<BorderAgent>().ForwardToLeader(aMessage, aMessageInfo, kUriLeaderPetition));
break;
case kUriCommissionerKeepAlive:
Get<BorderAgent>().HandleTmfCommissionerKeepAlive(aMessage, aMessageInfo);
break;
case kUriRelayTx:
Get<BorderAgent>().HandleTmfRelayTx(aMessage, aMessageInfo);
break;
case kUriCommissionerGet:
case kUriActiveGet:
case kUriPendingGet:
Get<BorderAgent>().HandleTmfDatasetGet(aMessage, aMessageInfo, uri);
break;
case kUriProxyTx:
Get<BorderAgent>().HandleTmfProxyTx(aMessage, aMessageInfo);
break;
default:
didHandle = false;
break;
}

return didHandle;
}

//----------------------------------------------------------------------------------------------------------------------
// `BorderAgent::ForwardContext`

Expand Down
Loading

0 comments on commit 1024a1f

Please sign in to comment.