diff --git a/src/core/api/ble_secure_api.cpp b/src/core/api/ble_secure_api.cpp index ec03f9a15..622b488f6 100644 --- a/src/core/api/ble_secure_api.cpp +++ b/src/core/api/ble_secure_api.cpp @@ -85,9 +85,15 @@ void otBleSecureSetPsk(otInstance *aInstance, #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength) { - return AsCoreType(aInstance).Get().GetPeerCertificateBase64(aPeerCert, aCertLength); + Error error; + + VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs); + error = AsCoreType(aInstance).Get().GetPeerCertificateBase64(aPeerCert, aCertLength, *aCertLength); + +exit: + return error; } -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#endif #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance, diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp index 9652eb801..a7e490ba9 100644 --- a/src/core/coap/coap_secure.cpp +++ b/src/core/coap/coap_secure.cpp @@ -42,9 +42,9 @@ namespace Coap { RegisterLogModule("CoapSecure"); -CoapSecureBase::CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) +CoapSecureBase::CoapSecureBase(Instance &aInstance, MeshCoP::Dtls &aDtls) : CoapBase(aInstance, Send) - , mDtls(aInstance, aLayerTwoSecurity) + , mDtls(aDtls) , mTransmitTask(aInstance, HandleTransmit, this) { } @@ -62,7 +62,7 @@ exit: return error; } -Error CoapSecureBase::Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext) +Error CoapSecureBase::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext) { Error error; @@ -106,7 +106,7 @@ Error CoapSecureBase::Connect(const Ip6::SockAddr &aSockAddr, ConnectEventCallba void CoapSecureBase::SetPsk(const MeshCoP::JoinerPskd &aPskd) { static_assert(static_cast(MeshCoP::JoinerPskd::kMaxLength) <= - static_cast(MeshCoP::SecureTransport::kPskMaxLength), + static_cast(MeshCoP::Dtls::kPskMaxLength), "The maximum length of DTLS PSK is smaller than joiner PSKd"); SuccessOrAssert(mDtls.SetPsk(reinterpret_cast(aPskd.GetAsCString()), aPskd.GetLength())); @@ -172,12 +172,12 @@ Error CoapSecureBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessa return kErrorNone; } -void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext) +void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent, void *aContext) { return static_cast(aContext)->HandleDtlsConnectEvent(aEvent); } -void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent) +void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent) { mConnectEventCallback.InvokeIfSet(aEvent); } diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp index 07a0e5c9d..67a54a13d 100644 --- a/src/core/coap/coap_secure.hpp +++ b/src/core/coap/coap_secure.hpp @@ -96,7 +96,7 @@ public: * @retval kErrorNone Successfully started the CoAP agent. * @retval kErrorAlready Already started. */ - Error Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext); + Error Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext); /** * Sets connected callback of this secure CoAP agent. @@ -159,7 +159,7 @@ public: * * @returns A reference to the DTLS object. */ - MeshCoP::SecureTransport &GetDtls(void) { return mDtls; } + MeshCoP::Dtls &GetDtls(void) { return mDtls; } /** * Gets the UDP port of this agent. @@ -293,7 +293,7 @@ public: const Ip6::MessageInfo &GetMessageInfo(void) const { return mDtls.GetMessageInfo(); } protected: - CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity); + CoapSecureBase(Instance &aInstance, MeshCoP::Dtls &aDtls); Error Open(uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext); @@ -304,8 +304,8 @@ protected: Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - static void HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext); - void HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent); + static void HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent, void *aContext); + void HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent); static void HandleDtlsAutoClose(void *aContext); void HandleDtlsAutoClose(void); @@ -316,7 +316,7 @@ protected: static void HandleTransmit(Tasklet &aTasklet); void HandleTransmit(void); - MeshCoP::SecureTransport mDtls; + MeshCoP::Dtls &mDtls; Callback mConnectEventCallback; Callback mAutoStopCallback; ot::MessageQueue mTransmitQueue; @@ -328,7 +328,7 @@ protected: /** * Represents an Application CoAPS. */ -class ApplicationCoapSecure : public CoapSecureBase +class ApplicationCoapSecure : public CoapSecureBase, public MeshCoP::Dtls::Extension { public: /** @@ -338,86 +338,14 @@ public: * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. */ ApplicationCoapSecure(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) - : CoapSecureBase(aInstance, aLayerTwoSecurity) + : CoapSecureBase(aInstance, mDtls) + , MeshCoP::Dtls::Extension(mDtls) + , mDtls(aInstance, aLayerTwoSecurity, *this) { } -#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - /** - * Sets the Pre-Shared Key (PSK) for DTLS sessions identified by a PSK. - * - * DTLS mode "TLS with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aPsk A pointer to the PSK. - * @param[in] aPskLength The PSK char length. - * @param[in] aPskIdentity The Identity Name for the PSK. - * @param[in] aPskIdLength The PSK Identity Length. - */ - void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength) - { - mDtls.SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength); - } -#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - /** - * Sets a X509 certificate with corresponding private key for DTLS session. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aX509Cert A pointer to the PEM formatted X509 PEM certificate. - * @param[in] aX509Length The length of certificate. - * @param[in] aPrivateKey A pointer to the PEM formatted private key. - * @param[in] aPrivateKeyLength The length of the private key. - */ - void SetCertificate(const uint8_t *aX509Cert, - uint32_t aX509Length, - const uint8_t *aPrivateKey, - uint32_t aPrivateKeyLength) - { - mDtls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength); - } - - /** - * Sets the trusted top level CAs. It is needed for validate the certificate of the peer. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain. - * @param[in] aX509CaCertChainLength The length of chain. - */ - void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength) - { - mDtls.SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength); - } -#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /** - * Returns the peer x509 certificate base64 encoded. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[out] aPeerCert A pointer to the base64 encoded certificate buffer. - * @param[out] aCertLength The length of the base64 encoded peer certificate. - * @param[in] aCertBufferSize The buffer size of aPeerCert. - * - * @retval kErrorNone Successfully get the peer certificate. - * @retval kErrorNoBufs Can't allocate memory for certificate. - */ - Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize) - { - return mDtls.GetPeerCertificateBase64(aPeerCert, aCertLength, aCertBufferSize); - } -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - - /** - * Sets the authentication mode for the CoAP secure connection. It disables or enables the verification - * of peer certificate. - * - * @param[in] aVerifyPeerCertificate true, if the peer certificate should be verified - */ - void SetSslAuthMode(bool aVerifyPeerCertificate) { mDtls.SetSslAuthMode(aVerifyPeerCertificate); } +private: + MeshCoP::DtlsExtended mDtls; }; #endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 1e14c6649..e458f32ef 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -639,14 +639,14 @@ exit: FreeMessageOnError(response, error); } -void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent, void *aContext) +void BorderAgent::HandleConnected(Dtls::ConnectEvent aEvent, void *aContext) { static_cast(aContext)->HandleConnected(aEvent); } -void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent) +void BorderAgent::HandleConnected(Dtls::ConnectEvent aEvent) { - if (aEvent == SecureTransport::kConnected) + if (aEvent == Dtls::kConnected) { LogInfo("SecureSession connected"); mState = kStateConnected; @@ -674,11 +674,11 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent) { RestartAfterRemovingEphemeralKey(); - if (aEvent == SecureTransport::kDisconnectedError) + if (aEvent == Dtls::kDisconnectedError) { mCounters.mEpskcSecureSessionFailures++; } - else if (aEvent == SecureTransport::kDisconnectedPeerClosed) + else if (aEvent == Dtls::kDisconnectedPeerClosed) { mCounters.mEpskcDeactivationDisconnects++; } @@ -689,7 +689,7 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent) mState = kStateStarted; mUdpProxyPort = 0; - if (aEvent == SecureTransport::kDisconnectedError) + if (aEvent == Dtls::kDisconnectedError) { mCounters.mPskcSecureSessionFailures++; } diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp index 7091b0e79..fc85eabff 100644 --- a/src/core/meshcop/border_agent.hpp +++ b/src/core/meshcop/border_agent.hpp @@ -251,8 +251,7 @@ public: uint16_t GetUdpProxyPort(void) const { return mUdpProxyPort; } private: - static_assert(kMaxEphemeralKeyLength <= SecureTransport::kPskMaxLength, - "Max ephemeral key length is larger than max PSK len"); + static_assert(kMaxEphemeralKeyLength <= Dtls::kPskMaxLength, "Max ephemeral key length is larger than max PSK len"); static constexpr uint16_t kUdpPort = OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT; static constexpr uint32_t kKeepAliveTimeout = 50 * 1000; // Timeout to reject a commissioner (in msec) @@ -288,8 +287,8 @@ private: void SendErrorMessage(const ForwardContext &aForwardContext, Error aError); void SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError); - static void HandleConnected(SecureTransport::ConnectEvent aEvent, void *aContext); - void HandleConnected(SecureTransport::ConnectEvent aEvent); + static void HandleConnected(Dtls::ConnectEvent aEvent, void *aContext); + void HandleConnected(Dtls::ConnectEvent aEvent); template void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 9e7cd8c32..6c4b093bd 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -112,14 +112,14 @@ exit: return; } -void Commissioner::HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent, void *aContext) +void Commissioner::HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent, void *aContext) { static_cast(aContext)->HandleSecureAgentConnectEvent(aEvent); } -void Commissioner::HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent) +void Commissioner::HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent) { - bool isConnected = (aEvent == SecureTransport::kConnected); + bool isConnected = (aEvent == Dtls::kConnected); if (!isConnected) { mJoinerSessionTimer.Stop(); diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp index 4fd2ebcf8..03f79044b 100644 --- a/src/core/meshcop/commissioner.hpp +++ b/src/core/meshcop/commissioner.hpp @@ -414,8 +414,8 @@ private: Error aResult); void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult); - static void HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent, void *aContext); - void HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent); + static void HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent, void *aContext); + void HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent); template void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 056804849..032c6662e 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -367,16 +367,16 @@ exit: return error; } -void Joiner::HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent, void *aContext) +void Joiner::HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent, void *aContext) { static_cast(aContext)->HandleSecureCoapClientConnect(aEvent); } -void Joiner::HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent) +void Joiner::HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent) { VerifyOrExit(mState == kStateConnect); - if (aEvent == SecureTransport::kConnected) + if (aEvent == Dtls::kConnected) { SetState(kStateConnected); SendJoinerFinalize(); diff --git a/src/core/meshcop/joiner.hpp b/src/core/meshcop/joiner.hpp index b1334d954..d4a8ed063 100644 --- a/src/core/meshcop/joiner.hpp +++ b/src/core/meshcop/joiner.hpp @@ -189,8 +189,8 @@ private: static void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult, void *aContext); void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult); - static void HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent, void *aContext); - void HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent); + static void HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent, void *aContext); + void HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent); static void HandleJoinerFinalizeResponse(void *aContext, otMessage *aMessage, diff --git a/src/core/meshcop/secure_transport.cpp b/src/core/meshcop/secure_transport.cpp index 2a71ab654..0859847dd 100644 --- a/src/core/meshcop/secure_transport.cpp +++ b/src/core/meshcop/secure_transport.cpp @@ -89,6 +89,9 @@ SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwo , mSocket(aInstance, *this) , mTimer(aInstance, SecureTransport::HandleTimer, this) , mTimerIntermediate(0) +#if OPENTHREAD_CONFIG_TLS_API_ENABLE + , mExtension(nullptr) +#endif { ClearAllBytes(mPsk); ClearAllBytes(mSsl); @@ -108,7 +111,10 @@ void SecureTransport::FreeMbedtls(void) } #endif #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - mEcdheEcdsaInfo.Free(); + if (mExtension != nullptr) + { + mExtension->mEcdheEcdsaInfo.Free(); + } #endif mbedtls_ssl_config_free(&mConf); mbedtls_ssl_free(&mSsl); @@ -277,9 +283,14 @@ Error SecureTransport::Setup(bool aClient) mbedtls_ssl_init(&mSsl); mbedtls_ssl_config_init(&mConf); + #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - mEcdheEcdsaInfo.Init(); + if (mExtension != nullptr) + { + mExtension->mEcdheEcdsaInfo.Init(); + } #endif + #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C) if (mDatagramTransport) { @@ -367,9 +378,9 @@ Error SecureTransport::Setup(bool aClient) rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength); } #if OPENTHREAD_CONFIG_TLS_API_ENABLE - else + else if (mExtension != nullptr) { - rval = SetApplicationSecureKeys(); + rval = mExtension->SetApplicationSecureKeys(); } #endif VerifyOrExit(rval == 0); @@ -400,23 +411,23 @@ exit: } #if OPENTHREAD_CONFIG_TLS_API_ENABLE -int SecureTransport::SetApplicationSecureKeys(void) +int SecureTransport::Extension::SetApplicationSecureKeys(void) { int rval = 0; - switch (mCipherSuite) + switch (mSecureTransport.mCipherSuite) { #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED case kEcdheEcdsaWithAes128Ccm8: case kEcdheEcdsaWithAes128GcmSha256: - rval = mEcdheEcdsaInfo.SetSecureKeys(mConf); + rval = mEcdheEcdsaInfo.SetSecureKeys(mSecureTransport.mConf); VerifyOrExit(rval == 0); break; #endif #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED case kPskWithAes128Ccm8: - rval = mPskInfo.SetSecureKeys(mConf); + rval = mPskInfo.SetSecureKeys(mSecureTransport.mConf); VerifyOrExit(rval == 0); break; #endif @@ -425,7 +436,6 @@ int SecureTransport::SetApplicationSecureKeys(void) LogCrit("Application Coap Secure: Not supported cipher."); rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; ExitNow(); - break; } exit: @@ -480,21 +490,21 @@ exit: #if OPENTHREAD_CONFIG_TLS_API_ENABLE #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -void SecureTransport::EcdheEcdsaInfo::Init(void) +void SecureTransport::Extension::EcdheEcdsaInfo::Init(void) { mbedtls_x509_crt_init(&mCaChain); mbedtls_x509_crt_init(&mOwnCert); mbedtls_pk_init(&mPrivateKey); } -void SecureTransport::EcdheEcdsaInfo::Free(void) +void SecureTransport::Extension::EcdheEcdsaInfo::Free(void) { mbedtls_x509_crt_free(&mCaChain); mbedtls_x509_crt_free(&mOwnCert); mbedtls_pk_free(&mPrivateKey); } -int SecureTransport::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) +int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) { int rval = 0; @@ -528,10 +538,10 @@ exit: return rval; } -void SecureTransport::SetCertificate(const uint8_t *aX509Certificate, - uint32_t aX509CertLength, - const uint8_t *aPrivateKey, - uint32_t aPrivateKeyLength) +void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate, + uint32_t aX509CertLength, + const uint8_t *aPrivateKey, + uint32_t aPrivateKeyLength) { OT_ASSERT(aX509CertLength > 0); OT_ASSERT(aX509Certificate != nullptr); @@ -544,10 +554,12 @@ void SecureTransport::SetCertificate(const uint8_t *aX509Certificate, mEcdheEcdsaInfo.mPrivateKeySrc = aPrivateKey; mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength; - mCipherSuite = mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256; + mSecureTransport.mCipherSuite = + mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256; } -void SecureTransport::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength) +void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, + uint32_t aX509CaCertChainLength) { OT_ASSERT(aX509CaCertChainLength > 0); OT_ASSERT(aX509CaCertificateChain != nullptr); @@ -560,16 +572,16 @@ void SecureTransport::SetCaCertificateChain(const uint8_t *aX509CaCertificateCha #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -int SecureTransport::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const +int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const { return mbedtls_ssl_conf_psk(&aConfig, static_cast(mPreSharedKey), mPreSharedKeyLength, static_cast(mPreSharedKeyIdentity), mPreSharedKeyIdLength); } -void SecureTransport::SetPreSharedKey(const uint8_t *aPsk, - uint16_t aPskLength, - const uint8_t *aPskIdentity, - uint16_t aPskIdLength) +void SecureTransport::Extension::SetPreSharedKey(const uint8_t *aPsk, + uint16_t aPskLength, + const uint8_t *aPskIdentity, + uint16_t aPskIdLength) { OT_ASSERT(aPsk != nullptr); OT_ASSERT(aPskIdentity != nullptr); @@ -581,30 +593,37 @@ void SecureTransport::SetPreSharedKey(const uint8_t *aPsk, mPskInfo.mPreSharedKeyIdentity = aPskIdentity; mPskInfo.mPreSharedKeyIdLength = aPskIdLength; - mCipherSuite = kPskWithAes128Ccm8; + mSecureTransport.mCipherSuite = kPskWithAes128Ccm8; } #endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -Error SecureTransport::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize) +Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert, + size_t *aCertLength, + size_t aCertBufferSize) { Error error = kErrorNone; - VerifyOrExit(IsStateConnected(), error = kErrorInvalidState); + VerifyOrExit(mSecureTransport.IsStateConnected(), error = kErrorInvalidState); #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) - VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength, - mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p, - mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == 0, - error = kErrorNoBufs); -#else VerifyOrExit( - mbedtls_base64_encode( - aPeerCert, aCertBufferSize, aCertLength, - mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), - mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) == 0, + 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, + error = kErrorNoBufs); #endif exit: @@ -613,17 +632,17 @@ exit: #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -Error SecureTransport::GetPeerSubjectAttributeByOid(const char *aOid, - size_t aOidLength, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength, - int *aAsn1Type) +Error SecureTransport::Extension::GetPeerSubjectAttributeByOid(const char *aOid, + size_t aOidLength, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength, + int *aAsn1Type) { Error error = kErrorNone; const mbedtls_asn1_named_data *data; size_t length; size_t attributeBufferSize; - mbedtls_x509_crt *peerCert = const_cast(mbedtls_ssl_get_peer_cert(&mSsl)); + mbedtls_x509_crt *peerCert = const_cast(mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl)); VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); attributeBufferSize = *aAttributeLength; @@ -650,30 +669,30 @@ exit: return error; } -Error SecureTransport::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) +Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength) { - const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSsl); + const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl); return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); } #endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -Error SecureTransport::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) +Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength) { const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert; return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); } -Error SecureTransport::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, - int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) +Error SecureTransport::Extension::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, + int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength) { Error error = kErrorNotFound; char oid[9] = {0x2B, 0x06, 0x01, 0x04, 0x01, static_cast(0x82), static_cast(0xDF), diff --git a/src/core/meshcop/secure_transport.hpp b/src/core/meshcop/secure_transport.hpp index b6992cd9d..b6539fa2f 100644 --- a/src/core/meshcop/secure_transport.hpp +++ b/src/core/meshcop/secure_transport.hpp @@ -88,6 +88,9 @@ namespace ot { namespace MeshCoP { +/** + * Represents a secure transport, used as base class for `Dtls` and `Tls`. + */ class SecureTransport : public InstanceLocator { public: @@ -132,14 +135,233 @@ public: */ typedef void (*AutoCloseCallback)(void *aContext); +#if OPENTHREAD_CONFIG_TLS_API_ENABLE /** - * Initializes the SecureTransport object. + * Represents an API extension for a `SecureTransport` (DTLS or TLS). * - * @param[in] aInstance A reference to the OpenThread instance. - * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. - * @param[in] aDatagramTransport Specifies if dtls of tls connection should be used. + * The `Extension` provides support for additional cipher suites along with related methods to configure them. + * This class decouples this functionality from the common `SecureTransport` object, allowing this to be added + * to any class. + * + * The general pattern to use the `Extension` class is to have it be inherited by classes that want to provide the + * same methods for configuring ciphers (e.g. `SetPreSharedKey()` or `SetCertificate()`). An `Extension` should + * then be associated with a `SecureTransport` (or any of its subclasses). */ - explicit SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport = true); + class Extension + { + friend SecureTransport; + + public: +#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + /** + * Sets the Pre-Shared Key (PSK) for sessions-identified by a PSK. + * + * DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS. + * + * @param[in] aPsk A pointer to the PSK. + * @param[in] aPskLength The PSK char length. + * @param[in] aPskIdentity The Identity Name for the PSK. + * @param[in] aPskIdLength The PSK Identity Length. + */ + void SetPreSharedKey(const uint8_t *aPsk, + uint16_t aPskLength, + const uint8_t *aPskIdentity, + uint16_t aPskIdLength); +#endif + +#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + /** + * Sets a reference to the own x509 certificate with corresponding private key. + * + * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. + * + * @param[in] aX509Certificate A pointer to the PEM formatted X509 certificate. + * @param[in] aX509CertLength The length of certificate. + * @param[in] aPrivateKey A pointer to the PEM formatted private key. + * @param[in] aPrivateKeyLength The length of the private key. + */ + void SetCertificate(const uint8_t *aX509Certificate, + uint32_t aX509CertLength, + const uint8_t *aPrivateKey, + uint32_t aPrivateKeyLength); + + /** + * Sets the trusted top level CAs. It is needed for validate the certificate of the peer. + * + * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. + * + * @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain. + * @param[in] aX509CaCertChainLength The length of chain. + */ + void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength); + + /** + * Extracts public key from it's own certificate. + * + * @returns Public key from own certificate in form of entire ASN.1 field. + */ + const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mEcdheEcdsaInfo.mOwnCert.pk_raw; } + +#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /** + * Returns the peer x509 certificate base64 encoded. + * + * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. + * + * @param[out] aPeerCert A pointer to the base64 encoded certificate buffer. + * @param[out] aCertLength The length of the base64 encoded peer certificate. + * @param[in] aCertBufferSize The buffer size of aPeerCert. + * + * @retval kErrorInvalidState Not connected yet. + * @retval kErrorNone Successfully get the peer certificate. + * @retval kErrorNoBufs Can't allocate memory for certificate. + */ + Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize); +#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /** + * Returns an attribute value identified by its OID from the subject + * of the peer x509 certificate. The peer OID is provided in binary format. + * The attribute length is set if the attribute was successfully read or zero + * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard + * if the attribute was successfully read. + * + * @param[in] aOid A pointer to the OID to be found. + * @param[in] aOidLength The length of the OID. + * @param[out] aAttributeBuffer A pointer to the attribute buffer. + * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. + * On output, the length of the attribute written to the buffer. + * @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer. + * + * @retval kErrorInvalidState Not connected yet. + * @retval kErrorInvalidArgs Invalid attribute length. + * @retval kErrorNone Successfully read attribute. + * @retval kErrorNoBufs Insufficient memory for storing the attribute value. + */ + Error GetPeerSubjectAttributeByOid(const char *aOid, + size_t aOidLength, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength, + int *aAsn1Type); + + /** + * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of + * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor. + * The attribute length is set if the attribute was successfully read or zero if unsuccessful. + * Requires a connection to be active. + * + * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. + * @param[out] aAttributeBuffer A pointer to the attribute buffer. + * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. + * On output, the length of the attribute written to the buffer. + * + * @retval kErrorNone Successfully read attribute. + * @retval kErrorInvalidArgs Invalid attribute length. + * @retval kErrorNotFound The requested attribute was not found. + * @retval kErrorNoBufs Insufficient memory for storing the attribute value. + * @retval kErrorInvalidState Not connected yet. + * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. + * @retval kErrorParse The certificate extensions could not be parsed. + */ + Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength); +#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + + /** + * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of + * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor. + * The attribute length is set if the attribute was successfully read or zero if unsuccessful. + * Requires a connection to be active. + * + * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. + * @param[out] aAttributeBuffer A pointer to the attribute buffer. + * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. + * On output, the length of the attribute written to the buffer. + * + * @retval kErrorNone Successfully read attribute. + * @retval kErrorInvalidArgs Invalid attribute length. + * @retval kErrorNotFound The requested attribute was not found. + * @retval kErrorNoBufs Insufficient memory for storing the attribute value. + * @retval kErrorInvalidState Not connected yet. + * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. + * @retval kErrorParse The certificate extensions could not be parsed. + */ + Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength); + + /** + * Set the authentication mode for a connection. + * + * Disable or enable the verification of peer certificate. + * Must called before start. + * + * @param[in] aVerifyPeerCertificate true, if the peer certificate should verify. + */ + void SetSslAuthMode(bool aVerifyPeerCertificate) + { + mSecureTransport.mVerifyPeerCertificate = aVerifyPeerCertificate; + } + + protected: + explicit Extension(SecureTransport &aSecureTransport) + : mSecureTransport(aSecureTransport) + { + } + + private: +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + struct EcdheEcdsaInfo : public Clearable + { + EcdheEcdsaInfo(void) { Clear(); } + void Init(void); + void Free(void); + int SetSecureKeys(mbedtls_ssl_config &aConfig); + + const uint8_t *mCaChainSrc; + const uint8_t *mOwnCertSrc; + const uint8_t *mPrivateKeySrc; + uint32_t mOwnCertLength; + uint32_t mCaChainLength; + uint32_t mPrivateKeyLength; + mbedtls_x509_crt mCaChain; + mbedtls_x509_crt mOwnCert; + mbedtls_pk_context mPrivateKey; + }; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + struct PskInfo : public Clearable + { + PskInfo(void) { Clear(); } + int SetSecureKeys(mbedtls_ssl_config &aConfig) const; + + const uint8_t *mPreSharedKey; + const uint8_t *mPreSharedKeyIdentity; + uint16_t mPreSharedKeyLength; + uint16_t mPreSharedKeyIdLength; + }; +#endif + + int SetApplicationSecureKeys(void); + Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, + int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength); + + SecureTransport &mSecureTransport; +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + EcdheEcdsaInfo mEcdheEcdsaInfo; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + PskInfo mPskInfo; +#endif + }; +#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE /** * Opens the socket. @@ -258,161 +480,6 @@ public: */ Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength); -#if OPENTHREAD_CONFIG_TLS_API_ENABLE - -#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - /** - * Sets the Pre-Shared Key (PSK) for sessions-identified by a PSK. - * - * DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aPsk A pointer to the PSK. - * @param[in] aPskLength The PSK char length. - * @param[in] aPskIdentity The Identity Name for the PSK. - * @param[in] aPskIdLength The PSK Identity Length. - * - * @retval kErrorNone Successfully set the PSK. - */ - void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength); -#endif - -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - /** - * Sets a reference to the own x509 certificate with corresponding private key. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aX509Certificate A pointer to the PEM formatted X509 certificate. - * @param[in] aX509CertLength The length of certificate. - * @param[in] aPrivateKey A pointer to the PEM formatted private key. - * @param[in] aPrivateKeyLength The length of the private key. - */ - void SetCertificate(const uint8_t *aX509Certificate, - uint32_t aX509CertLength, - const uint8_t *aPrivateKey, - uint32_t aPrivateKeyLength); - - /** - * Sets the trusted top level CAs. It is needed for validate the certificate of the peer. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain. - * @param[in] aX509CaCertChainLength The length of chain. - */ - void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength); - - /** - * Extracts public key from it's own certificate. - * - * @returns Public key from own certificate in form of entire ASN.1 field. - */ - const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mEcdheEcdsaInfo.mOwnCert.pk_raw; } - -#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /** - * Returns the peer x509 certificate base64 encoded. - * - * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. - * - * @param[out] aPeerCert A pointer to the base64 encoded certificate buffer. - * @param[out] aCertLength The length of the base64 encoded peer certificate. - * @param[in] aCertBufferSize The buffer size of aPeerCert. - * - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNone Successfully get the peer certificate. - * @retval kErrorNoBufs Can't allocate memory for certificate. - */ - Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize); -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /** - * Returns an attribute value identified by its OID from the subject - * of the peer x509 certificate. The peer OID is provided in binary format. - * The attribute length is set if the attribute was successfully read or zero - * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard - * if the attribute was successfully read. - * - * @param[in] aOid A pointer to the OID to be found. - * @param[in] aOidLength The length of the OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer. - * - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorInvalidArgs Invalid attribute length. - * @retval kErrorNone Successfully read attribute. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - */ - Error GetPeerSubjectAttributeByOid(const char *aOid, - size_t aOidLength, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength, - int *aAsn1Type); - - /** - * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of - * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor. - * The attribute length is set if the attribute was successfully read or zero if unsuccessful. - * Requires a connection to be active. - * - * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * - * @retval kErrorNone Successfully read attribute. - * @retval kErrorInvalidArgs Invalid attribute length. - * @retval kErrorNotFound The requested attribute was not found. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. - * @retval kErrorParse The certificate extensions could not be parsed. - */ - Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength); -#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - - /** - * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of - * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor. - * The attribute length is set if the attribute was successfully read or zero if unsuccessful. - * Requires a connection to be active. - * - * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * - * @retval kErrorNone Successfully read attribute. - * @retval kErrorInvalidArgs Invalid attribute length. - * @retval kErrorNotFound The requested attribute was not found. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. - * @retval kErrorParse The certificate extensions could not be parsed. - */ - Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength); - - /** - * Set the authentication mode for a connection. - * - * Disable or enable the verification of peer certificate. - * Must called before start. - * - * @param[in] aVerifyPeerCertificate true, if the peer certificate should verify. - */ - void SetSslAuthMode(bool aVerifyPeerCertificate) { mVerifyPeerCertificate = aVerifyPeerCertificate; } - -#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE - /** * Sends data within the session. * @@ -440,6 +507,13 @@ public: */ void HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); +protected: + SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport); + +#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; @@ -474,39 +548,6 @@ private: kUnspecifiedCipherSuite, }; -#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - struct EcdheEcdsaInfo : public Clearable - { - EcdheEcdsaInfo(void) { Clear(); } - void Init(void); - void Free(void); - int SetSecureKeys(mbedtls_ssl_config &aConfig); - - const uint8_t *mCaChainSrc; - const uint8_t *mOwnCertSrc; - const uint8_t *mPrivateKeySrc; - uint32_t mOwnCertLength; - uint32_t mCaChainLength; - uint32_t mPrivateKeyLength; - mbedtls_x509_crt mCaChain; - mbedtls_x509_crt mOwnCert; - mbedtls_pk_context mPrivateKey; - }; -#endif - -#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - struct PskInfo : public Clearable - { - PskInfo(void) { Clear(); } - int SetSecureKeys(mbedtls_ssl_config &aConfig) const; - - const uint8_t *mPreSharedKey; - const uint8_t *mPreSharedKeyIdentity; - uint16_t mPreSharedKeyLength; - uint16_t mPreSharedKeyIdLength; - }; -#endif - bool IsStateClosed(void) const { return mState == kStateClosed; } bool IsStateOpen(void) const { return mState == kStateOpen; } bool IsStateInitializing(void) const { return mState == kStateInitializing; } @@ -519,14 +560,6 @@ private: void FreeMbedtls(void); Error Setup(bool aClient); -#if OPENTHREAD_CONFIG_TLS_API_ENABLE - int SetApplicationSecureKeys(void); - Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, - int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength); -#endif - static bool IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext); static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr); @@ -633,14 +666,77 @@ private: #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C) mbedtls_ssl_cookie_ctx mCookieCtx; #endif -#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - EcdheEcdsaInfo mEcdheEcdsaInfo; -#endif -#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - PskInfo mPskInfo; +#if OPENTHREAD_CONFIG_TLS_API_ENABLE + Extension *mExtension; #endif }; +/** + * Represents a DTLS instance. + */ +class Dtls : public SecureTransport +{ +public: + /** + * Initializes the `Dtls` object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. + */ + Dtls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) + : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ true) + { + } +}; + +#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE + +/** + * Represents an extended DTLS instance providing `Dtls::Extension` APIs. + */ +class DtlsExtended : public Dtls +{ +public: + /** + * Initializes the `DtlsExtended` object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. + * @param[in] aExtension An extension providing additional configuration methods. + */ + DtlsExtended(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension) + : Dtls(aInstance, aLayerTwoSecurity) + { + SetExtension(aExtension); + } +}; + +#endif + +#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE + +/** + * Represents a TLS instance. + */ +class Tls : public SecureTransport +{ +public: + /** + * Initializes the `Tls` object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. + * @param[in] aExtension An extension providing additional configuration methods. + */ + Tls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension) + : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ false) + { + SetExtension(aExtension); + } +}; + +#endif + } // namespace MeshCoP } // namespace ot diff --git a/src/core/meshcop/tcat_agent.cpp b/src/core/meshcop/tcat_agent.cpp index e9dede3d6..8d40e2273 100644 --- a/src/core/meshcop/tcat_agent.cpp +++ b/src/core/meshcop/tcat_agent.cpp @@ -112,7 +112,7 @@ exit: return error; } -Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext) +Error TcatAgent::Connected(MeshCoP::Tls::Extension &aTls) { size_t len; Error error; @@ -120,13 +120,13 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext) VerifyOrExit(IsEnabled(), error = kErrorInvalidState); len = sizeof(mCommissionerAuthorizationField); SuccessOrExit( - error = aTlsContext.GetThreadAttributeFromPeerCertificate( + error = aTls.GetThreadAttributeFromPeerCertificate( kCertificateAuthorizationField, reinterpret_cast(&mCommissionerAuthorizationField), &len)); VerifyOrExit(len == sizeof(mCommissionerAuthorizationField), error = kErrorParse); VerifyOrExit((mCommissionerAuthorizationField.mHeader & kCommissionerFlag) == 1, error = kErrorParse); len = sizeof(mDeviceAuthorizationField); - SuccessOrExit(error = aTlsContext.GetThreadAttributeFromOwnCertificate( + SuccessOrExit(error = aTls.GetThreadAttributeFromOwnCertificate( kCertificateAuthorizationField, reinterpret_cast(&mDeviceAuthorizationField), &len)); VerifyOrExit(len == sizeof(mDeviceAuthorizationField), error = kErrorParse); VerifyOrExit((mDeviceAuthorizationField.mHeader & kCommissionerFlag) == 0, error = kErrorParse); @@ -136,7 +136,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext) mCommissionerHasExtendedPanId = false; len = sizeof(mCommissionerDomainName) - 1; - if (aTlsContext.GetThreadAttributeFromPeerCertificate( + if (aTls.GetThreadAttributeFromPeerCertificate( kCertificateDomainName, reinterpret_cast(&mCommissionerDomainName), &len) == kErrorNone) { mCommissionerDomainName.m8[len] = '\0'; @@ -144,7 +144,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext) } len = sizeof(mCommissionerNetworkName) - 1; - if (aTlsContext.GetThreadAttributeFromPeerCertificate( + if (aTls.GetThreadAttributeFromPeerCertificate( kCertificateNetworkName, reinterpret_cast(&mCommissionerNetworkName), &len) == kErrorNone) { mCommissionerNetworkName.m8[len] = '\0'; @@ -152,7 +152,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext) } len = sizeof(mCommissionerExtendedPanId); - if (aTlsContext.GetThreadAttributeFromPeerCertificate( + if (aTls.GetThreadAttributeFromPeerCertificate( kCertificateExtendedPanId, reinterpret_cast(&mCommissionerExtendedPanId), &len) == kErrorNone) { if (len == sizeof(mCommissionerExtendedPanId)) diff --git a/src/core/meshcop/tcat_agent.hpp b/src/core/meshcop/tcat_agent.hpp index e318351db..9b87daf46 100644 --- a/src/core/meshcop/tcat_agent.hpp +++ b/src/core/meshcop/tcat_agent.hpp @@ -334,7 +334,7 @@ public: bool GetInstallCodeVerifyStatus(void) const { return mInstallCodeVerified; } private: - Error Connected(MeshCoP::SecureTransport &aTlsContext); + Error Connected(MeshCoP::Tls::Extension &aTls); void Disconnected(void); Error HandleSingleTlv(const Message &aIncomingMessage, Message &aOutgoingMessage); diff --git a/src/core/radio/ble_secure.cpp b/src/core/radio/ble_secure.cpp index b169bf3e2..f7c2d9cf1 100644 --- a/src/core/radio/ble_secure.cpp +++ b/src/core/radio/ble_secure.cpp @@ -48,7 +48,8 @@ RegisterLogModule("BleSecure"); BleSecure::BleSecure(Instance &aInstance) : InstanceLocator(aInstance) - , mTls(aInstance, kNoLinkSecurity, /* aDatagramTransport */ false) + , MeshCoP::Tls::Extension(mTls) + , mTls(aInstance, kNoLinkSecurity, *this) , mTcatAgent(aInstance) , mTlvMode(false) , mReceivedMessage(nullptr) @@ -164,26 +165,12 @@ void BleSecure::Disconnect(void) void BleSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd) { static_assert(static_cast(MeshCoP::JoinerPskd::kMaxLength) <= - static_cast(MeshCoP::SecureTransport::kPskMaxLength), + static_cast(MeshCoP::Tls::kPskMaxLength), "The maximum length of TLS PSK is smaller than joiner PSKd"); SuccessOrAssert(mTls.SetPsk(reinterpret_cast(aPskd.GetAsCString()), aPskd.GetLength())); } -#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -Error BleSecure::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength) -{ - Error error; - - VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs); - - error = mTls.GetPeerCertificateBase64(aPeerCert, aCertLength, *aCertLength); - -exit: - return error; -} -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - Error BleSecure::SendMessage(ot::Message &aMessage) { Error error = kErrorNone; @@ -318,14 +305,14 @@ Error BleSecure::HandleBleMtuUpdate(uint16_t aMtu) return error; } -void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext) +void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent, void *aContext) { return static_cast(aContext)->HandleTlsConnectEvent(aEvent); } -void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent) +void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent) { - if (aEvent == MeshCoP::SecureTransport::kConnected) + if (aEvent == MeshCoP::Tls::kConnected) { Error err; @@ -333,7 +320,7 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEv { mReceivedMessage = Get().Allocate(Message::kTypeBle); } - err = mTcatAgent.Connected(mTls); + err = mTcatAgent.Connected(*this); if (err != kErrorNone) { @@ -353,7 +340,7 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEv } } - mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::SecureTransport::kConnected, true); + mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::Tls::kConnected, true); exit: return; diff --git a/src/core/radio/ble_secure.hpp b/src/core/radio/ble_secure.hpp index 48eda196d..2eec3a393 100644 --- a/src/core/radio/ble_secure.hpp +++ b/src/core/radio/ble_secure.hpp @@ -48,7 +48,7 @@ namespace ot { namespace Ble { -class BleSecure : public InstanceLocator, private NonCopyable +class BleSecure : public InstanceLocator, public MeshCoP::Tls::Extension, private NonCopyable { public: /** @@ -187,168 +187,6 @@ public: */ void SetPsk(const MeshCoP::JoinerPskd &aPskd); -#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - /** - * Sets the Pre-Shared Key (PSK) for TLS sessions identified by a PSK. - * - * TLS mode "TLS with AES 128 CCM 8" for secure BLE. - * - * @param[in] aPsk A pointer to the PSK. - * @param[in] aPskLength The PSK char length. - * @param[in] aPskIdentity The Identity Name for the PSK. - * @param[in] aPskIdLength The PSK Identity Length. - */ - void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength) - { - mTls.SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength); - } -#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - /** - * Sets a X509 certificate with corresponding private key for TLS session. - * - * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE. - * - * @param[in] aX509Cert A pointer to the PEM formatted X509 PEM certificate. - * @param[in] aX509Length The length of certificate. - * @param[in] aPrivateKey A pointer to the PEM formatted private key. - * @param[in] aPrivateKeyLength The length of the private key. - */ - void SetCertificate(const uint8_t *aX509Cert, - uint32_t aX509Length, - const uint8_t *aPrivateKey, - uint32_t aPrivateKeyLength) - { - mTls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength); - } - - /** - * Sets the trusted top level CAs. It is needed for validate the certificate of the peer. - * - * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE. - * - * @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain. - * @param[in] aX509CaCertChainLength The length of chain. - */ - void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength) - { - mTls.SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength); - } -#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /** - * Returns the peer x509 certificate base64 encoded. - * - * TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE. - * - * @param[out] aPeerCert A pointer to the base64 encoded certificate buffer. - * @param[out] aCertLength On input, the size the max size of @p aPeerCert. - * On output, the length of the base64 encoded peer certificate. - * - * @retval kErrorNone Successfully get the peer certificate. - * @retval kErrorInvalidArgs @p aInstance or @p aCertLength is invalid. - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNoBufs Can't allocate memory for certificate. - */ - Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength); -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /** - * Returns an attribute value identified by its OID from the subject - * of the peer x509 certificate. The peer OID is provided in binary format. - * The attribute length is set if the attribute was successfully read or zero - * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard - * if the attribute was successfully read. - * - * @param[in] aOid A pointer to the OID to be found. - * @param[in] aOidLength The length of the OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer. - * - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNone Successfully read attribute. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - */ - Error GetPeerSubjectAttributeByOid(const char *aOid, - size_t aOidLength, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength, - int *aAsn1Type) - { - return mTls.GetPeerSubjectAttributeByOid(aOid, aOidLength, aAttributeBuffer, aAttributeLength, aAsn1Type); - } - - /** - * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of - * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor. - * The attribute length is set if the attribute was successfully read or zero if unsuccessful. - * Requires a connection to be active. - * - * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * - * @retval kErrorNone Successfully read attribute. - * @retval kErrorNotFound The requested attribute was not found. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. - * @retval kErrorParse The certificate extensions could not be parsed. - */ - Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) - { - return mTls.GetThreadAttributeFromPeerCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); - } -#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - - /** - * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of - * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor. - * The attribute length is set if the attribute was successfully read or zero if unsuccessful. - * Requires a connection to be active. - * - * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. - * @param[out] aAttributeBuffer A pointer to the attribute buffer. - * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. - * On output, the length of the attribute written to the buffer. - * - * @retval kErrorNone Successfully read attribute. - * @retval kErrorNotFound The requested attribute was not found. - * @retval kErrorNoBufs Insufficient memory for storing the attribute value. - * @retval kErrorInvalidState Not connected yet. - * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. - * @retval kErrorParse The certificate extensions could not be parsed. - */ - Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) - { - return mTls.GetThreadAttributeFromOwnCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); - } - - /** - * Extracts public key from it's own certificate. - * - * @returns Public key from own certificate in form of entire ASN.1 field. - */ - const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mTls.GetOwnPublicKey(); } - - /** - * Sets the authentication mode for the BLE secure connection. It disables or enables the verification - * of peer certificate. - * - * @param[in] aVerifyPeerCertificate true, if the peer certificate should be verified - */ - void SetSslAuthMode(bool aVerifyPeerCertificate) { mTls.SetSslAuthMode(aVerifyPeerCertificate); } - /** * Sends a secure BLE message. * @@ -447,8 +285,8 @@ private: static constexpr uint8_t kPacketBufferSize = OT_BLE_ATT_MTU_MAX - kGattOverhead; static constexpr uint16_t kTxBleHandle = 0; // Characteristics Handle for TX (not used) - static void HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext); - void HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent); + static void HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent, void *aContext); + void HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent); static void HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength); void HandleTlsReceive(uint8_t *aBuf, uint16_t aLength); @@ -460,7 +298,7 @@ private: using TxTask = TaskletIn; - MeshCoP::SecureTransport mTls; + MeshCoP::Tls mTls; MeshCoP::TcatAgent mTcatAgent; Callback mConnectCallback; Callback mReceiveCallback; diff --git a/src/core/thread/tmf.cpp b/src/core/thread/tmf.cpp index e8662fba6..d2d6ce3cd 100644 --- a/src/core/thread/tmf.cpp +++ b/src/core/thread/tmf.cpp @@ -273,7 +273,8 @@ Message::Priority Agent::DscpToPriority(uint8_t aDscp) #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE SecureAgent::SecureAgent(Instance &aInstance) - : Coap::CoapSecureBase(aInstance, kNoLinkSecurity) + : Coap::CoapSecureBase(aInstance, mDtls) + , mDtls(aInstance, kNoLinkSecurity) { SetResourceHandler(&HandleResource); } diff --git a/src/core/thread/tmf.hpp b/src/core/thread/tmf.hpp index 2a8b177c2..9177ce766 100644 --- a/src/core/thread/tmf.hpp +++ b/src/core/thread/tmf.hpp @@ -213,6 +213,8 @@ private: Message &aMessage, const Ip6::MessageInfo &aMessageInfo); bool HandleResource(const char *aUriPath, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + + MeshCoP::Dtls mDtls; }; #endif