• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 DTLS_HPP_
35 #define DTLS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <mbedtls/net_sockets.h>
40 #include <mbedtls/ssl.h>
41 #include <mbedtls/ssl_cookie.h>
42 #include <mbedtls/version.h>
43 
44 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
45 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
46 #include <mbedtls/base64.h>
47 #include <mbedtls/x509.h>
48 #include <mbedtls/x509_crl.h>
49 #include <mbedtls/x509_crt.h>
50 #include <mbedtls/x509_csr.h>
51 #endif
52 #endif
53 
54 #include "common/locator.hpp"
55 #include "common/message.hpp"
56 #include "common/random.hpp"
57 #include "common/timer.hpp"
58 #include "crypto/sha256.hpp"
59 #include "meshcop/meshcop_tlvs.hpp"
60 #include "net/socket.hpp"
61 #include "net/udp6.hpp"
62 
63 namespace ot {
64 
65 namespace MeshCoP {
66 
67 class Dtls : public InstanceLocator
68 {
69 public:
70     static constexpr uint8_t kPskMaxLength = 32; ///< Maximum PSK length.
71 
72     /**
73      * This constructor initializes the DTLS object.
74      *
75      * @param[in]  aInstance            A reference to the OpenThread instance.
76      * @param[in]  aLayerTwoSecurity    Specifies whether to use layer two security or not.
77      *
78      */
79     explicit Dtls(Instance &aInstance, bool aLayerTwoSecurity);
80 
81     /**
82      * This function pointer is called when a connection is established or torn down.
83      *
84      * @param[in]  aContext    A pointer to application-specific context.
85      * @param[in]  aConnected  TRUE if a connection was established, FALSE otherwise.
86      *
87      */
88     typedef void (*ConnectedHandler)(void *aContext, bool aConnected);
89 
90     /**
91      * This function pointer is called when data is received from the DTLS session.
92      *
93      * @param[in]  aContext  A pointer to application-specific context.
94      * @param[in]  aBuf      A pointer to the received data buffer.
95      * @param[in]  aLength   Number of bytes in the received data buffer.
96      *
97      */
98     typedef void (*ReceiveHandler)(void *aContext, uint8_t *aBuf, uint16_t aLength);
99 
100     /**
101      * This function pointer is called when secure CoAP server want to send encrypted message.
102      *
103      * @param[in]  aContext      A pointer to arbitrary context information.
104      * @param[in]  aMessage      A reference to the message to send.
105      * @param[in]  aMessageInfo  A reference to the message info associated with @p aMessage.
106      *
107      */
108     typedef Error (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
109 
110     /**
111      * This method opens the DTLS socket.
112      *
113      * @param[in]  aReceiveHandler      A pointer to a function that is called to receive DTLS payload.
114      * @param[in]  aConnectedHandler    A pointer to a function that is called when connected or disconnected.
115      * @param[in]  aContext             A pointer to arbitrary context information.
116      *
117      * @retval kErrorNone     Successfully opened the socket.
118      * @retval kErrorAlready  The DTLS is already open.
119      *
120      */
121     Error Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
122 
123     /**
124      * This method binds this DTLS to a UDP port.
125      *
126      * @param[in]  aPort              The port to bind.
127      *
128      * @retval kErrorNone           Successfully bound the DTLS socket.
129      * @retval kErrorInvalidState   The DTLS socket is not open.
130      * @retval kErrorAlready        Already bound.
131      *
132      */
133     Error Bind(uint16_t aPort);
134 
135     /**
136      * This method gets the UDP port of this session.
137      *
138      * @returns  UDP port number.
139      *
140      */
141     uint16_t GetUdpPort(void) const;
142 
143     /**
144      * This method binds this DTLS with a transport callback.
145      *
146      * @param[in]  aCallback  A pointer to a function for sending messages.
147      * @param[in]  aContext   A pointer to arbitrary context information.
148      *
149      * @retval kErrorNone           Successfully bound the DTLS socket.
150      * @retval kErrorInvalidState   The DTLS socket is not open.
151      * @retval kErrorAlready        Already bound.
152      *
153      */
154     Error Bind(TransportCallback aCallback, void *aContext);
155 
156     /**
157      * This method establishes a DTLS session.
158      *
159      * For CoAP Secure API do first:
160      * Set X509 Pk and Cert for use DTLS mode ECDHE ECDSA with AES 128 CCM 8 or
161      * set PreShared Key for use DTLS mode PSK with AES 128 CCM 8.
162      *
163      * @param[in]  aSockAddr               A reference to the remote sockaddr.
164      *
165      * @retval kErrorNone          Successfully started DTLS handshake.
166      * @retval kErrorInvalidState  The DTLS socket is not open.
167      *
168      */
169     Error Connect(const Ip6::SockAddr &aSockAddr);
170 
171     /**
172      * This method indicates whether or not the DTLS session is active.
173      *
174      * @retval TRUE  If DTLS session is active.
175      * @retval FALSE If DTLS session is not active.
176      *
177      */
IsConnectionActive(void) const178     bool IsConnectionActive(void) const { return mState >= kStateConnecting; }
179 
180     /**
181      * This method indicates whether or not the DTLS session is connected.
182      *
183      * @retval TRUE   The DTLS session is connected.
184      * @retval FALSE  The DTLS session is not connected.
185      *
186      */
IsConnected(void) const187     bool IsConnected(void) const { return mState == kStateConnected; }
188 
189     /**
190      * This method disconnects the DTLS session.
191      *
192      */
193     void Disconnect(void);
194 
195     /**
196      * This method closes the DTLS socket.
197      *
198      */
199     void Close(void);
200 
201     /**
202      * This method sets the PSK.
203      *
204      * @param[in]  aPsk  A pointer to the PSK.
205      *
206      * @retval kErrorNone          Successfully set the PSK.
207      * @retval kErrorInvalidArgs   The PSK is invalid.
208      *
209      */
210     Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
211 
212 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
213 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
214     /**
215      * This method sets the Pre-Shared Key (PSK) for DTLS sessions-
216      * identified by a PSK.
217      *
218      * DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS.
219      *
220      * @param[in]  aPsk          A pointer to the PSK.
221      * @param[in]  aPskLength    The PSK char length.
222      * @param[in]  aPskIdentity  The Identity Name for the PSK.
223      * @param[in]  aPskIdLength  The PSK Identity Length.
224      *
225      * @retval kErrorNone  Successfully set the PSK.
226      *
227      */
228     void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength);
229 
230 #endif
231 
232 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
233     /**
234      * This method sets a reference to the own x509 certificate with corresponding private key.
235      *
236      * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
237      *
238      * @param[in]  aX509Certificate   A pointer to the PEM formatted X509 certificate.
239      * @param[in]  aX509CertLength    The length of certificate.
240      * @param[in]  aPrivateKey        A pointer to the PEM formatted private key.
241      * @param[in]  aPrivateKeyLength  The length of the private key.
242      *
243      */
244     void SetCertificate(const uint8_t *aX509Certificate,
245                         uint32_t       aX509CertLength,
246                         const uint8_t *aPrivateKey,
247                         uint32_t       aPrivateKeyLength);
248 
249     /**
250      * This method sets the trusted top level CAs. It is needed for validate the
251      * certificate of the peer.
252      *
253      * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
254      *
255      * @param[in]  aX509CaCertificateChain  A pointer to the PEM formatted X509 CA chain.
256      * @param[in]  aX509CaCertChainLength   The length of chain.
257      *
258      */
259     void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength);
260 #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
261 
262 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
263     /**
264      * This method returns the peer x509 certificate base64 encoded.
265      *
266      * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
267      *
268      * @param[out]  aPeerCert        A pointer to the base64 encoded certificate buffer.
269      * @param[out]  aCertLength      The length of the base64 encoded peer certificate.
270      * @param[in]   aCertBufferSize  The buffer size of aPeerCert.
271      *
272      * @retval kErrorInvalidState   Not connected yet.
273      * @retval kErrorNone           Successfully get the peer certificate.
274      * @retval kErrorNoBufs         Can't allocate memory for certificate.
275      *
276      */
277     Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);
278 #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
279 
280     /**
281      * This method set the authentication mode for a dtls connection.
282      *
283      * Disable or enable the verification of peer certificate.
284      * Must called before start.
285      *
286      * @param[in]  aVerifyPeerCertificate  true, if the peer certificate should verify.
287      *
288      */
SetSslAuthMode(bool aVerifyPeerCertificate)289     void SetSslAuthMode(bool aVerifyPeerCertificate) { mVerifyPeerCertificate = aVerifyPeerCertificate; }
290 #endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
291 
292 #ifdef MBEDTLS_SSL_SRV_C
293     /**
294      * This method sets the Client ID used for generating the Hello Cookie.
295      *
296      * @param[in]  aClientId  A pointer to the Client ID.
297      * @param[in]  aLength    Number of bytes in the Client ID.
298      *
299      * @retval kErrorNone  Successfully set the Client ID.
300      *
301      */
302     Error SetClientId(const uint8_t *aClientId, uint8_t aLength);
303 #endif
304 
305     /**
306      * This method sends data within the DTLS session.
307      *
308      * @param[in]  aMessage  A message to send via DTLS.
309      * @param[in]  aLength   Number of bytes in the data buffer.
310      *
311      * @retval kErrorNone     Successfully sent the data via the DTLS session.
312      * @retval kErrorNoBufs   A message is too long.
313      *
314      */
315     Error Send(Message &aMessage, uint16_t aLength);
316 
317     /**
318      * This method provides a received DTLS message to the DTLS object.
319      *
320      * @param[in]  aMessage  A reference to the message.
321      *
322      */
323     void Receive(Message &aMessage);
324 
325     /**
326      * This method sets the default message sub-type that will be used for all messages without defined
327      * sub-type.
328      *
329      * @param[in]  aMessageSubType  The default message sub-type.
330      *
331      */
SetDefaultMessageSubType(Message::SubType aMessageSubType)332     void SetDefaultMessageSubType(Message::SubType aMessageSubType) { mMessageDefaultSubType = aMessageSubType; }
333 
334     /**
335      * This method returns the DTLS session's peer address.
336      *
337      * @return DTLS session's message info.
338      *
339      */
GetMessageInfo(void) const340     const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
341 
342     void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
343 
344 private:
345     enum State : uint8_t
346     {
347         kStateClosed,       // UDP socket is closed.
348         kStateOpen,         // UDP socket is open.
349         kStateInitializing, // The DTLS service is initializing.
350         kStateConnecting,   // The DTLS service is establishing a connection.
351         kStateConnected,    // The DTLS service has a connection established.
352         kStateCloseNotify,  // The DTLS service is closing a connection.
353     };
354 
355     static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
356 
357 #if !OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
358     static constexpr uint16_t kApplicationDataMaxLength = 1152;
359 #else
360     static constexpr uint16_t         kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
361 #endif
362 
363     static constexpr size_t kDtlsKeyBlockSize     = 40;
364     static constexpr size_t kDtlsRandomBufferSize = 32;
365 
366     void  FreeMbedtls(void);
367     Error Setup(bool aClient);
368 
369 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
370     /**
371      * Set keys and/or certificates for dtls session dependent of used cipher suite.
372      *
373      * @retval mbedtls error, 0 if successfully.
374      *
375      */
376     int SetApplicationCoapSecureKeys(void);
377 #endif
378 
379     static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
380     void        HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr);
381 
382     static int HandleMbedtlsGetTimer(void *aContext);
383     int        HandleMbedtlsGetTimer(void);
384 
385     static void HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish);
386     void        HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish);
387 
388     static int HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength);
389     int        HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength);
390 
391     static int HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength);
392     int        HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength);
393 
394 #ifdef MBEDTLS_SSL_EXPORT_KEYS
395 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
396 
397     static void HandleMbedtlsExportKeys(void *                      aContext,
398                                         mbedtls_ssl_key_export_type aType,
399                                         const unsigned char *       aMasterSecret,
400                                         size_t                      aMasterSecretLen,
401                                         const unsigned char         aClientRandom[32],
402                                         const unsigned char         aServerRandom[32],
403                                         mbedtls_tls_prf_types       aTlsPrfType);
404 
405     void HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType,
406                                  const unsigned char *       aMasterSecret,
407                                  size_t                      aMasterSecretLen,
408                                  const unsigned char         aClientRandom[32],
409                                  const unsigned char         aServerRandom[32],
410                                  mbedtls_tls_prf_types       aTlsPrfType);
411 
412 #else
413 
414     static int HandleMbedtlsExportKeys(void *               aContext,
415                                        const unsigned char *aMasterSecret,
416                                        const unsigned char *aKeyBlock,
417                                        size_t               aMacLength,
418                                        size_t               aKeyLength,
419                                        size_t               aIvLength);
420     int        HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
421                                        const unsigned char *aKeyBlock,
422                                        size_t               aMacLength,
423                                        size_t               aKeyLength,
424                                        size_t               aIvLength);
425 
426 #endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000)
427 #endif // MBEDTLS_SSL_EXPORT_KEYS
428 
429     static void HandleTimer(Timer &aTimer);
430     void        HandleTimer(void);
431 
432     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
433 
434     void  HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
435     Error HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
436 
437     void Process(void);
438 
439     State mState;
440 
441     int     mCipherSuites[2];
442     uint8_t mPsk[kPskMaxLength];
443     uint8_t mPskLength;
444 
445 #if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
446     static const uint16_t sGroups[];
447 #else
448     static const mbedtls_ecp_group_id sCurves[];
449 #endif
450 
451 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
452     static const int sHashes[];
453 #endif
454 
455 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
456 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
457     const uint8_t *    mCaChainSrc;
458     uint32_t           mCaChainLength;
459     const uint8_t *    mOwnCertSrc;
460     uint32_t           mOwnCertLength;
461     const uint8_t *    mPrivateKeySrc;
462     uint32_t           mPrivateKeyLength;
463     mbedtls_x509_crt   mCaChain;
464     mbedtls_x509_crt   mOwnCert;
465     mbedtls_pk_context mPrivateKey;
466 #endif
467 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
468     const uint8_t *mPreSharedKey;
469     const uint8_t *mPreSharedKeyIdentity;
470     uint16_t       mPreSharedKeyLength;
471     uint16_t       mPreSharedKeyIdLength;
472 #endif
473 #endif
474 
475     bool mVerifyPeerCertificate;
476 
477     mbedtls_ssl_context mSsl;
478     mbedtls_ssl_config  mConf;
479 
480 #ifdef MBEDTLS_SSL_COOKIE_C
481     mbedtls_ssl_cookie_ctx mCookieCtx;
482 #endif
483 
484     TimerMilliContext mTimer;
485 
486     TimeMilli mTimerIntermediate;
487     bool      mTimerSet : 1;
488 
489     bool mLayerTwoSecurity : 1;
490 
491     Message *mReceiveMessage;
492 
493     ConnectedHandler mConnectedHandler;
494     ReceiveHandler   mReceiveHandler;
495     void *           mContext;
496 
497     Ip6::MessageInfo mMessageInfo;
498     Ip6::Udp::Socket mSocket;
499 
500     TransportCallback mTransportCallback;
501     void *            mTransportContext;
502 
503     Message::SubType mMessageSubType;
504     Message::SubType mMessageDefaultSubType;
505 };
506 
507 } // namespace MeshCoP
508 } // namespace ot
509 
510 #endif // DTLS_HPP_
511