mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 17:37:46 +00:00
[secure-transport] introduce SecureSession class (#11046)
This commit introduces the `SecureSession` class to manage session-related functionality, decoupling it from the `SecureTransport` class. `SecureSession` provides method such as `Connect()`, `Send()`, and `IsConnected()`, while `SecureTransport` focuses on transport-level operations and common configuration (e.g., setting PSK, cipher keys). The `Dtls` and `Tls` subclasses now inherit from both `SecureTransport` and `SecureSession`, effectively providing the same methods as before and implementing a single DTLS/TLS session over a socket.
This commit is contained in:
@@ -81,16 +81,12 @@ SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwo
|
||||
, mDatagramTransport(aDatagramTransport)
|
||||
, mIsOpen(false)
|
||||
, mIsServer(true)
|
||||
, mTimerSet(false)
|
||||
, mVerifyPeerCertificate(true)
|
||||
, mSessionState(kSessionDisconnected)
|
||||
, mCipherSuite(kUnspecifiedCipherSuite)
|
||||
, mMessageSubType(Message::kSubTypeNone)
|
||||
, mConnectEvent(kDisconnectedError)
|
||||
, mPskLength(0)
|
||||
, mMaxConnectionAttempts(0)
|
||||
, mRemainingConnectionAttempts(0)
|
||||
, mReceiveMessage(nullptr)
|
||||
, mSession(nullptr)
|
||||
, mSocket(aInstance, *this)
|
||||
, mTimer(aInstance, SecureTransport::HandleTimer, this)
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
@@ -98,44 +94,56 @@ SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwo
|
||||
#endif
|
||||
{
|
||||
ClearAllBytes(mPsk);
|
||||
OT_UNUSED_VARIABLE(mVerifyPeerCertificate);
|
||||
}
|
||||
|
||||
SecureSession::SecureSession(SecureTransport &aTransport)
|
||||
: mTimerSet(false)
|
||||
, mState(kStateDisconnected)
|
||||
, mMessageSubType(Message::kSubTypeNone)
|
||||
, mConnectEvent(kDisconnectedError)
|
||||
, mTransport(aTransport)
|
||||
, mReceiveMessage(nullptr)
|
||||
{
|
||||
ClearAllBytes(mSsl);
|
||||
ClearAllBytes(mConf);
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
ClearAllBytes(mCookieCtx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SecureTransport::FreeMbedtls(void)
|
||||
void SecureSession::FreeMbedtls(void)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
if (mDatagramTransport)
|
||||
if (mTransport.mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_cookie_free(&mCookieCtx);
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
if (mExtension != nullptr)
|
||||
if (mTransport.mExtension != nullptr)
|
||||
{
|
||||
mExtension->mEcdheEcdsaInfo.Free();
|
||||
mTransport.mExtension->mEcdheEcdsaInfo.Free();
|
||||
}
|
||||
#endif
|
||||
mbedtls_ssl_config_free(&mConf);
|
||||
mbedtls_ssl_free(&mSsl);
|
||||
}
|
||||
|
||||
void SecureTransport::SetSessionState(SessionState aSessionState)
|
||||
void SecureSession::SetState(State aState)
|
||||
{
|
||||
VerifyOrExit(mSessionState != aSessionState);
|
||||
VerifyOrExit(mState != aState);
|
||||
|
||||
LogInfo("State: %s -> %s", SessionStateToString(mSessionState), SessionStateToString(aSessionState));
|
||||
mSessionState = aSessionState;
|
||||
LogInfo("Session state: %s -> %s", StateToString(mState), StateToString(aState));
|
||||
mState = aState;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error SecureTransport::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
|
||||
Error SecureTransport::Open(SecureSession::ReceiveHandler aReceiveHandler,
|
||||
SecureSession::ConnectedHandler aConnectedHandler,
|
||||
void *aContext)
|
||||
{
|
||||
Error error;
|
||||
|
||||
@@ -144,13 +152,11 @@ Error SecureTransport::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aCo
|
||||
SuccessOrExit(error = mSocket.Open(Ip6::kNetifUnspecified));
|
||||
|
||||
mIsOpen = true;
|
||||
mConnectedCallback.Set(aConnectedHandler, aContext);
|
||||
mReceiveCallback.Set(aReceiveHandler, aContext);
|
||||
mSession->SetConnectedCallback(aConnectedHandler, aContext);
|
||||
mSession->SetReceiveCallback(aReceiveHandler, aContext);
|
||||
|
||||
mRemainingConnectionAttempts = mMaxConnectionAttempts;
|
||||
|
||||
SetSessionState(kSessionDisconnected);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -168,22 +174,18 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SecureTransport::Connect(const Ip6::SockAddr &aSockAddr)
|
||||
Error SecureSession::Connect(const Ip6::SockAddr &aSockAddr)
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsSessionDisconnected(), error = kErrorInvalidState);
|
||||
|
||||
if (mRemainingConnectionAttempts > 0)
|
||||
{
|
||||
mRemainingConnectionAttempts--;
|
||||
}
|
||||
VerifyOrExit(mTransport.mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsDisconnected(), error = kErrorInvalidState);
|
||||
|
||||
mTransport.DecremenetRemainingConnectionAttempts();
|
||||
mMessageInfo.SetPeerAddr(aSockAddr.GetAddress());
|
||||
mMessageInfo.SetPeerPort(aSockAddr.mPort);
|
||||
|
||||
mIsServer = false;
|
||||
mTransport.mIsServer = false;
|
||||
|
||||
error = Setup();
|
||||
|
||||
@@ -195,12 +197,22 @@ void SecureTransport::HandleReceive(Message &aMessage, const Ip6::MessageInfo &a
|
||||
{
|
||||
VerifyOrExit(mIsOpen);
|
||||
|
||||
if (IsSessionDisconnected())
|
||||
if (!mSession->IsDisconnected())
|
||||
{
|
||||
if (mRemainingConnectionAttempts > 0)
|
||||
{
|
||||
mRemainingConnectionAttempts--;
|
||||
}
|
||||
VerifyOrExit(mSession->Matches(aMessageInfo));
|
||||
}
|
||||
|
||||
mSession->HandleTransportReceive(aMessage, aMessageInfo);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void SecureSession::HandleTransportReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
if (IsDisconnected())
|
||||
{
|
||||
mTransport.DecremenetRemainingConnectionAttempts();
|
||||
|
||||
mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
|
||||
mMessageInfo.SetPeerPort(aMessageInfo.GetPeerPort());
|
||||
@@ -211,14 +223,9 @@ void SecureTransport::HandleReceive(Message &aMessage, const Ip6::MessageInfo &a
|
||||
|
||||
SuccessOrExit(Setup());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Once DTLS session is started, communicate only with a single peer.
|
||||
VerifyOrExit(mMessageInfo.HasSamePeerAddrAndPort(aMessageInfo));
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_SSL_SRV_C
|
||||
if (IsSessionConnecting())
|
||||
if (IsConnecting())
|
||||
{
|
||||
mbedtls_ssl_set_client_transport_id(&mSsl, mMessageInfo.GetPeerAddr().GetBytes(), sizeof(Ip6::Address));
|
||||
}
|
||||
@@ -237,9 +244,10 @@ Error SecureTransport::Bind(uint16_t aPort)
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsSessionDisconnected(), error = kErrorInvalidState);
|
||||
VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
|
||||
|
||||
VerifyOrExit(mSession->IsDisconnected(), error = kErrorInvalidState);
|
||||
|
||||
SuccessOrExit(error = mSocket.Bind(aPort));
|
||||
mIsServer = true;
|
||||
|
||||
@@ -252,10 +260,11 @@ Error SecureTransport::Bind(TransportCallback aCallback, void *aContext)
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsSessionDisconnected(), error = kErrorInvalidState);
|
||||
VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready);
|
||||
VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
|
||||
|
||||
VerifyOrExit(mSession->IsDisconnected(), error = kErrorInvalidState);
|
||||
|
||||
mTransportCallback.Set(aCallback, aContext);
|
||||
mIsServer = true;
|
||||
|
||||
@@ -263,31 +272,33 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SecureTransport::Setup(void)
|
||||
Error SecureSession::Setup(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
int rval = 0;
|
||||
|
||||
OT_ASSERT(mCipherSuite != kUnspecifiedCipherSuite);
|
||||
OT_ASSERT(mTransport.mCipherSuite != SecureTransport::kUnspecifiedCipherSuite);
|
||||
|
||||
VerifyOrExit(mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsSessionDisconnected(), error = kErrorBusy);
|
||||
VerifyOrExit(mTransport.mIsOpen, error = kErrorInvalidState);
|
||||
VerifyOrExit(IsDisconnected(), error = kErrorBusy);
|
||||
|
||||
SetSessionState(kSessionInitializing);
|
||||
SetState(kStateInitializing);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Setup the mbedtls_ssl_config `mConf`.
|
||||
|
||||
mbedtls_ssl_config_init(&mConf);
|
||||
|
||||
rval = mbedtls_ssl_config_defaults(
|
||||
&mConf, mIsServer ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
|
||||
mDatagramTransport ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
rval = mbedtls_ssl_config_defaults(&mConf, mTransport.mIsServer ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
|
||||
mTransport.mDatagramTransport ? MBEDTLS_SSL_TRANSPORT_DATAGRAM
|
||||
: MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
if (mVerifyPeerCertificate &&
|
||||
(mCipherSuite == kEcdheEcdsaWithAes128Ccm8 || mCipherSuite == kEcdheEcdsaWithAes128GcmSha256))
|
||||
if (mTransport.mVerifyPeerCertificate &&
|
||||
(mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128Ccm8 ||
|
||||
mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128GcmSha256))
|
||||
{
|
||||
mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
}
|
||||
@@ -295,8 +306,6 @@ Error SecureTransport::Setup(void)
|
||||
{
|
||||
mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
}
|
||||
#else
|
||||
OT_UNUSED_VARIABLE(mVerifyPeerCertificate);
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr);
|
||||
@@ -318,52 +327,52 @@ Error SecureTransport::Setup(void)
|
||||
struct EnumCheck
|
||||
{
|
||||
InitEnumValidatorCounter();
|
||||
ValidateNextEnum(kEcjpakeWithAes128Ccm8);
|
||||
ValidateNextEnum(SecureTransport::kEcjpakeWithAes128Ccm8);
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
ValidateNextEnum(kPskWithAes128Ccm8);
|
||||
ValidateNextEnum(SecureTransport::kPskWithAes128Ccm8);
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
ValidateNextEnum(kEcdheEcdsaWithAes128Ccm8);
|
||||
ValidateNextEnum(kEcdheEcdsaWithAes128GcmSha256);
|
||||
ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128Ccm8);
|
||||
ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128GcmSha256);
|
||||
#endif
|
||||
};
|
||||
|
||||
mbedtls_ssl_conf_ciphersuites(&mConf, kCipherSuites[mCipherSuite]);
|
||||
mbedtls_ssl_conf_ciphersuites(&mConf, SecureTransport::kCipherSuites[mTransport.mCipherSuite]);
|
||||
}
|
||||
|
||||
if (mCipherSuite == kEcjpakeWithAes128Ccm8)
|
||||
if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
|
||||
{
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
|
||||
mbedtls_ssl_conf_groups(&mConf, kGroups);
|
||||
mbedtls_ssl_conf_groups(&mConf, SecureTransport::kGroups);
|
||||
#else
|
||||
mbedtls_ssl_conf_curves(&mConf, kCurves);
|
||||
mbedtls_ssl_conf_curves(&mConf, SecureTransport::kCurves);
|
||||
#endif
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
|
||||
mbedtls_ssl_conf_sig_algs(&mConf, kSignatures);
|
||||
mbedtls_ssl_conf_sig_algs(&mConf, SecureTransport::kSignatures);
|
||||
#else
|
||||
mbedtls_ssl_conf_sig_hashes(&mConf, kHashes);
|
||||
mbedtls_ssl_conf_sig_hashes(&mConf, SecureTransport::kHashes);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
|
||||
mbedtls_ssl_conf_export_keys_cb(&mConf, HandleMbedtlsExportKeys, this);
|
||||
mbedtls_ssl_conf_export_keys_cb(&mConf, SecureTransport::HandleMbedtlsExportKeys, &mTransport);
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000);
|
||||
mbedtls_ssl_conf_dbg(&mConf, HandleMbedtlsDebug, this);
|
||||
mbedtls_ssl_conf_dbg(&mConf, SecureTransport::HandleMbedtlsDebug, &mTransport);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Setup the `Extension` components.
|
||||
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
if (mExtension != nullptr)
|
||||
if (mTransport.mExtension != nullptr)
|
||||
{
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
mExtension->mEcdheEcdsaInfo.Init();
|
||||
mTransport.mExtension->mEcdheEcdsaInfo.Init();
|
||||
#endif
|
||||
rval = mExtension->SetApplicationSecureKeys();
|
||||
rval = mTransport.mExtension->SetApplicationSecureKeys(mConf);
|
||||
VerifyOrExit(rval == 0);
|
||||
}
|
||||
#endif
|
||||
@@ -372,11 +381,11 @@ Error SecureTransport::Setup(void)
|
||||
// Setup the mbedtls_ssl_cookie_ctx `mCookieCtx`.
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
if (mDatagramTransport)
|
||||
if (mTransport.mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_cookie_init(&mCookieCtx);
|
||||
|
||||
if (mIsServer)
|
||||
if (mTransport.mIsServer)
|
||||
{
|
||||
rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
|
||||
VerifyOrExit(rval == 0);
|
||||
@@ -396,41 +405,41 @@ Error SecureTransport::Setup(void)
|
||||
|
||||
mbedtls_ssl_set_bio(&mSsl, this, HandleMbedtlsTransmit, HandleMbedtlsReceive, /* RecvTimeoutFn */ nullptr);
|
||||
|
||||
if (mDatagramTransport)
|
||||
if (mTransport.mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_set_timer_cb(&mSsl, this, HandleMbedtlsSetTimer, HandleMbedtlsGetTimer);
|
||||
}
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
mbedtls_ssl_set_export_keys_cb(&mSsl, HandleMbedtlsExportKeys, this);
|
||||
mbedtls_ssl_set_export_keys_cb(&mSsl, SecureTransport::HandleMbedtlsExportKeys, &mTransport);
|
||||
#endif
|
||||
|
||||
if (mCipherSuite == kEcjpakeWithAes128Ccm8)
|
||||
if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
|
||||
{
|
||||
rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
|
||||
rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength);
|
||||
VerifyOrExit(rval == 0);
|
||||
}
|
||||
|
||||
mReceiveMessage = nullptr;
|
||||
mMessageSubType = Message::kSubTypeNone;
|
||||
|
||||
SetSessionState(kSessionConnecting);
|
||||
SetState(kStateConnecting);
|
||||
|
||||
Process();
|
||||
|
||||
exit:
|
||||
if (mIsOpen && IsSessionInitializing())
|
||||
if (IsInitializing())
|
||||
{
|
||||
error = Crypto::MbedTls::MapError(rval);
|
||||
|
||||
if ((mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0))
|
||||
if (mTransport.HasNoRemainingConnectionAttempts())
|
||||
{
|
||||
Close();
|
||||
mAutoCloseCallback.InvokeIfSet();
|
||||
mTransport.Close();
|
||||
mTransport.mAutoCloseCallback.InvokeIfSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSessionState(kSessionDisconnected);
|
||||
SetState(kStateDisconnected);
|
||||
FreeMbedtls();
|
||||
}
|
||||
}
|
||||
@@ -442,11 +451,10 @@ void SecureTransport::Close(void)
|
||||
{
|
||||
VerifyOrExit(mIsOpen);
|
||||
|
||||
Disconnect(kDisconnectedLocalClosed);
|
||||
SetSessionState(kSessionDisconnected);
|
||||
mSession->Disconnect(SecureSession::kDisconnectedLocalClosed);
|
||||
mSession->SetState(SecureSession::kStateDisconnected);
|
||||
|
||||
mIsOpen = false;
|
||||
mTimerSet = false;
|
||||
mIsOpen = false;
|
||||
mTransportCallback.Clear();
|
||||
IgnoreError(mSocket.Close());
|
||||
mTimer.Stop();
|
||||
@@ -455,15 +463,18 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void SecureTransport::Disconnect(ConnectEvent aEvent)
|
||||
void SecureSession::Disconnect(ConnectEvent aEvent)
|
||||
{
|
||||
VerifyOrExit(mIsOpen);
|
||||
VerifyOrExit(IsSessionConnectingOrConnected());
|
||||
VerifyOrExit(mTransport.mIsOpen);
|
||||
VerifyOrExit(IsConnectingOrConnected());
|
||||
|
||||
mbedtls_ssl_close_notify(&mSsl);
|
||||
SetSessionState(kSessionDisconnecting);
|
||||
SetState(kStateDisconnecting);
|
||||
mConnectEvent = aEvent;
|
||||
mTimer.Start(kGuardTimeNewConnectionMilli);
|
||||
|
||||
mTimerSet = false;
|
||||
mTimerFinish = TimerMilli::GetNow() + kGuardTimeNewConnectionMilli;
|
||||
mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
|
||||
|
||||
mMessageInfo.Clear();
|
||||
|
||||
@@ -473,6 +484,19 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void SecureTransport::DecremenetRemainingConnectionAttempts(void)
|
||||
{
|
||||
if (mRemainingConnectionAttempts > 0)
|
||||
{
|
||||
mRemainingConnectionAttempts--;
|
||||
}
|
||||
}
|
||||
|
||||
bool SecureTransport::HasNoRemainingConnectionAttempts(void) const
|
||||
{
|
||||
return (mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0);
|
||||
}
|
||||
|
||||
Error SecureTransport::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -487,7 +511,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SecureTransport::Send(Message &aMessage)
|
||||
Error SecureSession::Send(Message &aMessage)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t length = aMessage.GetLength();
|
||||
@@ -506,7 +530,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool SecureTransport::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext)
|
||||
bool SecureSession::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext)
|
||||
{
|
||||
return
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
@@ -516,35 +540,46 @@ bool SecureTransport::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext)
|
||||
#endif
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
|
||||
int SecureSession::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
|
||||
return static_cast<SecureSession *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
|
||||
int SecureSession::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
Message::SubType msgSubType = mMessageSubType;
|
||||
|
||||
mMessageSubType = Message::kSubTypeNone;
|
||||
|
||||
return mTransport.Transmit(aBuf, aLength, mMessageInfo, msgSubType);
|
||||
}
|
||||
|
||||
int SecureTransport::Transmit(const unsigned char *aBuf,
|
||||
size_t aLength,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
Message::SubType aMessageSubType)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Message *message = mSocket.NewMessage();
|
||||
int rval;
|
||||
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
message->SetSubType(mMessageSubType);
|
||||
message->SetSubType(aMessageSubType);
|
||||
message->SetLinkSecurityEnabled(mLayerTwoSecurity);
|
||||
|
||||
SuccessOrExit(error = message->AppendBytes(aBuf, static_cast<uint16_t>(aLength)));
|
||||
|
||||
if (mTransportCallback.IsSet())
|
||||
{
|
||||
error = mTransportCallback.Invoke(*message, mMessageInfo);
|
||||
error = mTransportCallback.Invoke(*message, aMessageInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = mSocket.SendTo(*message, mMessageInfo);
|
||||
error = mSocket.SendTo(*message, aMessageInfo);
|
||||
}
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
mMessageSubType = Message::kSubTypeNone;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
@@ -565,12 +600,12 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
|
||||
int SecureSession::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
|
||||
return static_cast<SecureSession *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
|
||||
int SecureSession::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
int rval = MBEDTLS_ERR_SSL_WANT_READ;
|
||||
uint16_t readLength;
|
||||
@@ -587,12 +622,12 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsGetTimer(void *aContext)
|
||||
int SecureSession::HandleMbedtlsGetTimer(void *aContext)
|
||||
{
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsGetTimer();
|
||||
return static_cast<SecureSession *>(aContext)->HandleMbedtlsGetTimer();
|
||||
}
|
||||
|
||||
int SecureTransport::HandleMbedtlsGetTimer(void)
|
||||
int SecureSession::HandleMbedtlsGetTimer(void)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
@@ -623,17 +658,16 @@ int SecureTransport::HandleMbedtlsGetTimer(void)
|
||||
return rval;
|
||||
}
|
||||
|
||||
void SecureTransport::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
|
||||
void SecureSession::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
|
||||
{
|
||||
static_cast<SecureTransport *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
|
||||
static_cast<SecureSession *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
|
||||
}
|
||||
|
||||
void SecureTransport::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
|
||||
void SecureSession::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
|
||||
{
|
||||
if (aFinish == 0)
|
||||
{
|
||||
mTimerSet = false;
|
||||
mTimer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -643,7 +677,7 @@ void SecureTransport::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFi
|
||||
mTimerIntermediate = now + aIntermediate;
|
||||
mTimerFinish = now + aFinish;
|
||||
|
||||
mTimer.FireAt(mTimerFinish);
|
||||
mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,26 +772,47 @@ void SecureTransport::HandleTimer(Timer &aTimer)
|
||||
|
||||
void SecureTransport::HandleTimer(void)
|
||||
{
|
||||
VerifyOrExit(mIsOpen);
|
||||
|
||||
if (IsSessionConnectingOrConnected())
|
||||
if (mIsOpen)
|
||||
{
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
|
||||
mSession->HandleTimer(now);
|
||||
}
|
||||
}
|
||||
|
||||
void SecureSession::HandleTimer(TimeMilli aNow)
|
||||
{
|
||||
if (IsConnectingOrConnected())
|
||||
{
|
||||
VerifyOrExit(mTimerSet);
|
||||
|
||||
if (aNow < mTimerFinish)
|
||||
{
|
||||
mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
Process();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (IsSessionDisconnecting())
|
||||
if (IsDisconnecting())
|
||||
{
|
||||
if ((mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0))
|
||||
if (aNow < mTimerFinish)
|
||||
{
|
||||
Close();
|
||||
mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (mTransport.HasNoRemainingConnectionAttempts())
|
||||
{
|
||||
mTransport.Close();
|
||||
mConnectEvent = kDisconnectedMaxAttempts;
|
||||
mAutoCloseCallback.InvokeIfSet();
|
||||
mTransport.mAutoCloseCallback.InvokeIfSet();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSessionState(kSessionDisconnected);
|
||||
mTimer.Stop();
|
||||
SetState(kStateDisconnected);
|
||||
}
|
||||
|
||||
mConnectedCallback.InvokeIfSet(mConnectEvent);
|
||||
@@ -767,22 +822,22 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void SecureTransport::Process(void)
|
||||
void SecureSession::Process(void)
|
||||
{
|
||||
uint8_t buf[kMaxContentLen];
|
||||
int rval;
|
||||
ConnectEvent disconnectEvent;
|
||||
bool shouldReset;
|
||||
|
||||
while (IsSessionConnectingOrConnected())
|
||||
while (IsConnectingOrConnected())
|
||||
{
|
||||
if (IsSessionConnecting())
|
||||
if (IsConnecting())
|
||||
{
|
||||
rval = mbedtls_ssl_handshake(&mSsl);
|
||||
|
||||
if (IsMbedtlsHandshakeOver(&mSsl))
|
||||
{
|
||||
SetSessionState(kSessionConnected);
|
||||
SetState(kStateConnected);
|
||||
mConnectEvent = kConnected;
|
||||
mConnectedCallback.InvokeIfSet(mConnectEvent);
|
||||
}
|
||||
@@ -851,9 +906,9 @@ void SecureTransport::Process(void)
|
||||
{
|
||||
mbedtls_ssl_session_reset(&mSsl);
|
||||
|
||||
if (mCipherSuite == kEcjpakeWithAes128Ccm8)
|
||||
if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
|
||||
{
|
||||
mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
|
||||
mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,27 +954,27 @@ void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLin
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
|
||||
const char *SecureTransport::SessionStateToString(SessionState aState)
|
||||
const char *SecureSession::StateToString(State aState)
|
||||
{
|
||||
static const char *const kSessionStrings[] = {
|
||||
"Disconnected", // (0) kSessionDisconnected
|
||||
"Initializing", // (1) kSessionInitializing
|
||||
"Connecting", // (2) kSessionConnecting
|
||||
"Connected", // (3) kSessionConnected
|
||||
"Disconnecting", // (4) kSessionDisconnecting
|
||||
static const char *const kStateStrings[] = {
|
||||
"Disconnected", // (0) kStateDisconnected
|
||||
"Initializing", // (1) kStateInitializing
|
||||
"Connecting", // (2) kStateConnecting
|
||||
"Connected", // (3) kStateConnected
|
||||
"Disconnecting", // (4) kStateDisconnecting
|
||||
};
|
||||
|
||||
struct EnumCheck
|
||||
{
|
||||
InitEnumValidatorCounter();
|
||||
ValidateNextEnum(kSessionDisconnected);
|
||||
ValidateNextEnum(kSessionInitializing);
|
||||
ValidateNextEnum(kSessionConnecting);
|
||||
ValidateNextEnum(kSessionConnected);
|
||||
ValidateNextEnum(kSessionDisconnecting);
|
||||
ValidateNextEnum(kStateDisconnected);
|
||||
ValidateNextEnum(kStateInitializing);
|
||||
ValidateNextEnum(kStateConnecting);
|
||||
ValidateNextEnum(kStateConnected);
|
||||
ValidateNextEnum(kStateDisconnecting);
|
||||
};
|
||||
|
||||
return kSessionStrings[aState];
|
||||
return kStateStrings[aState];
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -929,7 +984,7 @@ const char *SecureTransport::SessionStateToString(SessionState aState)
|
||||
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
|
||||
int SecureTransport::Extension::SetApplicationSecureKeys(void)
|
||||
int SecureTransport::Extension::SetApplicationSecureKeys(mbedtls_ssl_config &aConfig)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
@@ -942,14 +997,14 @@ int SecureTransport::Extension::SetApplicationSecureKeys(void)
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
case kEcdheEcdsaWithAes128Ccm8:
|
||||
case kEcdheEcdsaWithAes128GcmSha256:
|
||||
rval = mEcdheEcdsaInfo.SetSecureKeys(mSecureTransport.mConf);
|
||||
rval = mEcdheEcdsaInfo.SetSecureKeys(aConfig);
|
||||
VerifyOrExit(rval == 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
case kPskWithAes128Ccm8:
|
||||
rval = mPskInfo.SetSecureKeys(mSecureTransport.mConf);
|
||||
rval = mPskInfo.SetSecureKeys(aConfig);
|
||||
VerifyOrExit(rval == 0);
|
||||
break;
|
||||
#endif
|
||||
@@ -1079,27 +1134,25 @@ Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerC
|
||||
size_t *aCertLength,
|
||||
size_t aCertBufferSize)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
SecureSession *session = mSecureTransport.mSession;
|
||||
|
||||
VerifyOrExit(mSecureTransport.IsSessionConnected(), error = kErrorInvalidState);
|
||||
VerifyOrExit(session->IsConnected(), error = kErrorInvalidState);
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
|
||||
VerifyOrExit(
|
||||
mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
|
||||
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
|
||||
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == 0,
|
||||
error = kErrorNoBufs);
|
||||
#else
|
||||
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
|
||||
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)
|
||||
->MBEDTLS_PRIVATE(peer_cert)
|
||||
->MBEDTLS_PRIVATE(raw)
|
||||
.MBEDTLS_PRIVATE(p),
|
||||
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)
|
||||
->MBEDTLS_PRIVATE(peer_cert)
|
||||
->MBEDTLS_PRIVATE(raw)
|
||||
.MBEDTLS_PRIVATE(len)) == 0,
|
||||
session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
|
||||
session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) ==
|
||||
0,
|
||||
error = kErrorNoBufs);
|
||||
#else
|
||||
VerifyOrExit(
|
||||
mbedtls_base64_encode(
|
||||
aPeerCert, aCertBufferSize, aCertLength,
|
||||
session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
|
||||
session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(
|
||||
len)) == 0,
|
||||
error = kErrorNoBufs);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
@@ -1118,7 +1171,8 @@ Error SecureTransport::Extension::GetPeerSubjectAttributeByOid(const char *aOid,
|
||||
const mbedtls_asn1_named_data *data;
|
||||
size_t length;
|
||||
size_t attributeBufferSize;
|
||||
mbedtls_x509_crt *peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl));
|
||||
SecureSession *session = mSecureTransport.mSession;
|
||||
mbedtls_x509_crt *peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&session->mSsl));
|
||||
|
||||
VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
|
||||
attributeBufferSize = *aAttributeLength;
|
||||
@@ -1149,7 +1203,7 @@ Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl);
|
||||
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.mSession->mSsl);
|
||||
|
||||
return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
#include "common/locator.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "common/timer.hpp"
|
||||
#include "crypto/sha256.hpp"
|
||||
@@ -88,11 +89,23 @@ namespace ot {
|
||||
|
||||
namespace MeshCoP {
|
||||
|
||||
class SecureTransport;
|
||||
class Dtls;
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
class Tls;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents a secure transport, used as base class for `Dtls` and `Tls`.
|
||||
* Represents a secure session.
|
||||
*/
|
||||
class SecureTransport : public InstanceLocator
|
||||
class SecureSession : private NonCopyable
|
||||
{
|
||||
friend class SecureTransport;
|
||||
friend class Dtls;
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
friend class Tls;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef otCoapSecureConnectEvent ConnectEvent; ///< A connect event.
|
||||
|
||||
@@ -102,10 +115,9 @@ public:
|
||||
static constexpr ConnectEvent kDisconnectedMaxAttempts = OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS;
|
||||
static constexpr ConnectEvent kDisconnectedError = OT_COAP_SECURE_DISCONNECTED_ERROR;
|
||||
|
||||
static constexpr uint8_t kPskMaxLength = 32; ///< Maximum PSK length.
|
||||
|
||||
/**
|
||||
* Function pointer which is called reporting a connection event (when connection established or disconnected)
|
||||
* Function pointer which is called reporting a session connection event (when connection established or
|
||||
* disconnected).
|
||||
*/
|
||||
typedef otHandleCoapSecureClientConnect ConnectedHandler;
|
||||
|
||||
@@ -119,7 +131,158 @@ public:
|
||||
typedef void (*ReceiveHandler)(void *aContext, uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Pointer is called when secure CoAP server want to send encrypted message.
|
||||
* Sets the connection event callback.
|
||||
*
|
||||
* @param[in] aConnectedHandler A pointer to a function that is called when connected or disconnected.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
void SetConnectedCallback(ConnectedHandler aConnectedHandler, void *aContext)
|
||||
{
|
||||
mConnectedCallback.Set(aConnectedHandler, aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the receive callback.
|
||||
*
|
||||
* @param[in] aReceiveHandler A pointer to a function that is called to receive payload.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*/
|
||||
void SetReceiveCallback(ReceiveHandler aReceiveHandler, void *aContext)
|
||||
{
|
||||
mReceiveCallback.Set(aReceiveHandler, aContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes a secure session (as client).
|
||||
*
|
||||
* @param[in] aSockAddr The server address to connect to.
|
||||
*
|
||||
* @retval kErrorNone Successfully started session establishment
|
||||
* @retval kErrorInvalidState Transport is not ready.
|
||||
*/
|
||||
Error Connect(const Ip6::SockAddr &aSockAddr);
|
||||
|
||||
/**
|
||||
* Disconnects the session.
|
||||
*/
|
||||
void Disconnect(void) { Disconnect(kDisconnectedLocalClosed); }
|
||||
|
||||
/**
|
||||
* Sends message to the secure session.
|
||||
*
|
||||
* When successful (returning `kErrorNone`), this method takes over the ownership of @p aMessage and will free
|
||||
* it after transmission. Otherwise, the caller keeps the ownership of @p aMessage.
|
||||
*
|
||||
* @param[in] aMessage A message to send.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent the message.
|
||||
* @retval kErrorNoBufs @p aMessage is too long.
|
||||
*/
|
||||
Error Send(Message &aMessage);
|
||||
|
||||
/**
|
||||
* Returns the session's peer address.
|
||||
*
|
||||
* @return The session's message info.
|
||||
*/
|
||||
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the session is active (connected, connecting, or disconnecting).
|
||||
*
|
||||
* @retval TRUE If session is active.
|
||||
* @retval FALSE If session is not active.
|
||||
*/
|
||||
bool IsConnectionActive(void) const { return (mState != kStateDisconnected); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the session is connected.
|
||||
*
|
||||
* @retval TRUE The session is connected.
|
||||
* @retval FALSE The session is not connected.
|
||||
*/
|
||||
bool IsConnected(void) const { return (mState == kStateConnected); }
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
|
||||
static constexpr uint16_t kMaxContentLen = OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN;
|
||||
|
||||
#if !OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
static constexpr uint16_t kApplicationDataMaxLength = 1152;
|
||||
#else
|
||||
static constexpr uint16_t kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
|
||||
#endif
|
||||
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisconnected,
|
||||
kStateInitializing,
|
||||
kStateConnecting,
|
||||
kStateConnected,
|
||||
kStateDisconnecting,
|
||||
};
|
||||
|
||||
explicit SecureSession(SecureTransport &aTransport);
|
||||
|
||||
bool IsDisconnected(void) const { return mState == kStateDisconnected; }
|
||||
bool IsInitializing(void) const { return mState == kStateInitializing; }
|
||||
bool IsConnecting(void) const { return mState == kStateConnecting; }
|
||||
bool IsDisconnecting(void) const { return mState == kStateDisconnecting; }
|
||||
bool IsConnectingOrConnected(void) const { return mState == kStateConnecting || mState == kStateConnected; }
|
||||
void SetState(State aState);
|
||||
bool Matches(const Ip6::MessageInfo &aInfo) { return mMessageInfo.HasSamePeerAddrAndPort(aInfo); }
|
||||
void HandleTransportReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
Error Setup(void);
|
||||
void Disconnect(ConnectEvent aEvent);
|
||||
void HandleTimer(TimeMilli aNow);
|
||||
void Process(void);
|
||||
void FreeMbedtls(void);
|
||||
|
||||
static int HandleMbedtlsGetTimer(void *aContext);
|
||||
int HandleMbedtlsGetTimer(void);
|
||||
static void HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish);
|
||||
void HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish);
|
||||
static int HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength);
|
||||
int HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength);
|
||||
static int HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength);
|
||||
int HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength);
|
||||
|
||||
static bool IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext);
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
static const char *StateToString(State aState);
|
||||
#endif
|
||||
|
||||
bool mTimerSet : 1;
|
||||
State mState;
|
||||
Message::SubType mMessageSubType;
|
||||
ConnectEvent mConnectEvent;
|
||||
TimeMilli mTimerIntermediate;
|
||||
TimeMilli mTimerFinish;
|
||||
SecureTransport &mTransport;
|
||||
Message *mReceiveMessage;
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
Callback<ConnectedHandler> mConnectedCallback;
|
||||
Callback<ReceiveHandler> mReceiveCallback;
|
||||
mbedtls_ssl_config mConf;
|
||||
mbedtls_ssl_context mSsl;
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
mbedtls_ssl_cookie_ctx mCookieCtx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a secure transport, used as base class for `Dtls` and `Tls`.
|
||||
*/
|
||||
class SecureTransport : public InstanceLocator
|
||||
{
|
||||
friend class SecureSession;
|
||||
|
||||
public:
|
||||
static constexpr uint8_t kPskMaxLength = 32; ///< Maximum PSK length.
|
||||
|
||||
/**
|
||||
* Pointer is called to send encrypted message.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aMessage A reference to the message to send.
|
||||
@@ -150,6 +313,7 @@ public:
|
||||
class Extension
|
||||
{
|
||||
friend SecureTransport;
|
||||
friend SecureSession;
|
||||
|
||||
public:
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
@@ -347,7 +511,7 @@ public:
|
||||
};
|
||||
#endif
|
||||
|
||||
int SetApplicationSecureKeys(void);
|
||||
int SetApplicationSecureKeys(mbedtls_ssl_config &aConfig);
|
||||
Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
@@ -373,7 +537,9 @@ public:
|
||||
* @retval kErrorNone Successfully opened the socket.
|
||||
* @retval kErrorAlready The connection is already open.
|
||||
*/
|
||||
Error Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
|
||||
Error Open(SecureSession::ReceiveHandler aReceiveHandler,
|
||||
SecureSession::ConnectedHandler aConnectedHandler,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Sets the maximum number of allowed connection requests before socket is automatically closed.
|
||||
@@ -422,36 +588,6 @@ public:
|
||||
*/
|
||||
Error Bind(TransportCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Establishes a secure session.
|
||||
*
|
||||
* 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] aSockAddr A reference to the remote sockaddr.
|
||||
*
|
||||
* @retval kErrorNone Successfully started handshake.
|
||||
* @retval kErrorInvalidState The socket is not open.
|
||||
*/
|
||||
Error Connect(const Ip6::SockAddr &aSockAddr);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the session is active.
|
||||
*
|
||||
* @retval TRUE If session is active.
|
||||
* @retval FALSE If session is not active.
|
||||
*/
|
||||
bool IsConnectionActive(void) const { return mSessionState >= kSessionConnecting; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the session is connected.
|
||||
*
|
||||
* @retval TRUE The session is connected.
|
||||
* @retval FALSE The session is not connected.
|
||||
*/
|
||||
bool IsConnected(void) const { return mSessionState == kSessionConnected; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the secure transpose socket is closed.
|
||||
*
|
||||
@@ -460,11 +596,6 @@ public:
|
||||
*/
|
||||
bool IsClosed(void) const { return !mIsOpen; }
|
||||
|
||||
/**
|
||||
* Disconnects the session.
|
||||
*/
|
||||
void Disconnect(void) { Disconnect(kDisconnectedLocalClosed); }
|
||||
|
||||
/**
|
||||
* Closes the socket.
|
||||
*/
|
||||
@@ -480,26 +611,6 @@ public:
|
||||
*/
|
||||
Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
|
||||
|
||||
/**
|
||||
* Sends message to the secure session.
|
||||
*
|
||||
* When successful (returning `kErrorNone`), this method takes over the ownership of @p aMessage and will free it
|
||||
* after transmission. Otherwise, the caller keeps the ownership of @p aMessage.
|
||||
*
|
||||
* @param[in] aMessage A message to send.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent the message.
|
||||
* @retval kErrorNoBufs @p aMessage is too long.
|
||||
*/
|
||||
Error Send(Message &aMessage);
|
||||
|
||||
/**
|
||||
* Returns the session's peer address.
|
||||
*
|
||||
* @return session's message info.
|
||||
*/
|
||||
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
|
||||
|
||||
/**
|
||||
* Checks and handles a received message provided to the SecureTransport object. If checks based on
|
||||
* the message info and current connection state pass, the message is processed.
|
||||
@@ -512,29 +623,15 @@ public:
|
||||
protected:
|
||||
SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport);
|
||||
|
||||
void SetSession(SecureSession &aSesssion) { mSession = &aSesssion; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
void SetExtension(Extension &aExtension) { mExtension = &aExtension; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
static constexpr uint16_t kMaxContentLen = OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN;
|
||||
static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
|
||||
static constexpr size_t kSecureTransportKeyBlockSize = 40;
|
||||
static constexpr size_t kSecureTransportRandomBufferSize = 32;
|
||||
#if !OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
static constexpr uint16_t kApplicationDataMaxLength = 1152;
|
||||
#else
|
||||
static constexpr uint16_t kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
|
||||
#endif
|
||||
|
||||
enum SessionState : uint8_t
|
||||
{
|
||||
kSessionDisconnected,
|
||||
kSessionInitializing,
|
||||
kSessionConnecting,
|
||||
kSessionConnected,
|
||||
kSessionDisconnecting,
|
||||
};
|
||||
static constexpr size_t kSecureTransportKeyBlockSize = 40;
|
||||
static constexpr size_t kSecureTransportRandomBufferSize = 32;
|
||||
|
||||
enum CipherSuite : uint8_t
|
||||
{
|
||||
@@ -549,37 +646,16 @@ private:
|
||||
kUnspecifiedCipherSuite,
|
||||
};
|
||||
|
||||
bool IsSessionDisconnected(void) const { return mSessionState == kSessionDisconnected; }
|
||||
bool IsSessionInitializing(void) const { return mSessionState == kSessionInitializing; }
|
||||
bool IsSessionConnecting(void) const { return mSessionState == kSessionConnecting; }
|
||||
bool IsSessionConnected(void) const { return mSessionState == kSessionConnected; }
|
||||
bool IsSessionDisconnecting(void) const { return mSessionState == kSessionDisconnecting; }
|
||||
bool IsSessionConnectingOrConnected(void) const
|
||||
{
|
||||
return mSessionState == kSessionConnecting || mSessionState == kSessionConnected;
|
||||
}
|
||||
void SetSessionState(SessionState aSessionState);
|
||||
|
||||
void FreeMbedtls(void);
|
||||
Error Setup(void);
|
||||
|
||||
static bool IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext);
|
||||
void DecremenetRemainingConnectionAttempts(void);
|
||||
bool HasNoRemainingConnectionAttempts(void) const;
|
||||
int Transmit(const unsigned char *aBuf,
|
||||
size_t aLength,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
Message::SubType aMessageSubType);
|
||||
|
||||
static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
|
||||
void HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr);
|
||||
|
||||
static int HandleMbedtlsGetTimer(void *aContext);
|
||||
int HandleMbedtlsGetTimer(void);
|
||||
|
||||
static void HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish);
|
||||
void HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish);
|
||||
|
||||
static int HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength);
|
||||
int HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength);
|
||||
|
||||
static int HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength);
|
||||
int HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength);
|
||||
|
||||
#ifdef MBEDTLS_SSL_EXPORT_KEYS
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
|
||||
@@ -618,13 +694,6 @@ private:
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void HandleTimer(void);
|
||||
|
||||
void Process(void);
|
||||
void Disconnect(ConnectEvent aEvent);
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
static const char *SessionStateToString(SessionState aState);
|
||||
#endif
|
||||
|
||||
using TransportSocket = Ip6::Udp::SocketIn<SecureTransport, &SecureTransport::HandleReceive>;
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
|
||||
@@ -647,31 +716,17 @@ private:
|
||||
bool mDatagramTransport : 1;
|
||||
bool mIsOpen : 1;
|
||||
bool mIsServer : 1;
|
||||
bool mTimerSet : 1;
|
||||
bool mVerifyPeerCertificate : 1;
|
||||
SessionState mSessionState;
|
||||
CipherSuite mCipherSuite;
|
||||
Message::SubType mMessageSubType;
|
||||
ConnectEvent mConnectEvent;
|
||||
uint8_t mPskLength;
|
||||
uint16_t mMaxConnectionAttempts;
|
||||
uint16_t mRemainingConnectionAttempts;
|
||||
Message *mReceiveMessage;
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
SecureSession *mSession;
|
||||
TransportSocket mSocket;
|
||||
uint8_t mPsk[kPskMaxLength];
|
||||
TimeMilli mTimerIntermediate;
|
||||
TimeMilli mTimerFinish;
|
||||
TimerMilliContext mTimer;
|
||||
Callback<AutoCloseCallback> mAutoCloseCallback;
|
||||
Callback<ConnectedHandler> mConnectedCallback;
|
||||
Callback<ReceiveHandler> mReceiveCallback;
|
||||
Callback<TransportCallback> mTransportCallback;
|
||||
mbedtls_ssl_context mSsl;
|
||||
mbedtls_ssl_config mConf;
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
mbedtls_ssl_cookie_ctx mCookieCtx;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
Extension *mExtension;
|
||||
#endif
|
||||
@@ -680,7 +735,7 @@ private:
|
||||
/**
|
||||
* Represents a DTLS instance.
|
||||
*/
|
||||
class Dtls : public SecureTransport
|
||||
class Dtls : public SecureTransport, public SecureSession
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -691,7 +746,9 @@ public:
|
||||
*/
|
||||
Dtls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity)
|
||||
: SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ true)
|
||||
, SecureSession(*static_cast<SecureTransport *>(this))
|
||||
{
|
||||
SetSession(*static_cast<SecureSession *>(this));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -724,7 +781,7 @@ public:
|
||||
/**
|
||||
* Represents a TLS instance.
|
||||
*/
|
||||
class Tls : public SecureTransport
|
||||
class Tls : public SecureTransport, public SecureSession
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -736,7 +793,9 @@ public:
|
||||
*/
|
||||
Tls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension)
|
||||
: SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ false)
|
||||
, SecureSession(*static_cast<SecureTransport *>(this))
|
||||
{
|
||||
SetSession(*static_cast<SecureSession *>(this));
|
||||
SetExtension(aExtension);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user