From a7e058f56cf76c990efe60b59c52277b47282c74 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 20 Nov 2024 10:20:47 -0800 Subject: [PATCH] [coap] add base class `CoapSecureBase` and `ApplicationCoapSecure` (#10945) This commit refactors COAPS classes, renaming the `CoapSecure` class as `CoapSecureBase`, which is the base class of `Tmf::SecureAgent` and a newly added `ApplicationCoapSecure` class. This change simplifies the code and class hierarchy and ensures that the Application COAP secure related functions are only provided by `ApplicationCoapSecure` and when the corresponding config feature `OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE` is enabled. --- src/core/coap/coap_secure.cpp | 78 ++++++------- src/core/coap/coap_secure.hpp | 197 ++++++++++++++++++--------------- src/core/instance/instance.hpp | 4 +- src/core/thread/tmf.cpp | 2 +- src/core/thread/tmf.hpp | 2 +- 5 files changed, 148 insertions(+), 135 deletions(-) diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp index 057a2ff8d..9652eb801 100644 --- a/src/core/coap/coap_secure.cpp +++ b/src/core/coap/coap_secure.cpp @@ -42,16 +42,16 @@ namespace Coap { RegisterLogModule("CoapSecure"); -CoapSecure::CoapSecure(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) - : CoapBase(aInstance, &CoapSecure::Send) +CoapSecureBase::CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) + : CoapBase(aInstance, Send) , mDtls(aInstance, aLayerTwoSecurity) - , mTransmitTask(aInstance, CoapSecure::HandleTransmit, this) + , mTransmitTask(aInstance, HandleTransmit, this) { } -Error CoapSecure::Start(uint16_t aPort) { return Start(aPort, /* aMaxAttempts */ 0, nullptr, nullptr); } +Error CoapSecureBase::Start(uint16_t aPort) { return Start(aPort, /* aMaxAttempts */ 0, nullptr, nullptr); } -Error CoapSecure::Start(uint16_t aPort, uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext) +Error CoapSecureBase::Start(uint16_t aPort, uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext) { Error error; @@ -62,7 +62,7 @@ exit: return error; } -Error CoapSecure::Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext) +Error CoapSecureBase::Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext) { Error error; @@ -73,7 +73,7 @@ exit: return error; } -Error CoapSecure::Open(uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext) +Error CoapSecureBase::Open(uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext) { Error error = kErrorAlready; @@ -88,7 +88,7 @@ exit: return error; } -void CoapSecure::Stop(void) +void CoapSecureBase::Stop(void) { mDtls.Close(); @@ -96,14 +96,14 @@ void CoapSecure::Stop(void) ClearRequestsAndResponses(); } -Error CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectEventCallback aCallback, void *aContext) +Error CoapSecureBase::Connect(const Ip6::SockAddr &aSockAddr, ConnectEventCallback aCallback, void *aContext) { mConnectEventCallback.Set(aCallback, aContext); return mDtls.Connect(aSockAddr); } -void CoapSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd) +void CoapSecureBase::SetPsk(const MeshCoP::JoinerPskd &aPskd) { static_assert(static_cast(MeshCoP::JoinerPskd::kMaxLength) <= static_cast(MeshCoP::SecureTransport::kPskMaxLength), @@ -113,11 +113,11 @@ void CoapSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd) } #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE -Error CoapSecure::SendMessage(Message &aMessage, - ResponseHandler aHandler, - void *aContext, - otCoapBlockwiseTransmitHook aTransmitHook, - otCoapBlockwiseReceiveHook aReceiveHook) +Error CoapSecureBase::SendMessage(Message &aMessage, + ResponseHandler aHandler, + void *aContext, + otCoapBlockwiseTransmitHook aTransmitHook, + otCoapBlockwiseReceiveHook aReceiveHook) { Error error = kErrorNone; @@ -130,18 +130,18 @@ exit: return error; } -Error CoapSecure::SendMessage(Message &aMessage, - const Ip6::MessageInfo &aMessageInfo, - ResponseHandler aHandler, - void *aContext, - otCoapBlockwiseTransmitHook aTransmitHook, - otCoapBlockwiseReceiveHook aReceiveHook) +Error CoapSecureBase::SendMessage(Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + ResponseHandler aHandler, + void *aContext, + otCoapBlockwiseTransmitHook aTransmitHook, + otCoapBlockwiseReceiveHook aReceiveHook) { return CoapBase::SendMessage(aMessage, aMessageInfo, TxParameters::GetDefault(), aHandler, aContext, aTransmitHook, aReceiveHook); } #else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE -Error CoapSecure::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext) +Error CoapSecureBase::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext) { Error error = kErrorNone; @@ -153,16 +153,16 @@ exit: return error; } -Error CoapSecure::SendMessage(Message &aMessage, - const Ip6::MessageInfo &aMessageInfo, - ResponseHandler aHandler, - void *aContext) +Error CoapSecureBase::SendMessage(Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + ResponseHandler aHandler, + void *aContext) { return CoapBase::SendMessage(aMessage, aMessageInfo, aHandler, aContext); } #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE -Error CoapSecure::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +Error CoapSecureBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { OT_UNUSED_VARIABLE(aMessageInfo); @@ -172,33 +172,33 @@ Error CoapSecure::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageIn return kErrorNone; } -void CoapSecure::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext) +void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext) { - return static_cast(aContext)->HandleDtlsConnectEvent(aEvent); + return static_cast(aContext)->HandleDtlsConnectEvent(aEvent); } -void CoapSecure::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent) +void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent) { mConnectEventCallback.InvokeIfSet(aEvent); } -void CoapSecure::HandleDtlsAutoClose(void *aContext) +void CoapSecureBase::HandleDtlsAutoClose(void *aContext) { - return static_cast(aContext)->HandleDtlsAutoClose(); + return static_cast(aContext)->HandleDtlsAutoClose(); } -void CoapSecure::HandleDtlsAutoClose(void) +void CoapSecureBase::HandleDtlsAutoClose(void) { Stop(); mAutoStopCallback.InvokeIfSet(); } -void CoapSecure::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength) +void CoapSecureBase::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength) { - return static_cast(aContext)->HandleDtlsReceive(aBuf, aLength); + return static_cast(aContext)->HandleDtlsReceive(aBuf, aLength); } -void CoapSecure::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength) +void CoapSecureBase::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength) { ot::Message *message = nullptr; @@ -211,12 +211,12 @@ exit: FreeMessage(message); } -void CoapSecure::HandleTransmit(Tasklet &aTasklet) +void CoapSecureBase::HandleTransmit(Tasklet &aTasklet) { - static_cast(static_cast(aTasklet).GetContext())->HandleTransmit(); + static_cast(static_cast(aTasklet).GetContext())->HandleTransmit(); } -void CoapSecure::HandleTransmit(void) +void CoapSecureBase::HandleTransmit(void) { Error error = kErrorNone; ot::Message *message = mTransmitQueue.GetHead(); diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp index ad75d7ac4..07a0e5c9d 100644 --- a/src/core/coap/coap_secure.hpp +++ b/src/core/coap/coap_secure.hpp @@ -49,7 +49,7 @@ namespace ot { namespace Coap { -class CoapSecure : public CoapBase +class CoapSecureBase : public CoapBase { public: /** @@ -63,14 +63,6 @@ public: */ typedef otCoapSecureAutoStopCallback AutoStopCallback; - /** - * Initializes the object. - * - * @param[in] aInstance A reference to the OpenThread instance. - * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. - */ - explicit CoapSecure(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity); - /** * Starts the secure CoAP agent. * @@ -194,87 +186,6 @@ public: */ void SetPsk(const MeshCoP::JoinerPskd &aPskd); -#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE - -#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); } - -#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE - #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE /** * Sends a CoAP message over secure DTLS connection. @@ -381,13 +292,16 @@ public: */ const Ip6::MessageInfo &GetMessageInfo(void) const { return mDtls.GetMessageInfo(); } -private: +protected: + CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity); + Error Open(uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext); static Error Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { - return static_cast(aCoapBase).Send(aMessage, aMessageInfo); + return static_cast(aCoapBase).Send(aMessage, aMessageInfo); } + Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); static void HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext); @@ -409,6 +323,105 @@ private: TaskletContext mTransmitTask; }; +#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE + +/** + * Represents an Application CoAPS. + */ +class ApplicationCoapSecure : public CoapSecureBase +{ +public: + /** + * Initializes the object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. + */ + ApplicationCoapSecure(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) + : CoapSecureBase(aInstance, aLayerTwoSecurity) + { + } + +#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); } +}; + +#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE + } // namespace Coap } // namespace ot diff --git a/src/core/instance/instance.hpp b/src/core/instance/instance.hpp index 8c48a696f..7b48fa249 100644 --- a/src/core/instance/instance.hpp +++ b/src/core/instance/instance.hpp @@ -368,7 +368,7 @@ public: * * @returns A reference to the application COAP Secure object. */ - Coap::CoapSecure &GetApplicationCoapSecure(void) { return mApplicationCoapSecure; } + Coap::ApplicationCoapSecure &GetApplicationCoapSecure(void) { return mApplicationCoapSecure; } #endif #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE @@ -657,7 +657,7 @@ private: #endif #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE - Coap::CoapSecure mApplicationCoapSecure; + Coap::ApplicationCoapSecure mApplicationCoapSecure; #endif #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE diff --git a/src/core/thread/tmf.cpp b/src/core/thread/tmf.cpp index 9919dc097..2f470a3db 100644 --- a/src/core/thread/tmf.cpp +++ b/src/core/thread/tmf.cpp @@ -273,7 +273,7 @@ Message::Priority Agent::DscpToPriority(uint8_t aDscp) #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE SecureAgent::SecureAgent(Instance &aInstance) - : Coap::CoapSecure(aInstance, kNoLinkSecurity) + : Coap::CoapSecureBase(aInstance, kNoLinkSecurity) { SetResourceHandler(&HandleResource); } diff --git a/src/core/thread/tmf.hpp b/src/core/thread/tmf.hpp index d33a3e382..2a8b177c2 100644 --- a/src/core/thread/tmf.hpp +++ b/src/core/thread/tmf.hpp @@ -197,7 +197,7 @@ private: /** * Implements functionality of the secure TMF agent. */ -class SecureAgent : public Coap::CoapSecure +class SecureAgent : public Coap::CoapSecureBase { public: /**