[dtls] refine CoAP secure and DTLS (#3632)

`CoapSecure` is always used by joiner, border agent or commissioner.
DTLS should not be shared with the application `CoapSecure`.

This commit includes the following changes:
* allow multiple DTLS by using `TimerMilliContext`
* move `CoAP::mSocket` into `Dtls`
* move `ThreadNetif::mDtls` into `CoapSecure`
* remove unnecessary getters of `Dtls` and `CoapSecure`
This commit is contained in:
Yakun Xu
2019-03-08 08:11:41 -08:00
committed by Jonathan Hui
parent 96725a985e
commit 7a0eb2c2e7
14 changed files with 386 additions and 319 deletions
+2 -4
View File
@@ -78,21 +78,19 @@ typedef void (*otHandleCoapSecureClientConnect)(bool aConnected, void *aContext)
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aPort The local UDP port to bind to.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully started the CoAP Secure server.
*
*/
otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort, void *aContext);
otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort);
/**
* This function stops the CoAP Secure server.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval OT_ERROR_NONE Successfully stopped the CoAP Secure server.
*/
otError otCoapSecureStop(otInstance *aInstance);
void otCoapSecureStop(otInstance *aInstance);
/**
* This method sets the Pre-Shared Key (PSK) and cipher suite
+7 -15
View File
@@ -147,7 +147,7 @@ otError CoapSecure::Process(int argc, char *argv[])
}
}
otCoapSecureSetSslAuthMode(mInterpreter.mInstance, mVerifyPeerCert);
SuccessOrExit(error = otCoapSecureStart(mInterpreter.mInstance, OT_DEFAULT_COAP_SECURE_PORT, this));
SuccessOrExit(error = otCoapSecureStart(mInterpreter.mInstance, OT_DEFAULT_COAP_SECURE_PORT));
otCoapSecureSetClientConnectedCallback(mInterpreter.mInstance, &CoapSecure::HandleClientConnect, this);
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
otCoapSecureSetDefaultHandler(mInterpreter.mInstance, &CoapSecure::DefaultHandle, this);
@@ -274,7 +274,7 @@ otError CoapSecure::Process(int argc, char *argv[])
}
else
{
SuccessOrExit(error = Stop());
Stop();
}
}
else if (strcmp(argv[0], "help") == 0)
@@ -311,13 +311,11 @@ exit:
return error;
}
otError CoapSecure::Stop(void)
void CoapSecure::Stop(void)
{
otError error = OT_ERROR_ABORT;
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
error = otCoapSecureStop(mInterpreter.mInstance);
mInterpreter.mServer->OutputFormat("Coap Secure service stopped: ");
return error;
otCoapSecureStop(mInterpreter.mInstance);
mInterpreter.mServer->OutputFormat("Coap Secure service stopped");
}
void OTCALL CoapSecure::HandleClientConnect(bool aConnected, void *aContext)
@@ -342,14 +340,8 @@ void CoapSecure::HandleClientConnect(bool aConnected)
else
{
mInterpreter.mServer->OutputFormat("CoAP Secure disconnected before stop.\r\n> ");
if (Stop() == OT_ERROR_NONE)
{
mInterpreter.mServer->OutputFormat(" Done\r\n> ");
}
else
{
mInterpreter.mServer->OutputFormat(" With error\r\n> ");
}
Stop();
mInterpreter.mServer->OutputFormat(" Done\r\n> ");
mShutdownFlag = false;
}
}
+1 -1
View File
@@ -90,7 +90,7 @@ private:
otError ProcessRequest(int argc, char *argv[]);
otError Stop(void);
void Stop(void);
static void OTCALL HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo);
+4 -4
View File
@@ -44,11 +44,11 @@
using namespace ot;
otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort, void *aContext)
otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetApplicationCoapSecure().Start(aPort, NULL, aContext);
return instance.GetApplicationCoapSecure().Start(aPort);
}
otError otCoapSecureSetCertificate(otInstance * aInstance,
@@ -184,11 +184,11 @@ bool otCoapSecureIsConnectionActive(otInstance *aInstance)
return instance.GetApplicationCoapSecure().IsConnectionActive();
}
otError otCoapSecureStop(otInstance *aInstance)
void otCoapSecureStop(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetApplicationCoapSecure().Stop();
instance.GetApplicationCoapSecure().Stop();
}
otError otCoapSecureSendRequest(otInstance * aInstance,
+32 -182
View File
@@ -49,35 +49,37 @@ namespace Coap {
CoapSecure::CoapSecure(Instance &aInstance, bool aLayerTwoSecurity)
: CoapBase(aInstance, &CoapSecure::Send)
, mDtls(aInstance, aLayerTwoSecurity)
, mConnectedCallback(NULL)
, mConnectedContext(NULL)
, mTransportCallback(NULL)
, mTransportContext(NULL)
, mTransmitQueue()
, mTransmitTask(aInstance, &CoapSecure::HandleTransmit, this)
, mSocket(aInstance.GetThreadNetif().GetIp6().GetUdp())
, mLayerTwoSecurity(aLayerTwoSecurity)
{
}
otError CoapSecure::Start(uint16_t aPort, TransportCallback aCallback, void *aContext)
otError CoapSecure::Start(uint16_t aPort)
{
otError error = OT_ERROR_NONE;
mTransportCallback = aCallback;
mTransportContext = aContext;
otError error = OT_ERROR_NONE;
mConnectedCallback = NULL;
mConnectedContext = NULL;
// Passing mTransportCallback means that we do not want to use socket
// to transmit/receive messages, so do not open it in that case.
if (mTransportCallback == NULL)
{
Ip6::SockAddr sockaddr;
SuccessOrExit(error = mDtls.Open(&CoapSecure::HandleDtlsReceive, &CoapSecure::HandleDtlsConnected, this));
SuccessOrExit(error = mDtls.Bind(aPort));
sockaddr.mPort = aPort;
SuccessOrExit(error = mSocket.Open(&CoapSecure::HandleUdpReceive, this));
VerifyOrExit((error = mSocket.Bind(sockaddr)) == OT_ERROR_NONE, mSocket.Close());
}
exit:
return error;
}
otError CoapSecure::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext)
{
otError error = OT_ERROR_NONE;
mConnectedCallback = NULL;
mConnectedContext = NULL;
SuccessOrExit(error = mDtls.Open(&CoapSecure::HandleDtlsReceive, &CoapSecure::HandleDtlsConnected, this));
SuccessOrExit(error = mDtls.Bind(aCallback, aContext));
exit:
return error;
@@ -89,16 +91,9 @@ void CoapSecure::SetConnectedCallback(ConnectedCallback aCallback, void *aContex
mConnectedContext = aContext;
}
otError CoapSecure::Stop(void)
void CoapSecure::Stop(void)
{
otError error;
SuccessOrExit(error = mSocket.Close());
if (IsConnectionActive())
{
Disconnect();
}
mDtls.Stop();
for (ot::Message *message = mTransmitQueue.GetHead(); message != NULL; message = message->GetNext())
{
@@ -106,66 +101,20 @@ otError CoapSecure::Stop(void)
message->Free();
}
mTransportCallback = NULL;
mTransportContext = NULL;
ClearRequestsAndResponses();
exit:
return error;
}
otError CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext)
{
memcpy(&mPeerAddress.mPeerAddr, &aSockAddr.mAddress, sizeof(mPeerAddress.mPeerAddr));
mPeerAddress.mPeerPort = aSockAddr.mPort;
if (aSockAddr.GetAddress().IsLinkLocal() || aSockAddr.GetAddress().IsMulticast())
{
mPeerAddress.mInterfaceId = aSockAddr.mScopeId;
}
else
{
mPeerAddress.mInterfaceId = 0;
}
mConnectedCallback = aCallback;
mConnectedContext = aContext;
return GetNetif().GetDtls().Start(true, &CoapSecure::HandleDtlsConnected, &CoapSecure::HandleDtlsReceive,
&CoapSecure::HandleDtlsSend, this);
}
bool CoapSecure::IsConnectionActive(void)
{
return GetNetif().GetDtls().GetState() != MeshCoP::Dtls::kStateStopped;
}
bool CoapSecure::IsConnected(void)
{
return GetNetif().GetDtls().GetState() == MeshCoP::Dtls::kStateConnected;
}
void CoapSecure::Disconnect(void)
{
GetNetif().GetDtls().Stop();
// Disconnect from previous peer by connecting to any address
{
otError error = mSocket.Connect(Ip6::SockAddr());
assert(error == OT_ERROR_NONE);
}
}
MeshCoP::Dtls &CoapSecure::GetDtls(void)
{
return GetNetif().GetDtls();
return mDtls.Connect(aSockAddr);
}
otError CoapSecure::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
{
return GetNetif().GetDtls().SetPsk(aPsk, aPskLength);
return mDtls.SetPsk(aPsk, aPskLength);
}
#if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
@@ -176,12 +125,12 @@ otError CoapSecure::SetCertificate(const uint8_t *aX509Cert,
const uint8_t *aPrivateKey,
uint32_t aPrivateKeyLength)
{
return GetNetif().GetDtls().SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
return mDtls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
}
otError CoapSecure::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
{
return GetNetif().GetDtls().SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength);
return mDtls.SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength);
}
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
@@ -191,14 +140,14 @@ otError CoapSecure::SetPreSharedKey(const uint8_t *aPsk,
const uint8_t *aPskIdentity,
uint16_t aPskIdLength)
{
return GetNetif().GetDtls().SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength);
return mDtls.SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength);
}
#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#ifdef MBEDTLS_BASE64_C
otError CoapSecure::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
return GetNetif().GetDtls().GetPeerCertificateBase64(aPeerCert, aCertLength, aCertBufferSize);
return mDtls.GetPeerCertificateBase64(aPeerCert, aCertLength, aCertBufferSize);
}
#endif // MBEDTLS_BASE64_C
@@ -210,7 +159,7 @@ void CoapSecure::SetClientConnectedCallback(ConnectedCallback aCallback, void *a
void CoapSecure::SetSslAuthMode(bool aVerifyPeerCertificate)
{
GetNetif().GetDtls().SetSslAuthMode(aVerifyPeerCertificate);
mDtls.SetSslAuthMode(aVerifyPeerCertificate);
}
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
@@ -221,7 +170,7 @@ otError CoapSecure::SendMessage(Message &aMessage, otCoapResponseHandler aHandle
VerifyOrExit(IsConnected(), error = OT_ERROR_INVALID_STATE);
error = CoapBase::SendMessage(aMessage, mPeerAddress, aHandler, aContext);
error = CoapBase::SendMessage(aMessage, mDtls.GetPeerAddress(), aHandler, aContext);
exit:
return error;
@@ -238,6 +187,7 @@ otError CoapSecure::SendMessage(Message & aMessage,
otError CoapSecure::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aMessageInfo);
otError error;
SuccessOrExit(error = mTransmitQueue.Enqueue(aMessage));
@@ -247,57 +197,6 @@ exit:
return error;
}
void CoapSecure::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
static_cast<CoapSecure *>(aContext)->HandleUdpReceive(*static_cast<ot::Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void CoapSecure::HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
ThreadNetif &netif = GetNetif();
if (netif.GetDtls().GetState() == MeshCoP::Dtls::kStateStopped)
{
Ip6::SockAddr sockAddr;
sockAddr.mAddress = aMessageInfo.GetPeerAddr();
sockAddr.mPort = aMessageInfo.GetPeerPort();
mSocket.Connect(sockAddr);
mPeerAddress.SetPeerAddr(aMessageInfo.GetPeerAddr());
mPeerAddress.SetPeerPort(aMessageInfo.GetPeerPort());
mPeerAddress.SetInterfaceId(aMessageInfo.GetInterfaceId());
if (netif.IsUnicastAddress(aMessageInfo.GetSockAddr()))
{
mPeerAddress.SetSockAddr(aMessageInfo.GetSockAddr());
}
mPeerAddress.SetSockPort(aMessageInfo.GetSockPort());
VerifyOrExit(netif.GetDtls().Start(false, &CoapSecure::HandleDtlsConnected, &CoapSecure::HandleDtlsReceive,
CoapSecure::HandleDtlsSend, this) == OT_ERROR_NONE);
}
else
{
// Once DTLS session is started, communicate only with a peer.
VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
(mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort()));
}
#if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER
if (netif.GetDtls().GetState() == MeshCoP::Dtls::kStateConnecting)
{
netif.GetDtls().SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields));
}
#endif
netif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
exit:
return;
}
void CoapSecure::HandleDtlsConnected(void *aContext, bool aConnected)
{
return static_cast<CoapSecure *>(aContext)->HandleDtlsConnected(aConnected);
@@ -305,14 +204,6 @@ void CoapSecure::HandleDtlsConnected(void *aContext, bool aConnected)
void CoapSecure::HandleDtlsConnected(bool aConnected)
{
if (!aConnected)
{
// Disconnect from previous peer by connecting to any address
otError error = mSocket.Connect(Ip6::SockAddr());
assert(error == OT_ERROR_NONE);
}
if (mConnectedCallback != NULL)
{
mConnectedCallback(aConnected, mConnectedContext);
@@ -332,7 +223,7 @@ void CoapSecure::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
NULL);
SuccessOrExit(message->Append(aBuf, aLength));
CoapBase::Receive(*message, mPeerAddress);
CoapBase::Receive(*message, mDtls.GetPeerAddress());
exit:
@@ -342,47 +233,6 @@ exit:
}
}
otError CoapSecure::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType)
{
return static_cast<CoapSecure *>(aContext)->HandleDtlsSend(aBuf, aLength, aMessageSubType);
}
otError CoapSecure::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType)
{
otError error = OT_ERROR_NONE;
ot::Message *message = NULL;
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS);
message->SetSubType(aMessageSubType);
message->SetLinkSecurityEnabled(mLayerTwoSecurity);
SuccessOrExit(error = message->Append(aBuf, aLength));
// Set message sub type in case Joiner Finalize Response is appended to the message.
if (aMessageSubType != Message::kSubTypeNone)
{
message->SetSubType(aMessageSubType);
}
if (mTransportCallback)
{
SuccessOrExit(error = mTransportCallback(mTransportContext, *message, mPeerAddress));
}
else
{
SuccessOrExit(error = mSocket.SendTo(*message, mPeerAddress));
}
exit:
if (error != OT_ERROR_NONE && message != NULL)
{
message->Free();
}
return error;
}
void CoapSecure::HandleTransmit(Tasklet &aTasklet)
{
static_cast<CoapSecure *>(static_cast<TaskletContext &>(aTasklet).GetContext())->HandleTransmit();
@@ -401,7 +251,7 @@ void CoapSecure::HandleTransmit(void)
mTransmitTask.Post();
}
SuccessOrExit(error = GetDtls().Send(*message, message->GetLength()));
SuccessOrExit(error = mDtls.Send(*message, message->GetLength()));
exit:
if (error != OT_ERROR_NONE)
+22 -32
View File
@@ -57,16 +57,6 @@ public:
*/
typedef void (*ConnectedCallback)(bool aConnected, void *aContext);
/**
* This function pointer is called when secure CoAP server want to send encrypted message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
typedef otError (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This constructor initializes the object.
*
@@ -80,15 +70,24 @@ public:
* This method starts the secure CoAP agent.
*
* @param[in] aPort The local UDP port to bind to.
*
* @retval OT_ERROR_NONE Successfully started the CoAP agent.
* @retval OT_ERROR_ALREADY Already started.
*
*/
otError Start(uint16_t aPort);
/**
* This method starts the secure CoAP agent, but do not use socket to transmit/receive messages.
*
* @param[in] aCallback A pointer to a function for sending messages.
* If NULL, the message is sent directly to the socket.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully started the CoAP agent.
* @retval OT_ERROR_ALREADY Already started.
*
*/
otError Start(uint16_t aPort, TransportCallback aCallback = NULL, void *aContext = NULL);
otError Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext);
/**
* This method sets connected callback of this secure CoAP agent.
@@ -102,10 +101,8 @@ public:
/**
* This method stops the secure CoAP agent.
*
* @retval OT_ERROR_NONE Successfully stopped the secure CoAP agent.
*
*/
otError Stop(void);
void Stop(void);
/**
* This method initializes DTLS session with a peer.
@@ -126,7 +123,7 @@ public:
* @retval FALSE If DTLS session is not active.
*
*/
bool IsConnectionActive(void);
bool IsConnectionActive(void) { return mDtls.IsConnectionActive(); }
/**
* This method indicates whether or not the DTLS session is connected.
@@ -135,13 +132,13 @@ public:
* @retval FALSE The DTLS session is not connected.
*
*/
bool IsConnected(void);
bool IsConnected(void) { return mDtls.IsConnected(); }
/**
* This method stops the DTLS connection.
*
*/
void Disconnect(void);
void Disconnect(void) { mDtls.Close(); }
/**
* This method returns a reference to the DTLS object.
@@ -149,7 +146,7 @@ public:
* @returns A reference to the DTLS object.
*
*/
MeshCoP::Dtls &GetDtls(void);
MeshCoP::Dtls &GetDtls(void) { return mDtls; }
/**
* This method sets the PSK.
@@ -306,7 +303,10 @@ public:
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
void HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return mDtls.HandleUdpReceive(aMessage, aMessageInfo);
}
/**
* This method returns the DTLS session's peer address.
@@ -314,7 +314,7 @@ public:
* @return DTLS session's message info.
*
*/
const Ip6::MessageInfo &GetPeerMessageInfo(void) const { return mPeerAddress; }
const Ip6::MessageInfo &GetPeerAddress(void) const { return mDtls.GetPeerAddress(); }
private:
static otError Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
@@ -329,24 +329,14 @@ private:
static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength);
static otError HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType);
otError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType);
static void HandleTransmit(Tasklet &aTasklet);
void HandleTransmit(void);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
Ip6::MessageInfo mPeerAddress;
MeshCoP::Dtls mDtls;
ConnectedCallback mConnectedCallback;
void * mConnectedContext;
TransportCallback mTransportCallback;
void * mTransportContext;
MessageQueue mTransmitQueue;
TaskletContext mTransmitTask;
Ip6::UdpSocket mSocket;
bool mLayerTwoSecurity : 1;
};
} // namespace Coap
-12
View File
@@ -623,18 +623,6 @@ template <> inline Dns::Client &Instance::Get(void)
}
#endif
#if OPENTHREAD_ENABLE_DTLS
template <> inline MeshCoP::Dtls &Instance::Get(void)
{
return GetThreadNetif().GetDtls();
}
template <> inline Coap::CoapSecure &Instance::Get(void)
{
return GetThreadNetif().GetCoapSecure();
}
#endif
#if OPENTHREAD_ENABLE_DHCP6_CLIENT
template <> inline Dhcp6::Dhcp6Client &Instance::Get(void)
{
+6 -7
View File
@@ -164,7 +164,7 @@ static void SendErrorMessage(Coap::CoapSecure &aCoapSecure, ForwardContext &aFor
VerifyOrExit((message = NewMeshCoPMessage(aCoapSecure)) != NULL, error = OT_ERROR_NO_BUFS);
aForwardContext.ToHeader(*message, CoapCodeFromError(error));
SuccessOrExit(error = aCoapSecure.SendMessage(*message, aCoapSecure.GetPeerMessageInfo()));
SuccessOrExit(error = aCoapSecure.SendMessage(*message, aCoapSecure.GetPeerAddress()));
exit:
if (error != OT_ERROR_NONE)
@@ -197,7 +197,7 @@ static void SendErrorMessage(Coap::CoapSecure &aCoapSecure, const Coap::Message
message->SetMessageId(aSeparate ? 0 : aRequest.GetMessageId());
message->SetToken(aRequest.GetToken(), aRequest.GetTokenLength());
SuccessOrExit(error = aCoapSecure.SendMessage(*message, aCoapSecure.GetPeerMessageInfo()));
SuccessOrExit(error = aCoapSecure.SendMessage(*message, aCoapSecure.GetPeerAddress()));
exit:
if (error != OT_ERROR_NONE)
@@ -436,7 +436,7 @@ bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageIn
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
}
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, netif.GetCoapSecure().GetPeerMessageInfo()));
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, netif.GetCoapSecure().GetPeerAddress()));
otLogInfoMeshCoP("Sent to commissioner on %s", OT_URI_PATH_PROXY_RX);
@@ -487,7 +487,7 @@ otError BorderAgent::ForwardToCommissioner(Coap::Message &aNewMessage, const Mes
SuccessOrExit(error = aNewMessage.SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), aNewMessage);
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(aNewMessage, netif.GetCoapSecure().GetPeerMessageInfo()));
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(aNewMessage, netif.GetCoapSecure().GetPeerAddress()));
otLogInfoMeshCoP("Sent to commissioner");
@@ -698,7 +698,7 @@ void BorderAgent::HandleTimeout(void)
otError BorderAgent::Stop(void)
{
otError error;
otError error = OT_ERROR_NONE;
ThreadNetif & netif = GetNetif();
Coap::CoapSecure &coaps = netif.GetCoapSecure();
Coap::Coap & coap = netif.GetCoap();
@@ -720,8 +720,7 @@ otError BorderAgent::Stop(void)
coap.RemoveResource(mRelayReceive);
error = coaps.Stop();
assert(error == OT_ERROR_NONE);
coaps.Stop();
SetState(OT_BORDER_AGENT_STATE_STOPPED);
+2 -1
View File
@@ -62,7 +62,8 @@ public:
/**
* This method starts the Border Agent service.
*
* @retval OT_ERROR_NONE Successfully started the Border Agent service.
* @retval OT_ERROR_NONE Successfully started the Border Agent service.
* @retval OT_ERROR_ALREADY Already started.
*
*/
otError Start(void);
+7 -6
View File
@@ -107,7 +107,7 @@ otError Commissioner::Start(void)
VerifyOrExit(mState == OT_COMMISSIONER_STATE_DISABLED, error = OT_ERROR_INVALID_STATE);
SuccessOrExit(error = GetNetif().GetCoapSecure().Start(OPENTHREAD_CONFIG_JOINER_UDP_PORT, SendRelayTransmit, this));
SuccessOrExit(error = GetNetif().GetCoapSecure().Start(SendRelayTransmit, this));
mState = OT_COMMISSIONER_STATE_PETITION;
mTransmitAttempts = 0;
@@ -135,7 +135,7 @@ otError Commissioner::Stop(void)
mTimer.Stop();
GetNetif().GetDtls().Stop();
GetNetif().GetCoapSecure().Stop();
SendKeepAlive();
@@ -318,7 +318,7 @@ exit:
const char *Commissioner::GetProvisioningUrl(uint16_t &aLength) const
{
ProvisioningUrlTlv &provisioningUrl = GetNetif().GetDtls().mProvisioningUrl;
ProvisioningUrlTlv &provisioningUrl = GetNetif().GetCoapSecure().GetDtls().mProvisioningUrl;
aLength = provisioningUrl.GetLength();
@@ -327,7 +327,7 @@ const char *Commissioner::GetProvisioningUrl(uint16_t &aLength) const
otError Commissioner::SetProvisioningUrl(const char *aProvisioningUrl)
{
return GetNetif().GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl);
return GetNetif().GetCoapSecure().GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl);
}
uint16_t Commissioner::GetSessionId(void) const
@@ -898,8 +898,9 @@ void Commissioner::HandleJoinerFinalize(Coap::Message &aMessage, const Ip6::Mess
if (Tlv::GetTlv(aMessage, Tlv::kProvisioningUrl, sizeof(provisioningUrl), provisioningUrl) == OT_ERROR_NONE)
{
if (provisioningUrl.GetLength() != GetNetif().GetDtls().mProvisioningUrl.GetLength() ||
memcmp(provisioningUrl.GetProvisioningUrl(), GetNetif().GetDtls().mProvisioningUrl.GetProvisioningUrl(),
if (provisioningUrl.GetLength() != GetNetif().GetCoapSecure().GetDtls().mProvisioningUrl.GetLength() ||
memcmp(provisioningUrl.GetProvisioningUrl(),
GetNetif().GetCoapSecure().GetDtls().mProvisioningUrl.GetProvisioningUrl(),
provisioningUrl.GetLength()) != 0)
{
state = StateTlv::kReject;
+177 -21
View File
@@ -43,6 +43,7 @@
#include "common/encoding.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/new.hpp"
#include "common/owner-locator.hpp"
#include "common/timer.hpp"
#include "crypto/sha256.hpp"
@@ -53,7 +54,7 @@
namespace ot {
namespace MeshCoP {
Dtls::Dtls(Instance &aInstance)
Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
: InstanceLocator(aInstance)
, mState(kStateStopped)
, mPskLength(0)
@@ -61,6 +62,7 @@ Dtls::Dtls(Instance &aInstance)
, mTimer(aInstance, &Dtls::HandleTimer, this)
, mTimerIntermediate(0)
, mTimerSet(false)
, mLayerTwoSecurity(aLayerTwoSecurity)
, mReceiveMessage(NULL)
, mReceiveOffset(0)
, mReceiveLength(0)
@@ -68,6 +70,9 @@ Dtls::Dtls(Instance &aInstance)
, mReceiveHandler(NULL)
, mSendHandler(NULL)
, mContext(NULL)
, mSocket(aInstance.GetThreadNetif().GetIp6().GetUdp())
, mTransportCallback(NULL)
, mTransportContext(NULL)
, mMessageSubType(Message::kSubTypeNone)
, mMessageDefaultSubType(Message::kSubTypeNone)
{
@@ -149,11 +154,120 @@ void Dtls::FreeMbedtls(void)
mbedtls_ssl_free(&mSsl);
}
otError Dtls::Start(bool aClient,
ConnectedHandler aConnectedHandler,
ReceiveHandler aReceiveHandler,
SendHandler aSendHandler,
void * aContext)
otError Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
{
otError error;
SuccessOrExit(error = mSocket.Open(&Dtls::HandleUdpReceive, this));
mReceiveHandler = aReceiveHandler;
mConnectedHandler = aConnectedHandler;
mContext = aContext;
exit:
return error;
}
otError Dtls::Connect(const Ip6::SockAddr &aSockAddr)
{
memcpy(&mPeerAddress.mPeerAddr, &aSockAddr.mAddress, sizeof(mPeerAddress.mPeerAddr));
mPeerAddress.mPeerPort = aSockAddr.mPort;
if (aSockAddr.GetAddress().IsLinkLocal() || aSockAddr.GetAddress().IsMulticast())
{
mPeerAddress.mInterfaceId = aSockAddr.mScopeId;
}
else
{
mPeerAddress.mInterfaceId = 0;
}
return Setup(true);
}
void Dtls::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
static_cast<Dtls *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
ThreadNetif &netif = GetNetif();
if (mState == MeshCoP::Dtls::kStateStopped)
{
Ip6::SockAddr sockAddr;
sockAddr.mAddress = aMessageInfo.GetPeerAddr();
sockAddr.mPort = aMessageInfo.GetPeerPort();
mSocket.Connect(sockAddr);
mPeerAddress.SetPeerAddr(aMessageInfo.GetPeerAddr());
mPeerAddress.SetPeerPort(aMessageInfo.GetPeerPort());
mPeerAddress.SetInterfaceId(aMessageInfo.GetInterfaceId());
if (netif.IsUnicastAddress(aMessageInfo.GetSockAddr()))
{
mPeerAddress.SetSockAddr(aMessageInfo.GetSockAddr());
}
mPeerAddress.SetSockPort(aMessageInfo.GetSockPort());
SuccessOrExit(Setup(false));
}
else
{
// Once DTLS session is started, communicate only with a peer.
VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
(mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort()));
}
#if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER
if (mState == MeshCoP::Dtls::kStateConnecting)
{
SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields));
}
#endif
Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
exit:
return;
}
otError Dtls::Bind(uint16_t aPort)
{
otError error;
Ip6::SockAddr sockaddr;
VerifyOrExit(mTransportCallback == NULL, error = OT_ERROR_ALREADY);
sockaddr.mPort = aPort;
SuccessOrExit(error = mSocket.Bind(sockaddr));
mState = kStateStopped;
exit:
return error;
}
otError Dtls::Bind(TransportCallback aCallback, void *aContext)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(mTransportCallback == NULL, error = OT_ERROR_ALREADY);
mState = kStateStopped;
mTransportCallback = aCallback;
mTransportContext = aContext;
exit:
return error;
}
otError Dtls::Setup(bool aClient)
{
int rval;
@@ -240,12 +354,9 @@ otError Dtls::Start(bool aClient,
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
VerifyOrExit(rval == 0);
mConnectedHandler = aConnectedHandler;
mReceiveHandler = aReceiveHandler;
mSendHandler = aSendHandler;
mContext = aContext;
mReceiveMessage = NULL;
mMessageSubType = Message::kSubTypeNone;
mReceiveMessage = NULL;
mMessageSubType = Message::kSubTypeNone;
mState = kStateConnecting;
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{
@@ -331,28 +442,37 @@ void Dtls::SetSslAuthMode(bool aVerifyPeerCertificate)
void Dtls::Stop(void)
{
VerifyOrExit((mState == kStateConnecting) || (mState == kStateConnected));
mbedtls_ssl_close_notify(&mSsl);
Close();
exit:
return;
mState = kStateStopped;
mTransportCallback = NULL;
mTransportContext = NULL;
mTimerSet = false;
mSocket.Close();
mTimer.Stop();
}
void Dtls::Close(void)
{
assert((mState == kStateConnecting) || (mState == kStateConnected));
VerifyOrExit(mState == kStateConnecting || mState == kStateConnected);
mbedtls_ssl_close_notify(&mSsl);
mState = kStateCloseNotify;
mTimer.Start(kGuardTimeNewConnectionMilli);
FreeMbedtls();
new (&mPeerAddress) Ip6::MessageInfo();
mSocket.Connect(Ip6::SockAddr());
if (mConnectedHandler != NULL)
{
mConnectedHandler(mContext, false);
}
FreeMbedtls();
exit:
return;
}
otError Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
@@ -518,7 +638,7 @@ int Dtls::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
}
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
error = mSendHandler(mContext, aBuf, static_cast<uint16_t>(aLength), mMessageSubType);
error = HandleDtlsSend(aBuf, static_cast<uint16_t>(aLength), mMessageSubType);
// Restore default sub type.
mMessageSubType = mMessageDefaultSubType;
@@ -691,7 +811,7 @@ int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
void Dtls::HandleTimer(Timer &aTimer)
{
aTimer.GetOwner<Dtls>().HandleTimer();
static_cast<Dtls *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer();
}
void Dtls::HandleTimer(void)
@@ -933,6 +1053,42 @@ void Dtls::HandleMbedtlsDebug(void *ctx, int level, const char *, int, const cha
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
}
otError Dtls::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType)
{
otError error = OT_ERROR_NONE;
ot::Message *message = NULL;
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS);
message->SetSubType(aMessageSubType);
message->SetLinkSecurityEnabled(mLayerTwoSecurity);
SuccessOrExit(error = message->Append(aBuf, aLength));
// Set message sub type in case Joiner Finalize Response is appended to the message.
if (aMessageSubType != Message::kSubTypeNone)
{
message->SetSubType(aMessageSubType);
}
if (mTransportCallback)
{
SuccessOrExit(error = mTransportCallback(mTransportContext, *message, mPeerAddress));
}
else
{
SuccessOrExit(error = mSocket.SendTo(*message, mPeerAddress));
}
exit:
if (error != OT_ERROR_NONE && message != NULL)
{
message->Free();
}
return error;
}
} // namespace MeshCoP
} // namespace ot
+123 -17
View File
@@ -60,6 +60,8 @@
#include "common/timer.hpp"
#include "crypto/sha256.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "net/socket.hpp"
#include "net/udp6.hpp"
namespace ot {
@@ -91,10 +93,11 @@ public:
/**
* This constructor initializes the DTLS object.
*
* @param[in] aNetif A reference to the Thread network interface.
* @param[in] aNetif A reference to the Thread network interface.
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
*
*/
explicit Dtls(Instance &aInstance);
explicit Dtls(Instance &aInstance, bool aLayerTwoSecurity);
/**
* This function pointer is called when a connection is established or torn down.
@@ -115,6 +118,16 @@ public:
*/
typedef void (*ReceiveHandler)(void *aContext, uint8_t *aBuf, uint16_t aLength);
/**
* This function pointer is called when secure CoAP server want to send encrypted message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
typedef otError (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This function pointer is called when data is ready to transmit for the DTLS session.
*
@@ -126,6 +139,19 @@ public:
*/
typedef otError (*SendHandler)(void *aContext, const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType);
/**
* This method opens the DTLS socket.
*
* @param[in] aReceiveHandler A pointer to a function that is called to receive DTLS payload.
* @param[in] aConnectedHandler A pointer to a function that is called when connected or disconnected.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully opened the socket.
* @retval OT_ERROR_ALREADY The DTLS is already open.
*
*/
otError Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
/**
* This method starts the DTLS service.
*
@@ -133,20 +159,73 @@ public:
* Set X509 Pk and Cert for use DTLS mode ECDHE ECDSA with AES 128 CCM 8 or
* set PreShared Key for use DTLS mode PSK with AES 128 CCM 8.
*
* @param[in] aClient TRUE if operating as a client, FALSE if operating as a server.
* @param[in] aConnectedHandler A pointer to the connected handler.
* @param[in] aReceiveHandler A pointer to the receive handler.
* @param[in] aSendHandler A pointer to the send handler.
* @param[in] aContext A pointer to application-specific context.
* @param[in] aSockAddr A reference to the remote sockaddr.
*
* @retval OT_ERROR_NONE Successfully started the DTLS service.
*
*/
otError Start(bool aClient,
ConnectedHandler aConnectedHandler,
ReceiveHandler aReceiveHandler,
SendHandler aSendHandler,
void * aContext);
otError Connect(const Ip6::SockAddr &aSockAddr);
/**
* This method set up the DTLS service.
*
* For CoAP Secure API do first:
* Set X509 Pk and Cert for use DTLS mode ECDHE ECDSA with AES 128 CCM 8 or
* set PreShared Key for use DTLS mode PSK with AES 128 CCM 8.
*
* @param[in] aClient TRUE if setup for client, otherwise setup for server.
*
* @retval OT_ERROR_NONE Successfully started the DTLS service.
*
*/
otError Setup(bool aClient);
/**
* This method binds this DTLS to a UDP port.
*
* @param[in] aPort The port to bind.
*
* @retval OT_ERROR_NONE Successfully binded the DTLS service.
* @retval OT_ERROR_ALREADY Already bound.
*
*/
otError Bind(uint16_t aPort);
/**
* This method binds this DTLS with a transport callback.
*
* @param[in] aCallback A pointer to a function for sending messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully binded the DTLS service.
* @retval OT_ERROR_ALREADY Already bound.
*
*/
otError Bind(TransportCallback aCallback, void *aContext);
/**
* This method indicates whether or not the DTLS session is active.
*
* @retval TRUE If DTLS session is active.
* @retval FALSE If DTLS session is not active.
*
*/
bool IsConnectionActive(void) { return mState != kStateStopped; }
/**
* This method indicates whether or not the DTLS session is connected.
*
* @retval TRUE The DTLS session is connected.
* @retval FALSE The DTLS session is not connected.
*
*/
bool IsConnected(void) { return mState == kStateConnected; }
/**
* This method close the current session.
*
*/
void Close(void);
/**
* This method stops the DTLS service.
@@ -308,12 +387,22 @@ public:
*/
void SetDefaultMessageSubType(uint8_t aMessageSubType) { mMessageDefaultSubType = aMessageSubType; }
/**
* This method returns the DTLS session's peer address.
*
* @return DTLS session's message info.
*
*/
const Ip6::MessageInfo &GetPeerAddress(void) const { return mPeerAddress; }
/**
* The provisioning URL is placed here so that both the Commissioner and Joiner can share the same object.
*
*/
ProvisioningUrlTlv mProvisioningUrl;
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
void FreeMbedtls(void);
@@ -358,9 +447,16 @@ private:
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
otError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, uint8_t aMessageSubType);
static void HandleUdpTransmit(Tasklet &aTasklet);
void HandleUdpTransmit(void);
static int HandleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen);
void Close(void);
void Process(void);
State mState;
@@ -402,11 +498,15 @@ private:
mbedtls_ssl_cookie_ctx mCookieCtx;
#endif
TimerMilli mTimer;
uint32_t mTimerIntermediate;
bool mTimerSet;
TimerMilliContext mTimer;
uint32_t mTimerIntermediate;
bool mTimerSet : 1;
bool mLayerTwoSecurity : 1;
const Message *mReceiveMessage;
Message *mReceiveMessage;
uint16_t mReceiveOffset;
uint16_t mReceiveLength;
@@ -415,6 +515,12 @@ private:
SendHandler mSendHandler;
void * mContext;
Ip6::MessageInfo mPeerAddress;
Ip6::UdpSocket mSocket;
TransportCallback mTransportCallback;
void * mTransportContext;
uint8_t mMessageSubType;
uint8_t mMessageDefaultSubType;
};
+3 -4
View File
@@ -88,7 +88,6 @@ ThreadNetif::ThreadNetif(Instance &aInstance)
, mCommissioner(aInstance)
#endif // OPENTHREAD_ENABLE_COMMISSIONER && OPENTHREAD_FTD
#if OPENTHREAD_ENABLE_DTLS
, mDtls(aInstance)
, mCoapSecure(aInstance)
#endif
#if OPENTHREAD_ENABLE_JOINER
@@ -150,14 +149,14 @@ void ThreadNetif::Down(void)
{
VerifyOrExit(mIsUp);
#if OPENTHREAD_ENABLE_DTLS
mDtls.Stop();
#endif
#if OPENTHREAD_ENABLE_DNS_CLIENT
mDnsClient.Stop();
#endif
#if OPENTHREAD_ENABLE_SNTP_CLIENT
mSntpClient.Stop();
#endif
#if OPENTHREAD_ENABLE_DTLS
mCoapSecure.Stop();
#endif
mCoap.Stop();
mMleRouter.Disable();
-13
View File
@@ -49,10 +49,6 @@
#include "meshcop/dataset_manager.hpp"
#if OPENTHREAD_ENABLE_DTLS
#include "meshcop/dtls.hpp"
#endif // OPENTHREAD_ENABLE_DTLS
#if OPENTHREAD_ENABLE_JOINER
#include "meshcop/joiner.hpp"
#endif // OPENTHREAD_ENABLE_JOINER
@@ -341,14 +337,6 @@ public:
#endif // OPENTHREAD_ENABLE_COMMISSIONER && OPENTHREAD_FTD
#if OPENTHREAD_ENABLE_DTLS
/**
* This method returns a reference to the Dtls object.
*
* @returns A reference to the Dtls object.
*
*/
MeshCoP::Dtls &GetDtls(void) { return mDtls; }
/**
* This method returns a reference to the secure CoAP object.
*
@@ -491,7 +479,6 @@ private:
#endif // OPENTHREAD_ENABLE_COMMISSIONER
#if OPENTHREAD_ENABLE_DTLS
MeshCoP::Dtls mDtls;
Coap::CoapSecure mCoapSecure;
#endif // OPENTHREAD_ENABLE_DTLS