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 implements the necessary hooks for mbedTLS.
32 */
33
34 #include "dtls.hpp"
35
36 #include <mbedtls/debug.h>
37 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
38 #include <mbedtls/pem.h>
39 #endif
40 #include <openthread/platform/radio.h>
41
42 #include "common/code_utils.hpp"
43 #include "common/debug.hpp"
44 #include "common/encoding.hpp"
45 #include "common/instance.hpp"
46 #include "common/locator_getters.hpp"
47 #include "common/logging.hpp"
48 #include "common/timer.hpp"
49 #include "crypto/mbedtls.hpp"
50 #include "crypto/sha256.hpp"
51 #include "thread/thread_netif.hpp"
52
53 #if OPENTHREAD_CONFIG_DTLS_ENABLE
54
55 namespace ot {
56 namespace MeshCoP {
57
58 const mbedtls_ecp_group_id Dtls::sCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
59 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
60 const int Dtls::sHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
61 #endif
62
Dtls(Instance & aInstance,bool aLayerTwoSecurity)63 Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
64 : InstanceLocator(aInstance)
65 , mState(kStateClosed)
66 , mPskLength(0)
67 , mVerifyPeerCertificate(true)
68 , mTimer(aInstance, Dtls::HandleTimer, this)
69 , mTimerIntermediate(0)
70 , mTimerSet(false)
71 , mLayerTwoSecurity(aLayerTwoSecurity)
72 , mReceiveMessage(nullptr)
73 , mConnectedHandler(nullptr)
74 , mReceiveHandler(nullptr)
75 , mContext(nullptr)
76 , mSocket(aInstance)
77 , mTransportCallback(nullptr)
78 , mTransportContext(nullptr)
79 , mMessageSubType(Message::kSubTypeNone)
80 , mMessageDefaultSubType(Message::kSubTypeNone)
81 {
82 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
83 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
84 mPreSharedKey = nullptr;
85 mPreSharedKeyIdentity = nullptr;
86 mPreSharedKeyIdLength = 0;
87 mPreSharedKeyLength = 0;
88 #endif
89
90 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
91 mCaChainSrc = nullptr;
92 mCaChainLength = 0;
93 mOwnCertSrc = nullptr;
94 mOwnCertLength = 0;
95 mPrivateKeySrc = nullptr;
96 mPrivateKeyLength = 0;
97 memset(&mCaChain, 0, sizeof(mCaChain));
98 memset(&mOwnCert, 0, sizeof(mOwnCert));
99 memset(&mPrivateKey, 0, sizeof(mPrivateKey));
100 #endif
101 #endif
102
103 memset(mCipherSuites, 0, sizeof(mCipherSuites));
104 memset(mPsk, 0, sizeof(mPsk));
105 memset(&mSsl, 0, sizeof(mSsl));
106 memset(&mConf, 0, sizeof(mConf));
107
108 #ifdef MBEDTLS_SSL_COOKIE_C
109 memset(&mCookieCtx, 0, sizeof(mCookieCtx));
110 #endif
111 }
112
FreeMbedtls(void)113 void Dtls::FreeMbedtls(void)
114 {
115 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
116 mbedtls_ssl_cookie_free(&mCookieCtx);
117 #endif
118 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
119 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
120 mbedtls_x509_crt_free(&mCaChain);
121 mbedtls_x509_crt_free(&mOwnCert);
122 mbedtls_pk_free(&mPrivateKey);
123 #endif
124 #endif
125 mbedtls_ssl_config_free(&mConf);
126 mbedtls_ssl_free(&mSsl);
127 }
128
Open(ReceiveHandler aReceiveHandler,ConnectedHandler aConnectedHandler,void * aContext)129 Error Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
130 {
131 Error error;
132
133 VerifyOrExit(mState == kStateClosed, error = kErrorAlready);
134
135 SuccessOrExit(error = mSocket.Open(&Dtls::HandleUdpReceive, this));
136
137 mReceiveHandler = aReceiveHandler;
138 mConnectedHandler = aConnectedHandler;
139 mContext = aContext;
140 mState = kStateOpen;
141
142 exit:
143 return error;
144 }
145
Connect(const Ip6::SockAddr & aSockAddr)146 Error Dtls::Connect(const Ip6::SockAddr &aSockAddr)
147 {
148 Error error;
149
150 VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
151
152 mMessageInfo.SetPeerAddr(aSockAddr.GetAddress());
153 mMessageInfo.SetPeerPort(aSockAddr.mPort);
154
155 error = Setup(true);
156
157 exit:
158 return error;
159 }
160
HandleUdpReceive(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo)161 void Dtls::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
162 {
163 static_cast<Dtls *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
164 *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
165 }
166
HandleUdpReceive(Message & aMessage,const Ip6::MessageInfo & aMessageInfo)167 void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
168 {
169 switch (mState)
170 {
171 case MeshCoP::Dtls::kStateClosed:
172 ExitNow();
173
174 case MeshCoP::Dtls::kStateOpen:
175 IgnoreError(mSocket.Connect(Ip6::SockAddr(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort())));
176
177 mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
178 mMessageInfo.SetPeerPort(aMessageInfo.GetPeerPort());
179 mMessageInfo.SetIsHostInterface(aMessageInfo.IsHostInterface());
180
181 if (Get<ThreadNetif>().HasUnicastAddress(aMessageInfo.GetSockAddr()))
182 {
183 mMessageInfo.SetSockAddr(aMessageInfo.GetSockAddr());
184 }
185
186 mMessageInfo.SetSockPort(aMessageInfo.GetSockPort());
187
188 SuccessOrExit(Setup(false));
189 break;
190
191 default:
192 // Once DTLS session is started, communicate only with a peer.
193 VerifyOrExit((mMessageInfo.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
194 (mMessageInfo.GetPeerPort() == aMessageInfo.GetPeerPort()));
195 break;
196 }
197
198 #ifdef MBEDTLS_SSL_SRV_C
199 if (mState == MeshCoP::Dtls::kStateConnecting)
200 {
201 IgnoreError(SetClientId(mMessageInfo.GetPeerAddr().mFields.m8, sizeof(mMessageInfo.GetPeerAddr().mFields)));
202 }
203 #endif
204
205 Receive(aMessage);
206
207 exit:
208 return;
209 }
210
GetUdpPort(void) const211 uint16_t Dtls::GetUdpPort(void) const
212 {
213 return mSocket.GetSockName().GetPort();
214 }
215
Bind(uint16_t aPort)216 Error Dtls::Bind(uint16_t aPort)
217 {
218 Error error;
219
220 VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
221 VerifyOrExit(mTransportCallback == nullptr, error = kErrorAlready);
222
223 SuccessOrExit(error = mSocket.Bind(aPort, OT_NETIF_UNSPECIFIED));
224
225 exit:
226 return error;
227 }
228
Bind(TransportCallback aCallback,void * aContext)229 Error Dtls::Bind(TransportCallback aCallback, void *aContext)
230 {
231 Error error = kErrorNone;
232
233 VerifyOrExit(mState == kStateOpen, error = kErrorInvalidState);
234 VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready);
235 VerifyOrExit(mTransportCallback == nullptr, error = kErrorAlready);
236
237 mTransportCallback = aCallback;
238 mTransportContext = aContext;
239
240 exit:
241 return error;
242 }
243
Setup(bool aClient)244 Error Dtls::Setup(bool aClient)
245 {
246 int rval;
247
248 // do not handle new connection before guard time expired
249 VerifyOrExit(mState == kStateOpen, rval = MBEDTLS_ERR_SSL_TIMEOUT);
250
251 mState = kStateInitializing;
252
253 mbedtls_ssl_init(&mSsl);
254 mbedtls_ssl_config_init(&mConf);
255 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
256 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
257 mbedtls_x509_crt_init(&mCaChain);
258 mbedtls_x509_crt_init(&mOwnCert);
259 mbedtls_pk_init(&mPrivateKey);
260 #endif
261 #endif
262 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
263 mbedtls_ssl_cookie_init(&mCookieCtx);
264 #endif
265
266 rval = mbedtls_ssl_config_defaults(&mConf, aClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
267 MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT);
268 VerifyOrExit(rval == 0);
269
270 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
271 if (mVerifyPeerCertificate && mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8)
272 {
273 mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED);
274 }
275 else
276 {
277 mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE);
278 }
279 #else
280 OT_UNUSED_VARIABLE(mVerifyPeerCertificate);
281 #endif
282
283 mbedtls_ssl_conf_rng(&mConf, mbedtls_ctr_drbg_random, Random::Crypto::MbedTlsContextGet());
284 mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
285 mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
286
287 OT_ASSERT(mCipherSuites[1] == 0);
288 mbedtls_ssl_conf_ciphersuites(&mConf, mCipherSuites);
289 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
290 {
291 mbedtls_ssl_conf_curves(&mConf, sCurves);
292 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
293 mbedtls_ssl_conf_sig_hashes(&mConf, sHashes);
294 #endif
295 }
296 mbedtls_ssl_conf_export_keys_cb(&mConf, HandleMbedtlsExportKeys, this);
297 mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000);
298 mbedtls_ssl_conf_dbg(&mConf, HandleMbedtlsDebug, this);
299
300 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
301 if (!aClient)
302 {
303 rval = mbedtls_ssl_cookie_setup(&mCookieCtx, mbedtls_ctr_drbg_random, Random::Crypto::MbedTlsContextGet());
304 VerifyOrExit(rval == 0);
305
306 mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx);
307 }
308 #endif
309
310 rval = mbedtls_ssl_setup(&mSsl, &mConf);
311 VerifyOrExit(rval == 0);
312
313 mbedtls_ssl_set_bio(&mSsl, this, &Dtls::HandleMbedtlsTransmit, HandleMbedtlsReceive, nullptr);
314 mbedtls_ssl_set_timer_cb(&mSsl, this, &Dtls::HandleMbedtlsSetTimer, HandleMbedtlsGetTimer);
315
316 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
317 {
318 rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
319 }
320 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
321 else
322 {
323 rval = SetApplicationCoapSecureKeys();
324 }
325 #endif
326 VerifyOrExit(rval == 0);
327
328 mReceiveMessage = nullptr;
329 mMessageSubType = Message::kSubTypeNone;
330 mState = kStateConnecting;
331
332 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
333 {
334 otLogInfoMeshCoP("DTLS started");
335 }
336 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
337 else
338 {
339 otLogInfoCoap("Application Coap Secure DTLS started");
340 }
341 #endif
342
343 mState = kStateConnecting;
344
345 Process();
346
347 exit:
348 if ((mState == kStateInitializing) && (rval != 0))
349 {
350 mState = kStateOpen;
351 FreeMbedtls();
352 }
353
354 return Crypto::MbedTls::MapError(rval);
355 }
356
357 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
SetApplicationCoapSecureKeys(void)358 int Dtls::SetApplicationCoapSecureKeys(void)
359 {
360 int rval = 0;
361
362 switch (mCipherSuites[0])
363 {
364 case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
365 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
366 if (mCaChainSrc != nullptr)
367 {
368 rval = mbedtls_x509_crt_parse(&mCaChain, static_cast<const unsigned char *>(mCaChainSrc),
369 static_cast<size_t>(mCaChainLength));
370 VerifyOrExit(rval == 0);
371 mbedtls_ssl_conf_ca_chain(&mConf, &mCaChain, nullptr);
372 }
373
374 if (mOwnCertSrc != nullptr && mPrivateKeySrc != nullptr)
375 {
376 rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast<const unsigned char *>(mOwnCertSrc),
377 static_cast<size_t>(mOwnCertLength));
378 VerifyOrExit(rval == 0);
379 rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc),
380 static_cast<size_t>(mPrivateKeyLength), nullptr, 0);
381 VerifyOrExit(rval == 0);
382 rval = mbedtls_ssl_conf_own_cert(&mConf, &mOwnCert, &mPrivateKey);
383 VerifyOrExit(rval == 0);
384 }
385 #endif
386 break;
387
388 case MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8:
389 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
390 rval = mbedtls_ssl_conf_psk(&mConf, static_cast<const unsigned char *>(mPreSharedKey), mPreSharedKeyLength,
391 static_cast<const unsigned char *>(mPreSharedKeyIdentity), mPreSharedKeyIdLength);
392 VerifyOrExit(rval == 0);
393 #endif
394 break;
395
396 default:
397 otLogCritCoap("Application Coap Secure DTLS: Not supported cipher.");
398 rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
399 ExitNow();
400 break;
401 }
402
403 exit:
404 return rval;
405 }
406
407 #endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
408
Close(void)409 void Dtls::Close(void)
410 {
411 Disconnect();
412
413 mState = kStateClosed;
414 mTransportCallback = nullptr;
415 mTransportContext = nullptr;
416 mTimerSet = false;
417
418 IgnoreError(mSocket.Close());
419 mTimer.Stop();
420 }
421
Disconnect(void)422 void Dtls::Disconnect(void)
423 {
424 VerifyOrExit(mState == kStateConnecting || mState == kStateConnected);
425
426 mbedtls_ssl_close_notify(&mSsl);
427 mState = kStateCloseNotify;
428 mTimer.Start(kGuardTimeNewConnectionMilli);
429
430 mMessageInfo.Clear();
431 IgnoreError(mSocket.Connect());
432
433 FreeMbedtls();
434
435 exit:
436 return;
437 }
438
SetPsk(const uint8_t * aPsk,uint8_t aPskLength)439 Error Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
440 {
441 Error error = kErrorNone;
442
443 VerifyOrExit(aPskLength <= sizeof(mPsk), error = kErrorInvalidArgs);
444
445 memcpy(mPsk, aPsk, aPskLength);
446 mPskLength = aPskLength;
447 mCipherSuites[0] = MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8;
448 mCipherSuites[1] = 0;
449
450 exit:
451 return error;
452 }
453
454 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
455 #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
456
SetCertificate(const uint8_t * aX509Certificate,uint32_t aX509CertLength,const uint8_t * aPrivateKey,uint32_t aPrivateKeyLength)457 void Dtls::SetCertificate(const uint8_t *aX509Certificate,
458 uint32_t aX509CertLength,
459 const uint8_t *aPrivateKey,
460 uint32_t aPrivateKeyLength)
461 {
462 OT_ASSERT(aX509CertLength > 0);
463 OT_ASSERT(aX509Certificate != nullptr);
464
465 OT_ASSERT(aPrivateKeyLength > 0);
466 OT_ASSERT(aPrivateKey != nullptr);
467
468 mOwnCertSrc = aX509Certificate;
469 mOwnCertLength = aX509CertLength;
470 mPrivateKeySrc = aPrivateKey;
471 mPrivateKeyLength = aPrivateKeyLength;
472
473 mCipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
474 mCipherSuites[1] = 0;
475 }
476
SetCaCertificateChain(const uint8_t * aX509CaCertificateChain,uint32_t aX509CaCertChainLength)477 void Dtls::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
478 {
479 OT_ASSERT(aX509CaCertChainLength > 0);
480 OT_ASSERT(aX509CaCertificateChain != nullptr);
481
482 mCaChainSrc = aX509CaCertificateChain;
483 mCaChainLength = aX509CaCertChainLength;
484 }
485
486 #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
487
488 #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
SetPreSharedKey(const uint8_t * aPsk,uint16_t aPskLength,const uint8_t * aPskIdentity,uint16_t aPskIdLength)489 void Dtls::SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength)
490 {
491 OT_ASSERT(aPsk != nullptr);
492 OT_ASSERT(aPskIdentity != nullptr);
493 OT_ASSERT(aPskLength > 0);
494 OT_ASSERT(aPskIdLength > 0);
495
496 mPreSharedKey = aPsk;
497 mPreSharedKeyLength = aPskLength;
498 mPreSharedKeyIdentity = aPskIdentity;
499 mPreSharedKeyIdLength = aPskIdLength;
500
501 mCipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8;
502 mCipherSuites[1] = 0;
503 }
504 #endif
505
506 #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
GetPeerCertificateBase64(unsigned char * aPeerCert,size_t * aCertLength,size_t aCertBufferSize)507 Error Dtls::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
508 {
509 Error error = kErrorNone;
510
511 VerifyOrExit(mState == kStateConnected, error = kErrorInvalidState);
512
513 VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength, mSsl.session->peer_cert->raw.p,
514 mSsl.session->peer_cert->raw.len) == 0,
515 error = kErrorNoBufs);
516
517 exit:
518 return error;
519 }
520 #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
521
522 #endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
523
524 #ifdef MBEDTLS_SSL_SRV_C
SetClientId(const uint8_t * aClientId,uint8_t aLength)525 Error Dtls::SetClientId(const uint8_t *aClientId, uint8_t aLength)
526 {
527 int rval = mbedtls_ssl_set_client_transport_id(&mSsl, aClientId, aLength);
528 return Crypto::MbedTls::MapError(rval);
529 }
530 #endif
531
Send(Message & aMessage,uint16_t aLength)532 Error Dtls::Send(Message &aMessage, uint16_t aLength)
533 {
534 Error error = kErrorNone;
535 uint8_t buffer[kApplicationDataMaxLength];
536
537 VerifyOrExit(aLength <= kApplicationDataMaxLength, error = kErrorNoBufs);
538
539 // Store message specific sub type.
540 if (aMessage.GetSubType() != Message::kSubTypeNone)
541 {
542 mMessageSubType = aMessage.GetSubType();
543 }
544
545 aMessage.ReadBytes(0, buffer, aLength);
546
547 SuccessOrExit(error = Crypto::MbedTls::MapError(mbedtls_ssl_write(&mSsl, buffer, aLength)));
548
549 aMessage.Free();
550
551 exit:
552 return error;
553 }
554
Receive(Message & aMessage)555 void Dtls::Receive(Message &aMessage)
556 {
557 mReceiveMessage = &aMessage;
558
559 Process();
560
561 mReceiveMessage = nullptr;
562 }
563
HandleMbedtlsTransmit(void * aContext,const unsigned char * aBuf,size_t aLength)564 int Dtls::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
565 {
566 return static_cast<Dtls *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
567 }
568
HandleMbedtlsTransmit(const unsigned char * aBuf,size_t aLength)569 int Dtls::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
570 {
571 Error error;
572 int rval = 0;
573
574 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
575 {
576 otLogDebgMeshCoP("Dtls::HandleMbedtlsTransmit");
577 }
578 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
579 else
580 {
581 otLogDebgCoap("Dtls::ApplicationCoapSecure HandleMbedtlsTransmit");
582 }
583 #endif
584
585 error = HandleDtlsSend(aBuf, static_cast<uint16_t>(aLength), mMessageSubType);
586
587 // Restore default sub type.
588 mMessageSubType = mMessageDefaultSubType;
589
590 switch (error)
591 {
592 case kErrorNone:
593 rval = static_cast<int>(aLength);
594 break;
595
596 case kErrorNoBufs:
597 rval = MBEDTLS_ERR_SSL_WANT_WRITE;
598 break;
599
600 default:
601 otLogWarnMeshCoP("Dtls::HandleMbedtlsTransmit: %s error", ErrorToString(error));
602 rval = MBEDTLS_ERR_NET_SEND_FAILED;
603 break;
604 }
605
606 return rval;
607 }
608
HandleMbedtlsReceive(void * aContext,unsigned char * aBuf,size_t aLength)609 int Dtls::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
610 {
611 return static_cast<Dtls *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
612 }
613
HandleMbedtlsReceive(unsigned char * aBuf,size_t aLength)614 int Dtls::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
615 {
616 int rval;
617
618 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
619 {
620 otLogDebgMeshCoP("Dtls::HandleMbedtlsReceive");
621 }
622 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
623 else
624 {
625 otLogDebgCoap("Dtls:: ApplicationCoapSecure HandleMbedtlsReceive");
626 }
627 #endif
628
629 VerifyOrExit(mReceiveMessage != nullptr && (rval = mReceiveMessage->GetLength() - mReceiveMessage->GetOffset()) > 0,
630 rval = MBEDTLS_ERR_SSL_WANT_READ);
631
632 if (aLength > static_cast<size_t>(rval))
633 {
634 aLength = static_cast<size_t>(rval);
635 }
636
637 rval = mReceiveMessage->ReadBytes(mReceiveMessage->GetOffset(), aBuf, static_cast<uint16_t>(aLength));
638 mReceiveMessage->MoveOffset(rval);
639
640 exit:
641 return rval;
642 }
643
HandleMbedtlsGetTimer(void * aContext)644 int Dtls::HandleMbedtlsGetTimer(void *aContext)
645 {
646 return static_cast<Dtls *>(aContext)->HandleMbedtlsGetTimer();
647 }
648
HandleMbedtlsGetTimer(void)649 int Dtls::HandleMbedtlsGetTimer(void)
650 {
651 int rval;
652
653 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
654 {
655 otLogDebgMeshCoP("Dtls::HandleMbedtlsGetTimer");
656 }
657 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
658 else
659 {
660 otLogDebgCoap("Dtls:: ApplicationCoapSecure HandleMbedtlsGetTimer");
661 }
662 #endif
663
664 if (!mTimerSet)
665 {
666 rval = -1;
667 }
668 else if (!mTimer.IsRunning())
669 {
670 rval = 2;
671 }
672 else if (mTimerIntermediate <= TimerMilli::GetNow())
673 {
674 rval = 1;
675 }
676 else
677 {
678 rval = 0;
679 }
680
681 return rval;
682 }
683
HandleMbedtlsSetTimer(void * aContext,uint32_t aIntermediate,uint32_t aFinish)684 void Dtls::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
685 {
686 static_cast<Dtls *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
687 }
688
HandleMbedtlsSetTimer(uint32_t aIntermediate,uint32_t aFinish)689 void Dtls::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
690 {
691 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
692 {
693 otLogDebgMeshCoP("Dtls::SetTimer");
694 }
695 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
696 else
697 {
698 otLogDebgCoap("Dtls::ApplicationCoapSecure SetTimer");
699 }
700 #endif
701
702 if (aFinish == 0)
703 {
704 mTimerSet = false;
705 mTimer.Stop();
706 }
707 else
708 {
709 mTimerSet = true;
710 mTimer.Start(aFinish);
711 mTimerIntermediate = TimerMilli::GetNow() + aIntermediate;
712 }
713 }
714
HandleMbedtlsExportKeys(void * aContext,const unsigned char * aMasterSecret,const unsigned char * aKeyBlock,size_t aMacLength,size_t aKeyLength,size_t aIvLength)715 int Dtls::HandleMbedtlsExportKeys(void * aContext,
716 const unsigned char *aMasterSecret,
717 const unsigned char *aKeyBlock,
718 size_t aMacLength,
719 size_t aKeyLength,
720 size_t aIvLength)
721 {
722 return static_cast<Dtls *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, aKeyLength,
723 aIvLength);
724 }
725
HandleMbedtlsExportKeys(const unsigned char * aMasterSecret,const unsigned char * aKeyBlock,size_t aMacLength,size_t aKeyLength,size_t aIvLength)726 int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
727 const unsigned char *aKeyBlock,
728 size_t aMacLength,
729 size_t aKeyLength,
730 size_t aIvLength)
731 {
732 OT_UNUSED_VARIABLE(aMasterSecret);
733
734 Crypto::Sha256::Hash kek;
735 Crypto::Sha256 sha256;
736
737 sha256.Start();
738 sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength));
739 sha256.Finish(kek);
740
741 Get<KeyManager>().SetKek(kek.GetBytes());
742
743 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
744 {
745 otLogDebgMeshCoP("Generated KEK");
746 }
747 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
748 else
749 {
750 otLogDebgCoap("ApplicationCoapSecure Generated KEK");
751 }
752 #endif
753 return 0;
754 }
755
HandleTimer(Timer & aTimer)756 void Dtls::HandleTimer(Timer &aTimer)
757 {
758 static_cast<Dtls *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer();
759 }
760
HandleTimer(void)761 void Dtls::HandleTimer(void)
762 {
763 switch (mState)
764 {
765 case kStateConnecting:
766 case kStateConnected:
767 Process();
768 break;
769
770 case kStateCloseNotify:
771 mState = kStateOpen;
772 mTimer.Stop();
773
774 if (mConnectedHandler != nullptr)
775 {
776 mConnectedHandler(mContext, false);
777 }
778 break;
779
780 default:
781 OT_ASSERT(false);
782 OT_UNREACHABLE_CODE(break);
783 }
784 }
785
Process(void)786 void Dtls::Process(void)
787 {
788 uint8_t buf[OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN];
789 bool shouldDisconnect = false;
790 int rval;
791
792 while ((mState == kStateConnecting) || (mState == kStateConnected))
793 {
794 if (mState == kStateConnecting)
795 {
796 rval = mbedtls_ssl_handshake(&mSsl);
797
798 if (mSsl.state == MBEDTLS_SSL_HANDSHAKE_OVER)
799 {
800 mState = kStateConnected;
801
802 if (mConnectedHandler != nullptr)
803 {
804 mConnectedHandler(mContext, true);
805 }
806 }
807 }
808 else
809 {
810 rval = mbedtls_ssl_read(&mSsl, buf, sizeof(buf));
811 }
812
813 if (rval > 0)
814 {
815 if (mReceiveHandler != nullptr)
816 {
817 mReceiveHandler(mContext, buf, static_cast<uint16_t>(rval));
818 }
819 }
820 else if (rval == 0 || rval == MBEDTLS_ERR_SSL_WANT_READ || rval == MBEDTLS_ERR_SSL_WANT_WRITE)
821 {
822 break;
823 }
824 else
825 {
826 switch (rval)
827 {
828 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
829 mbedtls_ssl_close_notify(&mSsl);
830 ExitNow(shouldDisconnect = true);
831 OT_UNREACHABLE_CODE(break);
832
833 case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
834 break;
835
836 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
837 mbedtls_ssl_close_notify(&mSsl);
838 ExitNow(shouldDisconnect = true);
839 OT_UNREACHABLE_CODE(break);
840
841 case MBEDTLS_ERR_SSL_INVALID_MAC:
842 if (mSsl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
843 {
844 mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
845 MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);
846 ExitNow(shouldDisconnect = true);
847 }
848
849 break;
850
851 default:
852 if (mSsl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
853 {
854 mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
855 MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
856 ExitNow(shouldDisconnect = true);
857 }
858
859 break;
860 }
861
862 mbedtls_ssl_session_reset(&mSsl);
863 if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
864 {
865 mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
866 }
867 break;
868 }
869 }
870
871 exit:
872
873 if (shouldDisconnect)
874 {
875 Disconnect();
876 }
877 }
878
HandleMbedtlsDebug(void * aContext,int aLevel,const char * aFile,int aLine,const char * aStr)879 void Dtls::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr)
880 {
881 static_cast<Dtls *>(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr);
882 }
883
HandleMbedtlsDebug(int aLevel,const char * aFile,int aLine,const char * aStr)884 void Dtls::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr)
885 {
886 OT_UNUSED_VARIABLE(aStr);
887 OT_UNUSED_VARIABLE(aFile);
888 OT_UNUSED_VARIABLE(aLine);
889
890 switch (aLevel)
891 {
892 case 1:
893 otLogCritMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
894 break;
895
896 case 2:
897 otLogWarnMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
898 break;
899
900 case 3:
901 otLogInfoMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
902 break;
903
904 case 4:
905 default:
906 otLogDebgMbedTls("[%hu] %s", mSocket.GetSockName().mPort, aStr);
907 break;
908 }
909 }
910
HandleDtlsSend(const uint8_t * aBuf,uint16_t aLength,Message::SubType aMessageSubType)911 Error Dtls::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType)
912 {
913 Error error = kErrorNone;
914 ot::Message *message = nullptr;
915
916 VerifyOrExit((message = mSocket.NewMessage(0)) != nullptr, error = kErrorNoBufs);
917 message->SetSubType(aMessageSubType);
918 message->SetLinkSecurityEnabled(mLayerTwoSecurity);
919
920 SuccessOrExit(error = message->AppendBytes(aBuf, aLength));
921
922 // Set message sub type in case Joiner Finalize Response is appended to the message.
923 if (aMessageSubType != Message::kSubTypeNone)
924 {
925 message->SetSubType(aMessageSubType);
926 }
927
928 if (mTransportCallback)
929 {
930 SuccessOrExit(error = mTransportCallback(mTransportContext, *message, mMessageInfo));
931 }
932 else
933 {
934 SuccessOrExit(error = mSocket.SendTo(*message, mMessageInfo));
935 }
936
937 exit:
938 FreeMessageOnError(message, error);
939 return error;
940 }
941
942 } // namespace MeshCoP
943 } // namespace ot
944
945 #endif // OPENTHREAD_CONFIG_DTLS_ENABLE
946