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 : public 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 the DER encoded peer x509 certificate. 440 * 441 * @param[out] aPeerCert A pointer to the DER encoded certificate buffer. 442 * @param[out] aCertLength The length of the DER encoded peer certificate. 443 * @param[in] aCertBufferSize The buffer size of aPeerCert. 444 * 445 * @retval kErrorInvalidState Not connected yet. 446 * @retval kErrorNone Successfully get the peer certificate. 447 * @retval kErrorNoBufs Can't allocate memory for certificate. 448 */ 449 Error GetPeerCertificateDer(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize); 450 451 /** 452 * Returns an attribute value identified by its OID from the subject 453 * of the peer x509 certificate. The peer OID is provided in binary format. 454 * The attribute length is set if the attribute was successfully read or zero 455 * if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard 456 * if the attribute was successfully read. 457 * 458 * @param[in] aOid A pointer to the OID to be found. 459 * @param[in] aOidLength The length of the OID. 460 * @param[out] aAttributeBuffer A pointer to the attribute buffer. 461 * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. 462 * On output, the length of the attribute written to the buffer. 463 * @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer. 464 * 465 * @retval kErrorInvalidState Not connected yet. 466 * @retval kErrorInvalidArgs Invalid attribute length. 467 * @retval kErrorNone Successfully read attribute. 468 * @retval kErrorNoBufs Insufficient memory for storing the attribute value. 469 */ 470 Error GetPeerSubjectAttributeByOid(const char *aOid, 471 size_t aOidLength, 472 uint8_t *aAttributeBuffer, 473 size_t *aAttributeLength, 474 int *aAsn1Type); 475 476 /** 477 * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of 478 * the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor. 479 * The attribute length is set if the attribute was successfully read or zero if unsuccessful. 480 * Requires a connection to be active. 481 * 482 * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. 483 * @param[out] aAttributeBuffer A pointer to the attribute buffer. 484 * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. 485 * On output, the length of the attribute written to the buffer. 486 * 487 * @retval kErrorNone Successfully read attribute. 488 * @retval kErrorInvalidArgs Invalid attribute length. 489 * @retval kErrorNotFound The requested attribute was not found. 490 * @retval kErrorNoBufs Insufficient memory for storing the attribute value. 491 * @retval kErrorInvalidState Not connected yet. 492 * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. 493 * @retval kErrorParse The certificate extensions could not be parsed. 494 */ 495 Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, 496 uint8_t *aAttributeBuffer, 497 size_t *aAttributeLength); 498 #endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) 499 500 /** 501 * Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of 502 * the own x509 certificate, where the last digit x is set to aThreadOidDescriptor. 503 * The attribute length is set if the attribute was successfully read or zero if unsuccessful. 504 * Requires a connection to be active. 505 * 506 * @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID. 507 * @param[out] aAttributeBuffer A pointer to the attribute buffer. 508 * @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer. 509 * On output, the length of the attribute written to the buffer. 510 * 511 * @retval kErrorNone Successfully read attribute. 512 * @retval kErrorInvalidArgs Invalid attribute length. 513 * @retval kErrorNotFound The requested attribute was not found. 514 * @retval kErrorNoBufs Insufficient memory for storing the attribute value. 515 * @retval kErrorInvalidState Not connected yet. 516 * @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127. 517 * @retval kErrorParse The certificate extensions could not be parsed. 518 */ 519 Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, 520 uint8_t *aAttributeBuffer, 521 size_t *aAttributeLength); 522 523 /** 524 * Set the authentication mode for a connection. 525 * 526 * Disable or enable the verification of peer certificate. 527 * Must called before start. 528 * 529 * @param[in] aVerifyPeerCertificate true, if the peer certificate should verify. 530 */ SetSslAuthMode(bool aVerifyPeerCertificate)531 void SetSslAuthMode(bool aVerifyPeerCertificate) 532 { 533 mSecureTransport.mVerifyPeerCertificate = aVerifyPeerCertificate; 534 } 535 536 protected: Extension(SecureTransport & aSecureTransport)537 explicit Extension(SecureTransport &aSecureTransport) 538 : mSecureTransport(aSecureTransport) 539 { 540 } 541 542 private: 543 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) 544 struct EcdheEcdsaInfo : public Clearable<EcdheEcdsaInfo> 545 { EcdheEcdsaInfoot::MeshCoP::SecureTransport::Extension::EcdheEcdsaInfo546 EcdheEcdsaInfo(void) { Clear(); } 547 void Init(void); 548 void Free(void); 549 int SetSecureKeys(mbedtls_ssl_config &aConfig); 550 551 const uint8_t *mCaChainSrc; 552 const uint8_t *mOwnCertSrc; 553 const uint8_t *mPrivateKeySrc; 554 uint32_t mOwnCertLength; 555 uint32_t mCaChainLength; 556 uint32_t mPrivateKeyLength; 557 mbedtls_x509_crt mCaChain; 558 mbedtls_x509_crt mOwnCert; 559 mbedtls_pk_context mPrivateKey; 560 }; 561 #endif 562 563 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) 564 struct PskInfo : public Clearable<PskInfo> 565 { PskInfoot::MeshCoP::SecureTransport::Extension::PskInfo566 PskInfo(void) { Clear(); } 567 int SetSecureKeys(mbedtls_ssl_config &aConfig) const; 568 569 const uint8_t *mPreSharedKey; 570 const uint8_t *mPreSharedKeyIdentity; 571 uint16_t mPreSharedKeyLength; 572 uint16_t mPreSharedKeyIdLength; 573 }; 574 #endif 575 576 int SetApplicationSecureKeys(mbedtls_ssl_config &aConfig); 577 Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, 578 int aThreadOidDescriptor, 579 uint8_t *aAttributeBuffer, 580 size_t *aAttributeLength); 581 582 SecureTransport &mSecureTransport; 583 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) 584 EcdheEcdsaInfo mEcdheEcdsaInfo; 585 #endif 586 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) 587 PskInfo mPskInfo; 588 #endif 589 }; 590 #endif // OPENTHREAD_CONFIG_TLS_API_ENABLE 591 592 /** 593 * Opens the transport. 594 * 595 * @param[in] aNetifIdentifier A network interface identifier. If not explicitly provided, kNetifUnspecified will 596 * be used by default. 597 * 598 * @retval kErrorNone Successfully opened the socket. 599 * @retval kErrorAlready The connection is already open. 600 */ 601 Error Open(Ip6::NetifIdentifier aNetifIdentifier = Ip6::NetifIdentifier::kNetifUnspecified); 602 603 /** 604 * Sets the maximum number of allowed connection requests before socket is automatically closed. 605 * 606 * This method can be called when socket is closed. Otherwise `kErrorInvalidSatet` is returned. 607 * 608 * If @p aMaxAttempts is zero, no limit is applied and connections are allowed until the socket is closed. This is 609 * the default behavior if `SetMaxConnectionAttempts()` is not called. 610 * 611 * @param[in] aMaxAttempts Maximum number of allowed connection attempts. 612 * @param[in] aCallback Callback to notify when max number of attempts has reached and socket is closed. 613 * @param[in] aContext A pointer to arbitrary context to use with `AutoCloseCallback`. 614 * 615 * @retval kErrorNone Successfully set the maximum allowed connection attempts and callback. 616 * @retval kErrorInvalidState Socket is not closed. 617 */ 618 Error SetMaxConnectionAttempts(uint16_t aMaxAttempts, AutoCloseCallback aCallback, void *aContext); 619 620 /** 621 * Sets the `AcceptCallback` used to accept new session connection requests. 622 * 623 * @param[in] aCallback The `AcceptCallback`. 624 * @param[in] aConext A pointer to arbitrary context to use with `AcceptCallback`. 625 */ SetAcceptCallback(AcceptCallback aCallback,void * aContext)626 void SetAcceptCallback(AcceptCallback aCallback, void *aContext) { mAcceptCallback.Set(aCallback, aContext); } 627 628 /** 629 * Sets the `RemoveSessionCallback` used to signal when a session is removed. 630 * 631 * @param[in] aCallback The `RemoveSessionCallback`. 632 * @param[in] aConext A pointer to arbitrary context to use with `RemoveSessionCallback`. 633 */ SetRemoveSessionCallback(RemoveSessionCallback aCallback,void * aContext)634 void SetRemoveSessionCallback(RemoveSessionCallback aCallback, void *aContext) 635 { 636 mRemoveSessionCallback.Set(aCallback, aContext); 637 } 638 639 /** 640 * Binds this DTLS to a UDP port. 641 * 642 * @param[in] aPort The port to bind. 643 * 644 * @retval kErrorNone Successfully bound the socket. 645 * @retval kErrorInvalidState The socket is not open. 646 * @retval kErrorAlready Already bound. 647 */ 648 Error Bind(uint16_t aPort); 649 650 /** 651 * Gets the UDP port of this session. 652 * 653 * @returns UDP port number. 654 */ GetUdpPort(void) const655 uint16_t GetUdpPort(void) const { return mSocket.GetSockName().GetPort(); } 656 657 /** 658 * Binds with a transport callback. 659 * 660 * @param[in] aCallback A pointer to a function for sending messages. 661 * @param[in] aContext A pointer to arbitrary context information. 662 * 663 * @retval kErrorNone Successfully bound the socket. 664 * @retval kErrorInvalidState The socket is not open. 665 * @retval kErrorAlready Already bound. 666 */ 667 Error Bind(TransportCallback aCallback, void *aContext); 668 669 /** 670 * Indicates whether or not the secure transpose socket is closed. 671 * 672 * @retval TRUE The secure transport socket closed. 673 * @retval FALSE The secure transport socket is not closed. 674 */ IsClosed(void) const675 bool IsClosed(void) const { return !mIsOpen; } 676 677 /** 678 * Closes the socket. 679 */ 680 void Close(void); 681 682 /** 683 * Sets the PSK. 684 * 685 * @param[in] aPsk A pointer to the PSK. 686 * 687 * @retval kErrorNone Successfully set the PSK. 688 * @retval kErrorInvalidArgs The PSK is invalid. 689 */ 690 Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength); 691 692 /** 693 * Sets the PSK. 694 * 695 * @param[in] aPskd A Joiner PSKd. 696 */ 697 void SetPsk(const JoinerPskd &aPskd); 698 699 /** 700 * Checks and handles a received message provided to the SecureTransport object. If checks based on 701 * the message info and current connection state pass, the message is processed. 702 * 703 * @param[in] aMessage A reference to the message to receive. 704 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 705 */ 706 void HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 707 708 /** 709 * Get the list of sessions associated with the `SecureTransport`. 710 * 711 * @returns The list of associated sessions. 712 */ GetSessions(void)713 LinkedList<SecureSession> &GetSessions(void) { return mSessions; } 714 715 protected: 716 SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport); 717 718 #if OPENTHREAD_CONFIG_TLS_API_ENABLE SetExtension(Extension & aExtension)719 void SetExtension(Extension &aExtension) { mExtension = &aExtension; } 720 #endif 721 722 private: 723 static constexpr size_t kSecureTransportKeyBlockSize = 40; 724 static constexpr size_t kSecureTransportRandomBufferSize = 32; 725 726 enum CipherSuite : uint8_t 727 { 728 kEcjpakeWithAes128Ccm8, 729 #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) 730 kPskWithAes128Ccm8, 731 #endif 732 #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) 733 kEcdheEcdsaWithAes128Ccm8, 734 kEcdheEcdsaWithAes128GcmSha256, 735 #endif 736 kUnspecifiedCipherSuite, 737 }; 738 739 void RemoveDisconnectedSessions(void); 740 void DecremenetRemainingConnectionAttempts(void); 741 bool HasNoRemainingConnectionAttempts(void) const; 742 int Transmit(const unsigned char *aBuf, 743 size_t aLength, 744 const Ip6::MessageInfo &aMessageInfo, 745 Message::SubType aMessageSubType); 746 747 static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr); 748 void HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr); 749 750 #ifdef MBEDTLS_SSL_EXPORT_KEYS 751 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000) 752 753 static void HandleMbedtlsExportKeys(void *aContext, 754 mbedtls_ssl_key_export_type aType, 755 const unsigned char *aMasterSecret, 756 size_t aMasterSecretLen, 757 const unsigned char aClientRandom[32], 758 const unsigned char aServerRandom[32], 759 mbedtls_tls_prf_types aTlsPrfType); 760 761 void HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType, 762 const unsigned char *aMasterSecret, 763 size_t aMasterSecretLen, 764 const unsigned char aClientRandom[32], 765 const unsigned char aServerRandom[32], 766 mbedtls_tls_prf_types aTlsPrfType); 767 768 #else 769 770 static int HandleMbedtlsExportKeys(void *aContext, 771 const unsigned char *aMasterSecret, 772 const unsigned char *aKeyBlock, 773 size_t aMacLength, 774 size_t aKeyLength, 775 size_t aIvLength); 776 int HandleMbedtlsExportKeys(const unsigned char *aMasterSecret, 777 const unsigned char *aKeyBlock, 778 size_t aMacLength, 779 size_t aKeyLength, 780 size_t aIvLength); 781 782 #endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000) 783 #endif // MBEDTLS_SSL_EXPORT_KEYS 784 785 static void HandleUpdateTask(Tasklet &aTasklet); 786 void HandleUpdateTask(void); 787 static void HandleTimer(Timer &aTimer); 788 void HandleTimer(void); 789 790 using TransportSocket = Ip6::Udp::SocketIn<SecureTransport, &SecureTransport::HandleReceive>; 791 792 #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) 793 static const uint16_t kGroups[]; 794 #else 795 static const mbedtls_ecp_group_id kCurves[]; 796 #endif 797 798 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) 799 #if (MBEDTLS_VERSION_NUMBER >= 0x03020000) 800 static const uint16_t kSignatures[]; 801 #else 802 static const int kHashes[]; 803 #endif 804 #endif 805 806 static const int kCipherSuites[][2]; 807 808 bool mLayerTwoSecurity : 1; 809 bool mDatagramTransport : 1; 810 bool mIsOpen : 1; 811 bool mIsClosing : 1; 812 bool mVerifyPeerCertificate : 1; 813 CipherSuite mCipherSuite; 814 uint8_t mPskLength; 815 uint16_t mMaxConnectionAttempts; 816 uint16_t mRemainingConnectionAttempts; 817 LinkedList<SecureSession> mSessions; 818 TransportSocket mSocket; 819 uint8_t mPsk[kPskMaxLength]; 820 TimerMilliContext mTimer; 821 TaskletContext mUpdateTask; 822 Callback<AutoCloseCallback> mAutoCloseCallback; 823 Callback<AcceptCallback> mAcceptCallback; 824 Callback<RemoveSessionCallback> mRemoveSessionCallback; 825 Callback<TransportCallback> mTransportCallback; 826 #if OPENTHREAD_CONFIG_TLS_API_ENABLE 827 Extension *mExtension; 828 #endif 829 }; 830 831 /** 832 * Defines DTLS `Transport` and `Session`. 833 */ 834 class Dtls 835 { 836 public: 837 class Session; 838 839 /** 840 * Represents a DTLS transport. 841 */ 842 class Transport : public SecureTransport 843 { 844 friend class Session; 845 846 public: 847 /** 848 * Initializes the `Dtls::Transport` object. 849 * 850 * @param[in] aInstance A reference to the OpenThread instance. 851 * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. 852 */ Transport(Instance & aInstance,LinkSecurityMode aLayerTwoSecurity)853 Transport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity) 854 : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ true) 855 { 856 } 857 }; 858 859 /** 860 * Represents a DTLS session. 861 */ 862 class Session : public SecureSession 863 { 864 public: 865 /** 866 * Initializes the `Dtls::Session` object. 867 * 868 * @param[in] aTransport The DTLS transport to use for this session. 869 */ Session(Transport & aTransport)870 Session(Transport &aTransport) 871 : SecureSession(aTransport) 872 { 873 } 874 875 /** 876 * Returns the DTLS transport used by this session. 877 * 878 * @returns The DTLS transport associated with this session. 879 */ GetTransport(void)880 Transport &GetTransport(void) { return static_cast<Transport &>(SecureSession::GetTransport()); } 881 }; 882 }; 883 884 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE 885 886 /** 887 * Represents a TLS instance. 888 */ 889 class Tls : public SecureTransport, public SecureSession 890 { 891 public: 892 /** 893 * Initializes the `Tls` object. 894 * 895 * @param[in] aInstance A reference to the OpenThread instance. 896 * @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not. 897 * @param[in] aExtension An extension providing additional configuration methods. 898 */ Tls(Instance & aInstance,LinkSecurityMode aLayerTwoSecurity,Extension & aExtension)899 Tls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension) 900 : SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ false) 901 , SecureSession(*static_cast<SecureTransport *>(this)) 902 { 903 SetExtension(aExtension); 904 SetAcceptCallback(&HandleAccept, this); 905 } 906 907 private: 908 static SecureSession *HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo); 909 SecureSession *HandleAccept(void); 910 }; 911 912 #endif 913 914 } // namespace MeshCoP 915 } // namespace ot 916 917 #endif // SECURE_TRANSPORT_HPP_ 918