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/certs.h>
40 #include <mbedtls/net_sockets.h>
41 #include <mbedtls/ssl.h>
42 #include <mbedtls/ssl_cookie.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]  aNetif               A reference to the Thread network interface.
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     void  FreeMbedtls(void);
364     Error Setup(bool aClient);
365 
366 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
367     /**
368      * Set keys and/or certificates for dtls session dependent of used cipher suite.
369      *
370      * @retval mbedtls error, 0 if successfully.
371      *
372      */
373     int SetApplicationCoapSecureKeys(void);
374 #endif
375 
376     static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
377     void        HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr);
378 
379     static int HandleMbedtlsGetTimer(void *aContext);
380     int        HandleMbedtlsGetTimer(void);
381 
382     static void HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish);
383     void        HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish);
384 
385     static int HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength);
386     int        HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength);
387 
388     static int HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength);
389     int        HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength);
390 
391     static int HandleMbedtlsExportKeys(void *               aContext,
392                                        const unsigned char *aMasterSecret,
393                                        const unsigned char *aKeyBlock,
394                                        size_t               aMacLength,
395                                        size_t               aKeyLength,
396                                        size_t               aIvLength);
397     int        HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
398                                        const unsigned char *aKeyBlock,
399                                        size_t               aMacLength,
400                                        size_t               aKeyLength,
401                                        size_t               aIvLength);
402 
403     static void HandleTimer(Timer &aTimer);
404     void        HandleTimer(void);
405 
406     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
407 
408     void  HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
409     Error HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
410 
411     void Process(void);
412 
413     State mState;
414 
415     int     mCipherSuites[2];
416     uint8_t mPsk[kPskMaxLength];
417     uint8_t mPskLength;
418 
419     static const mbedtls_ecp_group_id sCurves[];
420 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
421     static const int sHashes[];
422 #endif
423 
424 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
425 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
426     const uint8_t *    mCaChainSrc;
427     uint32_t           mCaChainLength;
428     const uint8_t *    mOwnCertSrc;
429     uint32_t           mOwnCertLength;
430     const uint8_t *    mPrivateKeySrc;
431     uint32_t           mPrivateKeyLength;
432     mbedtls_x509_crt   mCaChain;
433     mbedtls_x509_crt   mOwnCert;
434     mbedtls_pk_context mPrivateKey;
435 #endif
436 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
437     const uint8_t *mPreSharedKey;
438     const uint8_t *mPreSharedKeyIdentity;
439     uint16_t       mPreSharedKeyLength;
440     uint16_t       mPreSharedKeyIdLength;
441 #endif
442 #endif
443 
444     bool mVerifyPeerCertificate;
445 
446     mbedtls_ssl_context mSsl;
447     mbedtls_ssl_config  mConf;
448 
449 #ifdef MBEDTLS_SSL_COOKIE_C
450     mbedtls_ssl_cookie_ctx mCookieCtx;
451 #endif
452 
453     TimerMilliContext mTimer;
454 
455     TimeMilli mTimerIntermediate;
456     bool      mTimerSet : 1;
457 
458     bool mLayerTwoSecurity : 1;
459 
460     Message *mReceiveMessage;
461 
462     ConnectedHandler mConnectedHandler;
463     ReceiveHandler   mReceiveHandler;
464     void *           mContext;
465 
466     Ip6::MessageInfo mMessageInfo;
467     Ip6::Udp::Socket mSocket;
468 
469     TransportCallback mTransportCallback;
470     void *            mTransportContext;
471 
472     Message::SubType mMessageSubType;
473     Message::SubType mMessageDefaultSubType;
474 };
475 
476 } // namespace MeshCoP
477 } // namespace ot
478 
479 #endif // DTLS_HPP_
480