1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for using mbedTLS.
32  */
33 
34 #ifndef SECURE_TRANSPORT_HPP_
35 #define SECURE_TRANSPORT_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #ifdef OPENTHREAD_CONFIG_TLS_API_ENABLE
40 #error `OPENTHREAD_CONFIG_TLS_API_ENABLE` must not be defined directly, it is determined from `COAP_SECURE_API_ENABLE` and `BLE_TCAT_ENABLE`
41 #endif
42 
43 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
44 #define OPENTHREAD_CONFIG_TLS_API_ENABLE 1
45 #else
46 #define OPENTHREAD_CONFIG_TLS_API_ENABLE 0
47 #endif
48 
49 #include <mbedtls/net_sockets.h>
50 #include <mbedtls/ssl.h>
51 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
52 #include <mbedtls/ssl_cookie.h>
53 #endif
54 #include <mbedtls/version.h>
55 
56 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
57 #ifndef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
58 #error OPENTHREAD_CONFIG_BLE_TCAT_ENABLE requires MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
59 #endif
60 #endif
61 
62 #if OPENTHREAD_CONFIG_TLS_API_ENABLE
63 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
64 #include <mbedtls/base64.h>
65 #endif
66 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
67 #include <mbedtls/x509.h>
68 #include <mbedtls/x509_crl.h>
69 #include <mbedtls/x509_crt.h>
70 #include <mbedtls/x509_csr.h>
71 #endif
72 #endif
73 
74 #include <openthread/coap_secure.h>
75 
76 #include "common/callback.hpp"
77 #include "common/linked_list.hpp"
78 #include "common/locator.hpp"
79 #include "common/log.hpp"
80 #include "common/message.hpp"
81 #include "common/non_copyable.hpp"
82 #include "common/random.hpp"
83 #include "common/timer.hpp"
84 #include "crypto/sha256.hpp"
85 #include "meshcop/meshcop.hpp"
86 #include "meshcop/meshcop_tlvs.hpp"
87 #include "net/socket.hpp"
88 #include "net/udp6.hpp"
89 
90 namespace ot {
91 
92 namespace MeshCoP {
93 
94 class SecureTransport;
95 class Dtls;
96 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
97 class Tls;
98 #endif
99 
100 /**
101  * Represents a secure session.
102  */
103 class SecureSession : private LinkedListEntry<SecureSession>, private NonCopyable
104 {
105     friend class LinkedListEntry<SecureSession>;
106     friend class LinkedList<SecureSession>;
107     friend class SecureTransport;
108     friend class Dtls;
109 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
110     friend class Tls;
111 #endif
112 
113 public:
114     typedef otCoapSecureConnectEvent ConnectEvent; ///< A connect event.
115 
116     static constexpr ConnectEvent kConnected               = OT_COAP_SECURE_CONNECTED;
117     static constexpr ConnectEvent kDisconnectedPeerClosed  = OT_COAP_SECURE_DISCONNECTED_PEER_CLOSED;
118     static constexpr ConnectEvent kDisconnectedLocalClosed = OT_COAP_SECURE_DISCONNECTED_LOCAL_CLOSED;
119     static constexpr ConnectEvent kDisconnectedMaxAttempts = OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS;
120     static constexpr ConnectEvent kDisconnectedError       = OT_COAP_SECURE_DISCONNECTED_ERROR;
121 
122     /**
123      * Function pointer which is called reporting a session connection event.
124      */
125     typedef otHandleCoapSecureClientConnect ConnectHandler;
126 
127     /**
128      * Pointer is called when data is received from the session.
129      *
130      * @param[in]  aContext  A pointer to application-specific context.
131      * @param[in]  aBuf      A pointer to the received data buffer.
132      * @param[in]  aLength   Number of bytes in the received data buffer.
133      */
134     typedef void (*ReceiveHandler)(void *aContext, uint8_t *aBuf, uint16_t aLength);
135 
136     /**
137      * Sets the connection event callback.
138      *
139      * @param[in]  aConnectHandler   A pointer to a function that is called when connected or disconnected.
140      * @param[in]  aContext          A pointer to arbitrary context information.
141      */
SetConnectCallback(ConnectHandler aConnectHandler,void * aContext)142     void SetConnectCallback(ConnectHandler aConnectHandler, void *aContext)
143     {
144         mConnectedCallback.Set(aConnectHandler, aContext);
145     }
146 
147     /**
148      * Sets the receive callback.
149      *
150      * @param[in]  aReceiveHandler      A pointer to a function that is called to receive payload.
151      * @param[in]  aContext             A pointer to arbitrary context information.
152      */
SetReceiveCallback(ReceiveHandler aReceiveHandler,void * aContext)153     void SetReceiveCallback(ReceiveHandler aReceiveHandler, void *aContext)
154     {
155         mReceiveCallback.Set(aReceiveHandler, aContext);
156     }
157 
158     /**
159      * Establishes a secure session (as client).
160      *
161      * On success, ownership of the session is passed to the associated secure transport (`GetTransport()`).
162      * The transport will then manage the session. Once the session is disconnected and removed from the transport, the
163      * secure transport signals this using the `RemoveSessionCallback` callback, where ownership is
164      * released.
165      *
166      * @param[in]  aSockAddr       The server address to connect to.
167      *
168      * @retval kErrorNone          Successfully started session establishment
169      * @retval kErrorInvalidState  Transport is not ready.
170      * @retval kErrorNoBufs        Has reached max number of allowed connection attempts.
171      */
172     Error Connect(const Ip6::SockAddr &aSockAddr);
173 
174     /**
175      * Disconnects the session.
176      */
Disconnect(void)177     void Disconnect(void) { Disconnect(kDisconnectedLocalClosed); }
178 
179     /**
180      * Sends message to the secure session.
181      *
182      * When successful (returning `kErrorNone`), this method takes over the ownership of @p aMessage and will free
183      * it after transmission. Otherwise, the caller keeps the ownership of @p aMessage.
184      *
185      * @param[in]  aMessage   A message to send.
186      *
187      * @retval kErrorNone     Successfully sent the message.
188      * @retval kErrorNoBufs   @p aMessage is too long.
189      */
190     Error Send(Message &aMessage);
191 
192     /**
193      * Returns the session's peer address.
194      *
195      * @return The session's message info.
196      */
GetMessageInfo(void) const197     const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
198 
199     /**
200      * Indicates whether or not the session is active (connected, connecting, or disconnecting).
201      *
202      * @retval TRUE  If session is active.
203      * @retval FALSE If session is not active.
204      */
IsConnectionActive(void) const205     bool IsConnectionActive(void) const { return (mState != kStateDisconnected); }
206 
207     /**
208      * Indicates whether or not the session is connected.
209      *
210      * @retval TRUE   The session is connected.
211      * @retval FALSE  The session is not connected.
212      */
IsConnected(void) const213     bool IsConnected(void) const { return (mState == kStateConnected); }
214 
215     /**
216      * Gets the `SecureTransport` used by this session.
217      *
218      * @return The `SecureTransport` instance associated with this session.
219      */
GetTransport(void)220     SecureTransport &GetTransport(void) { return mTransport; }
221 
222 protected:
223     explicit SecureSession(SecureTransport &aTransport);
224 
IsSessionInUse(void) const225     bool IsSessionInUse(void) const { return (mNext != this); }
226 
227 private:
228     static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
229     static constexpr uint16_t kMaxContentLen               = OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN;
230 
231 #if !OPENTHREAD_CONFIG_TLS_API_ENABLE
232     static constexpr uint16_t kApplicationDataMaxLength = 1152;
233 #else
234     static constexpr uint16_t         kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
235 #endif
236 
237     enum State : uint8_t
238     {
239         kStateDisconnected,
240         kStateInitializing,
241         kStateConnecting,
242         kStateConnected,
243         kStateDisconnecting,
244     };
245 
246     void  Init(void);
IsDisconnected(void) const247     bool  IsDisconnected(void) const { return mState == kStateDisconnected; }
IsInitializing(void) const248     bool  IsInitializing(void) const { return mState == kStateInitializing; }
IsConnecting(void) const249     bool  IsConnecting(void) const { return mState == kStateConnecting; }
IsDisconnecting(void) const250     bool  IsDisconnecting(void) const { return mState == kStateDisconnecting; }
IsConnectingOrConnected(void) const251     bool  IsConnectingOrConnected(void) const { return mState == kStateConnecting || mState == kStateConnected; }
MarkAsNotUsed(void)252     void  MarkAsNotUsed(void) { mNext = this; }
253     void  SetState(State aState);
Matches(const Ip6::MessageInfo & aInfo) const254     bool  Matches(const Ip6::MessageInfo &aInfo) const { return mMessageInfo.HasSamePeerAddrAndPort(aInfo); }
Matches(State aState) const255     bool  Matches(State aState) const { return (mState == aState); }
256     void  Accept(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
257     void  HandleTransportReceive(Message &aMessage);
258     Error Setup(void);
259     void  Disconnect(ConnectEvent aEvent);
260     void  HandleTimer(TimeMilli aNow);
261     void  Process(void);
262     void  FreeMbedtls(void);
263 
264     static int  HandleMbedtlsGetTimer(void *aContext);
265     int         HandleMbedtlsGetTimer(void);
266     static void HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish);
267     void        HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish);
268     static int  HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength);
269     int         HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength);
270     static int  HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength);
271     int         HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength);
272 
273     static bool IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext);
274 
275 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
276     static const char *StateToString(State aState);
277 #endif
278 
279     bool                     mTimerSet : 1;
280     bool                     mIsServer : 1;
281     State                    mState;
282     Message::SubType         mMessageSubType;
283     ConnectEvent             mConnectEvent;
284     TimeMilli                mTimerIntermediate;
285     TimeMilli                mTimerFinish;
286     SecureSession           *mNext;
287     SecureTransport         &mTransport;
288     Message                 *mReceiveMessage;
289     Ip6::MessageInfo         mMessageInfo;
290     Callback<ConnectHandler> mConnectedCallback;
291     Callback<ReceiveHandler> mReceiveCallback;
292     mbedtls_ssl_config       mConf;
293     mbedtls_ssl_context      mSsl;
294 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
295     mbedtls_ssl_cookie_ctx mCookieCtx;
296 #endif
297 };
298 
299 /**
300  * Represents a secure transport, used as base class for `Dtls` and `Tls`.
301  */
302 class SecureTransport : private NonCopyable
303 {
304     friend class SecureSession;
305 
306 public:
307     static constexpr uint8_t kPskMaxLength = 32; ///< Maximum PSK length.
308 
309     /**
310      * Pointer is called to send encrypted message.
311      *
312      * @param[in]  aContext      A pointer to arbitrary context information.
313      * @param[in]  aMessage      A reference to the message to send.
314      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
315      */
316     typedef Error (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
317 
318     /**
319      * Callback to notify when the socket is automatically closed due to reaching the maximum number of connection
320      * attempts (set from `SetMaxConnectionAttempts()`).
321      *
322      * @param[in] aContext    A pointer to arbitrary context information.
323      */
324     typedef void (*AutoCloseCallback)(void *aContext);
325 
326     /**
327      * Callback to accept a new session connection request, providing the secure session to use.
328      *
329      * This method returns a pointer to a new `SecureSession` to use for the new session. The `SecureTransport` takes
330      * over the ownership of the given `SecureSession`. Once the session is disconnected and removed from the transport,
331      * the secure transport signals this using the `RemoveSessionCallback` callback, where ownership is released.
332      *
333      * `nullptr` can be returned to reject the new session connection request.
334      *
335      * @param[in] aContex       A pointer to arbitrary context information.
336      * @param[in] aMessageInfo  The message info from the new session connection request message.
337      *
338      * @returns A pointer to `SecureSession` to use for new session or `nullptr` if new connection is rejected.
339      */
340     typedef SecureSession *(*AcceptCallback)(void *aContext, const Ip6::MessageInfo &aMessageInfo);
341 
342     /**
343      * Callback to signal a session is removed, releasing the ownership of the session (by `SecureTransport`).
344      *
345      * @param[in] aContex       A pointer to arbitrary context information.
346      * @param[in] aSesssion     The session being removed.
347      */
348     typedef void (*RemoveSessionCallback)(void *aContext, SecureSession &aSesssion);
349 
350 #if OPENTHREAD_CONFIG_TLS_API_ENABLE
351     /**
352      * Represents an API extension for a `SecureTransport` (DTLS or TLS).
353      *
354      * The `Extension` provides support for additional cipher suites along with related methods to configure them.
355      * This class decouples this functionality from the common `SecureTransport` object, allowing this to be added
356      * to any class.
357      *
358      * The general pattern to use the `Extension` class is to have it be inherited by classes that want to provide the
359      * same methods for configuring ciphers (e.g. `SetPreSharedKey()` or `SetCertificate()`). An `Extension` should
360      * then be associated with a `SecureTransport` (or any of its subclasses).
361      */
362     class Extension
363     {
364         friend SecureTransport;
365         friend SecureSession;
366 
367     public:
368 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
369         /**
370          * Sets the Pre-Shared Key (PSK) for sessions-identified by a PSK.
371          *
372          * DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS.
373          *
374          * @param[in]  aPsk          A pointer to the PSK.
375          * @param[in]  aPskLength    The PSK char length.
376          * @param[in]  aPskIdentity  The Identity Name for the PSK.
377          * @param[in]  aPskIdLength  The PSK Identity Length.
378          */
379         void SetPreSharedKey(const uint8_t *aPsk,
380                              uint16_t       aPskLength,
381                              const uint8_t *aPskIdentity,
382                              uint16_t       aPskIdLength);
383 #endif
384 
385 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
386         /**
387          * Sets a reference to the own x509 certificate with corresponding private key.
388          *
389          * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
390          *
391          * @param[in]  aX509Certificate   A pointer to the PEM formatted X509 certificate.
392          * @param[in]  aX509CertLength    The length of certificate.
393          * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
394          * @param[in]  aPrivateKeyLength  The length of the private key.
395          */
396         void SetCertificate(const uint8_t *aX509Certificate,
397                             uint32_t       aX509CertLength,
398                             const uint8_t *aPrivateKey,
399                             uint32_t       aPrivateKeyLength);
400 
401         /**
402          * Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
403          *
404          * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
405          *
406          * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
407          * @param[in]  aX509CaCertChainLength   The length of chain.
408          */
409         void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength);
410 
411         /**
412          * Extracts public key from it's own certificate.
413          *
414          * @returns Public key from own certificate in form of entire ASN.1 field.
415          */
GetOwnPublicKey(void) const416         const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mEcdheEcdsaInfo.mOwnCert.pk_raw; }
417 
418 #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
419 
420 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
421         /**
422          * Returns the peer x509 certificate base64 encoded.
423          *
424          * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
425          *
426          * @param[out]  aPeerCert        A pointer to the base64 encoded certificate buffer.
427          * @param[out]  aCertLength      The length of the base64 encoded peer certificate.
428          * @param[in]   aCertBufferSize  The buffer size of aPeerCert.
429          *
430          * @retval kErrorInvalidState   Not connected yet.
431          * @retval kErrorNone           Successfully get the peer certificate.
432          * @retval kErrorNoBufs         Can't allocate memory for certificate.
433          */
434         Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);
435 #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
436 
437 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
438         /**
439          * Returns an attribute value identified by its OID from the subject
440          * of the peer x509 certificate. The peer OID is provided in binary format.
441          * The attribute length is set if the attribute was successfully read or zero
442          * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
443          * if the attribute was successfully read.
444          *
445          * @param[in]     aOid                A pointer to the OID to be found.
446          * @param[in]     aOidLength          The length of the OID.
447          * @param[out]    aAttributeBuffer    A pointer to the attribute buffer.
448          * @param[in,out] aAttributeLength    On input, the size the max size of @p aAttributeBuffer.
449          *                                    On output, the length of the attribute written to the buffer.
450          * @param[out]    aAsn1Type           A pointer to the ASN.1 type of the attribute written to the buffer.
451          *
452          * @retval kErrorInvalidState   Not connected yet.
453          * @retval kErrorInvalidArgs    Invalid attribute length.
454          * @retval kErrorNone           Successfully read attribute.
455          * @retval kErrorNoBufs         Insufficient memory for storing the attribute value.
456          */
457         Error GetPeerSubjectAttributeByOid(const char *aOid,
458                                            size_t      aOidLength,
459                                            uint8_t    *aAttributeBuffer,
460                                            size_t     *aAttributeLength,
461                                            int        *aAsn1Type);
462 
463         /**
464          * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
465          * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
466          * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
467          * Requires a connection to be active.
468          *
469          * @param[in]      aThreadOidDescriptor  The last digit of the Thread attribute OID.
470          * @param[out]     aAttributeBuffer      A pointer to the attribute buffer.
471          * @param[in,out]  aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
472          *                                           On output, the length of the attribute written to the buffer.
473          *
474          * @retval kErrorNone             Successfully read attribute.
475          * @retval kErrorInvalidArgs      Invalid attribute length.
476          * @retval kErrorNotFound         The requested attribute was not found.
477          * @retval kErrorNoBufs           Insufficient memory for storing the attribute value.
478          * @retval kErrorInvalidState     Not connected yet.
479          * @retval kErrorNotImplemented   The value of aThreadOidDescriptor is >127.
480          * @retval kErrorParse            The certificate extensions could not be parsed.
481          */
482         Error GetThreadAttributeFromPeerCertificate(int      aThreadOidDescriptor,
483                                                     uint8_t *aAttributeBuffer,
484                                                     size_t  *aAttributeLength);
485 #endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
486 
487         /**
488          * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
489          * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
490          * The attribute length is set if the attribute was successfully read or zero if unsuccessful.
491          * Requires a connection to be active.
492          *
493          * @param[in]      aThreadOidDescriptor  The last digit of the Thread attribute OID.
494          * @param[out]     aAttributeBuffer      A pointer to the attribute buffer.
495          * @param[in,out]  aAttributeLength      On input, the size the max size of @p aAttributeBuffer.
496          *                                       On output, the length of the attribute written to the buffer.
497          *
498          * @retval kErrorNone             Successfully read attribute.
499          * @retval kErrorInvalidArgs      Invalid attribute length.
500          * @retval kErrorNotFound         The requested attribute was not found.
501          * @retval kErrorNoBufs           Insufficient memory for storing the attribute value.
502          * @retval kErrorInvalidState     Not connected yet.
503          * @retval kErrorNotImplemented   The value of aThreadOidDescriptor is >127.
504          * @retval kErrorParse            The certificate extensions could not be parsed.
505          */
506         Error GetThreadAttributeFromOwnCertificate(int      aThreadOidDescriptor,
507                                                    uint8_t *aAttributeBuffer,
508                                                    size_t  *aAttributeLength);
509 
510         /**
511          * Set the authentication mode for a connection.
512          *
513          * Disable or enable the verification of peer certificate.
514          * Must called before start.
515          *
516          * @param[in]  aVerifyPeerCertificate  true, if the peer certificate should verify.
517          */
SetSslAuthMode(bool aVerifyPeerCertificate)518         void SetSslAuthMode(bool aVerifyPeerCertificate)
519         {
520             mSecureTransport.mVerifyPeerCertificate = aVerifyPeerCertificate;
521         }
522 
523     protected:
Extension(SecureTransport & aSecureTransport)524         explicit Extension(SecureTransport &aSecureTransport)
525             : mSecureTransport(aSecureTransport)
526         {
527         }
528 
529     private:
530 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
531         struct EcdheEcdsaInfo : public Clearable<EcdheEcdsaInfo>
532         {
EcdheEcdsaInfoot::MeshCoP::SecureTransport::Extension::EcdheEcdsaInfo533             EcdheEcdsaInfo(void) { Clear(); }
534             void Init(void);
535             void Free(void);
536             int  SetSecureKeys(mbedtls_ssl_config &aConfig);
537 
538             const uint8_t     *mCaChainSrc;
539             const uint8_t     *mOwnCertSrc;
540             const uint8_t     *mPrivateKeySrc;
541             uint32_t           mOwnCertLength;
542             uint32_t           mCaChainLength;
543             uint32_t           mPrivateKeyLength;
544             mbedtls_x509_crt   mCaChain;
545             mbedtls_x509_crt   mOwnCert;
546             mbedtls_pk_context mPrivateKey;
547         };
548 #endif
549 
550 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
551         struct PskInfo : public Clearable<PskInfo>
552         {
PskInfoot::MeshCoP::SecureTransport::Extension::PskInfo553             PskInfo(void) { Clear(); }
554             int SetSecureKeys(mbedtls_ssl_config &aConfig) const;
555 
556             const uint8_t *mPreSharedKey;
557             const uint8_t *mPreSharedKeyIdentity;
558             uint16_t       mPreSharedKeyLength;
559             uint16_t       mPreSharedKeyIdLength;
560         };
561 #endif
562 
563         int   SetApplicationSecureKeys(mbedtls_ssl_config &aConfig);
564         Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
565                                                 int                     aThreadOidDescriptor,
566                                                 uint8_t                *aAttributeBuffer,
567                                                 size_t                 *aAttributeLength);
568 
569         SecureTransport &mSecureTransport;
570 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
571         EcdheEcdsaInfo mEcdheEcdsaInfo;
572 #endif
573 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
574         PskInfo mPskInfo;
575 #endif
576     };
577 #endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
578 
579     /**
580      * Opens the transport.
581      *
582      * @retval kErrorNone     Successfully opened the socket.
583      * @retval kErrorAlready  The connection is already open.
584      */
585     Error Open(void);
586 
587     /**
588      * Sets the maximum number of allowed connection requests before socket is automatically closed.
589      *
590      * This method can be called when socket is closed. Otherwise `kErrorInvalidSatet` is returned.
591      *
592      * If @p aMaxAttempts is zero, no limit is applied and connections are allowed until the socket is closed. This is
593      * the default behavior if `SetMaxConnectionAttempts()` is not called.
594      *
595      * @param[in] aMaxAttempts    Maximum number of allowed connection attempts.
596      * @param[in] aCallback       Callback to notify when max number of attempts has reached and socket is closed.
597      * @param[in] aContext        A pointer to arbitrary context to use with `AutoCloseCallback`.
598      *
599      * @retval kErrorNone          Successfully set the maximum allowed connection attempts and callback.
600      * @retval kErrorInvalidState  Socket is not closed.
601      */
602     Error SetMaxConnectionAttempts(uint16_t aMaxAttempts, AutoCloseCallback aCallback, void *aContext);
603 
604     /**
605      * Sets the `AcceptCallback` used to accept new session connection requests.
606      *
607      * @param[in] aCallback   The `AcceptCallback`.
608      * @param[in] aConext     A pointer to arbitrary context to use with `AcceptCallback`.
609      */
SetAcceptCallback(AcceptCallback aCallback,void * aContext)610     void SetAcceptCallback(AcceptCallback aCallback, void *aContext) { mAcceptCallback.Set(aCallback, aContext); }
611 
612     /**
613      * Sets the `RemoveSessionCallback` used to signal when a session is removed.
614      *
615      * @param[in] aCallback   The `RemoveSessionCallback`.
616      * @param[in] aConext     A pointer to arbitrary context to use with `RemoveSessionCallback`.
617      */
SetRemoveSessionCallback(RemoveSessionCallback aCallback,void * aContext)618     void SetRemoveSessionCallback(RemoveSessionCallback aCallback, void *aContext)
619     {
620         mRemoveSessionCallback.Set(aCallback, aContext);
621     }
622 
623     /**
624      * Binds this DTLS to a UDP port.
625      *
626      * @param[in]  aPort              The port to bind.
627      *
628      * @retval kErrorNone           Successfully bound the socket.
629      * @retval kErrorInvalidState   The socket is not open.
630      * @retval kErrorAlready        Already bound.
631      */
632     Error Bind(uint16_t aPort);
633 
634     /**
635      * Gets the UDP port of this session.
636      *
637      * @returns  UDP port number.
638      */
GetUdpPort(void) const639     uint16_t GetUdpPort(void) const { return mSocket.GetSockName().GetPort(); }
640 
641     /**
642      * Binds with a transport callback.
643      *
644      * @param[in]  aCallback  A pointer to a function for sending messages.
645      * @param[in]  aContext   A pointer to arbitrary context information.
646      *
647      * @retval kErrorNone           Successfully bound the socket.
648      * @retval kErrorInvalidState   The socket is not open.
649      * @retval kErrorAlready        Already bound.
650      */
651     Error Bind(TransportCallback aCallback, void *aContext);
652 
653     /**
654      * Indicates whether or not the secure transpose socket is closed.
655      *
656      * @retval TRUE   The secure transport socket closed.
657      * @retval FALSE  The secure transport socket is not closed.
658      */
IsClosed(void) const659     bool IsClosed(void) const { return !mIsOpen; }
660 
661     /**
662      * Closes the socket.
663      */
664     void Close(void);
665 
666     /**
667      * Sets the PSK.
668      *
669      * @param[in]  aPsk  A pointer to the PSK.
670      *
671      * @retval kErrorNone          Successfully set the PSK.
672      * @retval kErrorInvalidArgs   The PSK is invalid.
673      */
674     Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
675 
676     /**
677      * Sets the PSK.
678      *
679      * @param[in]  aPskd  A Joiner PSKd.
680      */
681     void SetPsk(const JoinerPskd &aPskd);
682 
683     /**
684      * Checks and handles a received message provided to the SecureTransport object. If checks based on
685      * the message info and current connection state pass, the message is processed.
686      *
687      * @param[in]  aMessage  A reference to the message to receive.
688      * @param[in]  aMessageInfo A reference to the message info associated with @p aMessage.
689      */
690     void HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
691 
692     /**
693      * Get the list of sessions associated with the `SecureTransport`.
694      *
695      * @returns The list of associated sessions.
696      */
GetSessions(void)697     LinkedList<SecureSession> &GetSessions(void) { return mSessions; }
698 
699 protected:
700     SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport);
701 
702 #if OPENTHREAD_CONFIG_TLS_API_ENABLE
SetExtension(Extension & aExtension)703     void SetExtension(Extension &aExtension) { mExtension = &aExtension; }
704 #endif
705 
706 private:
707     static constexpr size_t kSecureTransportKeyBlockSize     = 40;
708     static constexpr size_t kSecureTransportRandomBufferSize = 32;
709 
710     enum CipherSuite : uint8_t
711     {
712         kEcjpakeWithAes128Ccm8,
713 #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
714         kPskWithAes128Ccm8,
715 #endif
716 #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
717         kEcdheEcdsaWithAes128Ccm8,
718         kEcdheEcdsaWithAes128GcmSha256,
719 #endif
720         kUnspecifiedCipherSuite,
721     };
722 
723     void RemoveDisconnectedSessions(void);
724     void DecremenetRemainingConnectionAttempts(void);
725     bool HasNoRemainingConnectionAttempts(void) const;
726     int  Transmit(const unsigned char    *aBuf,
727                   size_t                  aLength,
728                   const Ip6::MessageInfo &aMessageInfo,
729                   Message::SubType        aMessageSubType);
730 
731     static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
732     void        HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr);
733 
734 #ifdef MBEDTLS_SSL_EXPORT_KEYS
735 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
736 
737     static void HandleMbedtlsExportKeys(void                       *aContext,
738                                         mbedtls_ssl_key_export_type aType,
739                                         const unsigned char        *aMasterSecret,
740                                         size_t                      aMasterSecretLen,
741                                         const unsigned char         aClientRandom[32],
742                                         const unsigned char         aServerRandom[32],
743                                         mbedtls_tls_prf_types       aTlsPrfType);
744 
745     void HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType,
746                                  const unsigned char        *aMasterSecret,
747                                  size_t                      aMasterSecretLen,
748                                  const unsigned char         aClientRandom[32],
749                                  const unsigned char         aServerRandom[32],
750                                  mbedtls_tls_prf_types       aTlsPrfType);
751 
752 #else
753 
754     static int       HandleMbedtlsExportKeys(void                *aContext,
755                                              const unsigned char *aMasterSecret,
756                                              const unsigned char *aKeyBlock,
757                                              size_t               aMacLength,
758                                              size_t               aKeyLength,
759                                              size_t               aIvLength);
760     int              HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
761                                              const unsigned char *aKeyBlock,
762                                              size_t               aMacLength,
763                                              size_t               aKeyLength,
764                                              size_t               aIvLength);
765 
766 #endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000)
767 #endif // MBEDTLS_SSL_EXPORT_KEYS
768 
769     static void HandleUpdateTask(Tasklet &aTasklet);
770     void        HandleUpdateTask(void);
771     static void HandleTimer(Timer &aTimer);
772     void        HandleTimer(void);
773 
774     using TransportSocket = Ip6::Udp::SocketIn<SecureTransport, &SecureTransport::HandleReceive>;
775 
776 #if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
777     static const uint16_t kGroups[];
778 #else
779     static const mbedtls_ecp_group_id kCurves[];
780 #endif
781 
782 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
783 #if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
784     static const uint16_t kSignatures[];
785 #else
786     static const int kHashes[];
787 #endif
788 #endif
789 
790     static const int kCipherSuites[][2];
791 
792     bool                            mLayerTwoSecurity : 1;
793     bool                            mDatagramTransport : 1;
794     bool                            mIsOpen : 1;
795     bool                            mIsClosing : 1;
796     bool                            mVerifyPeerCertificate : 1;
797     CipherSuite                     mCipherSuite;
798     uint8_t                         mPskLength;
799     uint16_t                        mMaxConnectionAttempts;
800     uint16_t                        mRemainingConnectionAttempts;
801     LinkedList<SecureSession>       mSessions;
802     TransportSocket                 mSocket;
803     uint8_t                         mPsk[kPskMaxLength];
804     TimerMilliContext               mTimer;
805     TaskletContext                  mUpdateTask;
806     Callback<AutoCloseCallback>     mAutoCloseCallback;
807     Callback<AcceptCallback>        mAcceptCallback;
808     Callback<RemoveSessionCallback> mRemoveSessionCallback;
809     Callback<TransportCallback>     mTransportCallback;
810 #if OPENTHREAD_CONFIG_TLS_API_ENABLE
811     Extension *mExtension;
812 #endif
813 };
814 
815 /**
816  * Defines DTLS `Transport` and `Session`.
817  */
818 class Dtls
819 {
820 public:
821     class Session;
822 
823     /**
824      * Represents a DTLS transport.
825      */
826     class Transport : public SecureTransport
827     {
828         friend class Session;
829 
830     public:
831         /**
832          * Initializes the `Dtls::Transport` object.
833          *
834          * @param[in]  aInstance            A reference to the OpenThread instance.
835          * @param[in]  aLayerTwoSecurity    Specifies whether to use layer two security or not.
836          */
Transport(Instance & aInstance,LinkSecurityMode aLayerTwoSecurity)837         Transport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity)
838             : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ true)
839         {
840         }
841     };
842 
843     /**
844      * Represents a DTLS session.
845      */
846     class Session : public SecureSession
847     {
848     public:
849         /**
850          * Initializes the `Dtls::Session` object.
851          *
852          * @param[in] aTransport  The DTLS transport to use for this session.
853          */
Session(Transport & aTransport)854         Session(Transport &aTransport)
855             : SecureSession(aTransport)
856         {
857         }
858 
859         /**
860          * Returns the DTLS transport used by this session.
861          *
862          * @returns The DTLS transport associated with this session.
863          */
GetTransport(void)864         Transport &GetTransport(void) { return static_cast<Transport &>(SecureSession::GetTransport()); }
865     };
866 };
867 
868 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
869 
870 /**
871  * Represents a TLS instance.
872  */
873 class Tls : public SecureTransport, public SecureSession
874 {
875 public:
876     /**
877      * Initializes the `Tls` object.
878      *
879      * @param[in]  aInstance            A reference to the OpenThread instance.
880      * @param[in]  aLayerTwoSecurity    Specifies whether to use layer two security or not.
881      * @param[in]  aExtension           An extension providing additional configuration methods.
882      */
Tls(Instance & aInstance,LinkSecurityMode aLayerTwoSecurity,Extension & aExtension)883     Tls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension)
884         : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ false)
885         , SecureSession(*static_cast<SecureTransport *>(this))
886     {
887         SetExtension(aExtension);
888         SetAcceptCallback(&HandleAccept, this);
889     }
890 
891 private:
892     static SecureSession *HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo);
893     SecureSession        *HandleAccept(void);
894 };
895 
896 #endif
897 
898 } // namespace MeshCoP
899 } // namespace ot
900 
901 #endif // SECURE_TRANSPORT_HPP_
902