diff --git a/src/core/meshcop/secure_transport.cpp b/src/core/meshcop/secure_transport.cpp index 9c0602893..066e4c13b 100644 --- a/src/core/meshcop/secure_transport.cpp +++ b/src/core/meshcop/secure_transport.cpp @@ -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(aContext)->HandleMbedtlsTransmit(aBuf, aLength); + return static_cast(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(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(aContext)->HandleMbedtlsReceive(aBuf, aLength); + return static_cast(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(aContext)->HandleMbedtlsGetTimer(); + return static_cast(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(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish); + static_cast(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_ssl_get_peer_cert(&mSecureTransport.mSsl)); + SecureSession *session = mSecureTransport.mSession; + mbedtls_x509_crt *peerCert = const_cast(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); } diff --git a/src/core/meshcop/secure_transport.hpp b/src/core/meshcop/secure_transport.hpp index 5b03c56f9..a9abcc932 100644 --- a/src/core/meshcop/secure_transport.hpp +++ b/src/core/meshcop/secure_transport.hpp @@ -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 mConnectedCallback; + Callback 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; #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 mAutoCloseCallback; - Callback mConnectedCallback; - Callback mReceiveCallback; Callback 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(this)) { + SetSession(*static_cast(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(this)) { + SetSession(*static_cast(this)); SetExtension(aExtension); } };