Coverage Report

Created: 2025-05-12 06:47

/src/openthread/src/core/meshcop/secure_transport.cpp
Line
Count
Source (jump to first uncovered line)
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 "secure_transport.hpp"
35
36
#include <mbedtls/debug.h>
37
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
38
#include <mbedtls/pem.h>
39
#endif
40
41
#include "instance/instance.hpp"
42
43
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
44
45
namespace ot {
46
namespace MeshCoP {
47
48
RegisterLogModule("SecTransport");
49
50
//---------------------------------------------------------------------------------------------------------------------
51
// SecureSession
52
53
SecureSession::SecureSession(SecureTransport &aTransport)
54
42.6k
    : mTransport(aTransport)
55
42.6k
{
56
42.6k
    Init();
57
42.6k
}
58
59
void SecureSession::Init(void)
60
44.6k
{
61
44.6k
    mTimerSet       = false;
62
44.6k
    mIsServer       = false;
63
44.6k
    mState          = kStateDisconnected;
64
44.6k
    mMessageSubType = Message::kSubTypeNone;
65
44.6k
    mConnectEvent   = kDisconnectedError;
66
44.6k
    mReceiveMessage = nullptr;
67
44.6k
    mMessageInfo.Clear();
68
69
44.6k
    MarkAsNotUsed();
70
44.6k
    ClearAllBytes(mSsl);
71
44.6k
    ClearAllBytes(mConf);
72
44.6k
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
73
44.6k
    ClearAllBytes(mCookieCtx);
74
44.6k
#endif
75
44.6k
}
76
77
void SecureSession::FreeMbedtls(void)
78
1.96k
{
79
1.96k
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
80
1.96k
    if (mTransport.mDatagramTransport)
81
1.96k
    {
82
1.96k
        mbedtls_ssl_cookie_free(&mCookieCtx);
83
1.96k
    }
84
1.96k
#endif
85
1.96k
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
86
1.96k
    if (mTransport.mExtension != nullptr)
87
0
    {
88
0
        mTransport.mExtension->mEcdheEcdsaInfo.Free();
89
0
    }
90
1.96k
#endif
91
1.96k
    mbedtls_ssl_config_free(&mConf);
92
1.96k
    mbedtls_ssl_free(&mSsl);
93
1.96k
}
94
95
void SecureSession::SetState(State aState)
96
5.94k
{
97
5.94k
    VerifyOrExit(mState != aState);
98
99
4.23k
    LogInfo("Session state: %s -> %s", StateToString(mState), StateToString(aState));
100
4.23k
    mState = aState;
101
102
5.94k
exit:
103
5.94k
    return;
104
4.23k
}
105
106
Error SecureSession::Connect(const Ip6::SockAddr &aSockAddr)
107
0
{
108
0
    Error error;
109
110
0
    VerifyOrExit(mTransport.mIsOpen, error = kErrorInvalidState);
111
0
    VerifyOrExit(!IsSessionInUse(), error = kErrorInvalidState);
112
113
0
    Init();
114
0
    mMessageInfo.SetPeerAddr(aSockAddr.GetAddress());
115
0
    mMessageInfo.SetPeerPort(aSockAddr.mPort);
116
117
0
    SuccessOrExit(error = Setup());
118
119
0
    mTransport.mSessions.Push(*this);
120
121
0
exit:
122
0
    return error;
123
0
}
124
125
void SecureSession::Accept(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
126
1.97k
{
127
1.97k
    mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
128
1.97k
    mMessageInfo.SetPeerPort(aMessageInfo.GetPeerPort());
129
1.97k
    mMessageInfo.SetIsHostInterface(aMessageInfo.IsHostInterface());
130
1.97k
    mMessageInfo.SetSockAddr(aMessageInfo.GetSockAddr());
131
1.97k
    mMessageInfo.SetSockPort(aMessageInfo.GetSockPort());
132
133
1.97k
    mIsServer = true;
134
135
1.97k
    if (Setup() == kErrorNone)
136
221
    {
137
221
        HandleTransportReceive(aMessage);
138
221
    }
139
1.97k
}
140
141
void SecureSession::HandleTransportReceive(Message &aMessage)
142
542
{
143
542
    VerifyOrExit(!IsDisconnected());
144
145
250
#ifdef MBEDTLS_SSL_SRV_C
146
250
    if (IsConnecting())
147
237
    {
148
237
        mbedtls_ssl_set_client_transport_id(&mSsl, mMessageInfo.GetPeerAddr().GetBytes(), sizeof(Ip6::Address));
149
237
    }
150
250
#endif
151
152
250
    mReceiveMessage = &aMessage;
153
250
    Process();
154
250
    mReceiveMessage = nullptr;
155
156
542
exit:
157
542
    return;
158
250
}
159
160
Error SecureSession::Setup(void)
161
1.97k
{
162
1.97k
    Error error = kErrorNone;
163
1.97k
    int   rval  = 0;
164
165
1.97k
    OT_ASSERT(mTransport.mCipherSuite != SecureTransport::kUnspecifiedCipherSuite);
166
167
1.97k
    SetState(kStateInitializing);
168
169
1.97k
    if (mTransport.HasNoRemainingConnectionAttempts())
170
0
    {
171
0
        mConnectEvent = kDisconnectedMaxAttempts;
172
0
        error         = kErrorNoBufs;
173
0
        ExitNow();
174
0
    }
175
176
1.97k
    mTransport.DecremenetRemainingConnectionAttempts();
177
178
    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
179
    // Setup the mbedtls_ssl_config `mConf`.
180
181
1.97k
    mbedtls_ssl_config_init(&mConf);
182
183
1.97k
    rval = mbedtls_ssl_config_defaults(&mConf, mIsServer ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
184
1.97k
                                       mTransport.mDatagramTransport ? MBEDTLS_SSL_TRANSPORT_DATAGRAM
185
1.97k
                                                                     : MBEDTLS_SSL_TRANSPORT_STREAM,
186
1.97k
                                       MBEDTLS_SSL_PRESET_DEFAULT);
187
1.97k
    VerifyOrExit(rval == 0);
188
189
1.97k
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
190
1.97k
    if (mTransport.mVerifyPeerCertificate &&
191
1.97k
        (mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128Ccm8 ||
192
1.97k
         mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128GcmSha256))
193
0
    {
194
0
        mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED);
195
0
    }
196
1.97k
    else
197
1.97k
    {
198
1.97k
        mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE);
199
1.97k
    }
200
1.97k
#endif
201
202
1.97k
    mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr);
203
1.97k
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
204
1.97k
    mbedtls_ssl_conf_min_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2);
205
1.97k
    mbedtls_ssl_conf_max_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2);
206
#else
207
    mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
208
    mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
209
#endif
210
211
1.97k
    {
212
        // We use `kCipherSuites[mCipherSuite]` to look up the cipher
213
        // suites array to pass to `mbedtls_ssl_conf_ciphersuites()`
214
        // associated with `mCipherSuite`. We validate that the `enum`
215
        // values are correct and match the order in the `kCipherSuites[]`
216
        // array.
217
218
1.97k
        struct EnumCheck
219
1.97k
        {
220
1.97k
            InitEnumValidatorCounter();
221
1.97k
            ValidateNextEnum(SecureTransport::kEcjpakeWithAes128Ccm8);
222
1.97k
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
223
1.97k
            ValidateNextEnum(SecureTransport::kPskWithAes128Ccm8);
224
1.97k
#endif
225
1.97k
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
226
1.97k
            ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128Ccm8);
227
1.97k
            ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128GcmSha256);
228
1.97k
#endif
229
1.97k
        };
230
231
1.97k
        mbedtls_ssl_conf_ciphersuites(&mConf, SecureTransport::kCipherSuites[mTransport.mCipherSuite]);
232
1.97k
    }
233
234
1.97k
    if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
235
1.97k
    {
236
1.97k
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
237
1.97k
        mbedtls_ssl_conf_groups(&mConf, SecureTransport::kGroups);
238
#else
239
        mbedtls_ssl_conf_curves(&mConf, SecureTransport::kCurves);
240
#endif
241
1.97k
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
242
1.97k
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
243
1.97k
        mbedtls_ssl_conf_sig_algs(&mConf, SecureTransport::kSignatures);
244
#else
245
        mbedtls_ssl_conf_sig_hashes(&mConf, SecureTransport::kHashes);
246
#endif
247
1.97k
#endif
248
1.97k
    }
249
250
#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
251
    mbedtls_ssl_conf_export_keys_cb(&mConf, SecureTransport::HandleMbedtlsExportKeys, &mTransport);
252
#endif
253
254
1.97k
    mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000);
255
1.97k
    mbedtls_ssl_conf_dbg(&mConf, SecureTransport::HandleMbedtlsDebug, &mTransport);
256
257
    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
258
    // Setup the `Extension` components.
259
260
1.97k
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
261
1.97k
    if (mTransport.mExtension != nullptr)
262
0
    {
263
0
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
264
0
        mTransport.mExtension->mEcdheEcdsaInfo.Init();
265
0
#endif
266
0
        rval = mTransport.mExtension->SetApplicationSecureKeys(mConf);
267
0
        VerifyOrExit(rval == 0);
268
0
    }
269
1.97k
#endif
270
271
    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
272
    // Setup the mbedtls_ssl_cookie_ctx `mCookieCtx`.
273
274
1.97k
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
275
1.97k
    if (mTransport.mDatagramTransport)
276
1.97k
    {
277
1.97k
        mbedtls_ssl_cookie_init(&mCookieCtx);
278
279
1.97k
        if (mIsServer)
280
1.97k
        {
281
1.97k
            rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
282
1.97k
            VerifyOrExit(rval == 0);
283
284
1.97k
            mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx);
285
1.97k
        }
286
1.97k
    }
287
1.97k
#endif
288
289
    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
290
    // Setup the mbedtls_ssl_context `mSsl`.
291
292
1.97k
    mbedtls_ssl_init(&mSsl);
293
294
1.97k
    rval = mbedtls_ssl_setup(&mSsl, &mConf);
295
1.97k
    VerifyOrExit(rval == 0);
296
297
221
    mbedtls_ssl_set_bio(&mSsl, this, HandleMbedtlsTransmit, HandleMbedtlsReceive, /* RecvTimeoutFn */ nullptr);
298
299
221
    if (mTransport.mDatagramTransport)
300
221
    {
301
221
        mbedtls_ssl_set_timer_cb(&mSsl, this, HandleMbedtlsSetTimer, HandleMbedtlsGetTimer);
302
221
    }
303
304
221
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
305
221
    mbedtls_ssl_set_export_keys_cb(&mSsl, SecureTransport::HandleMbedtlsExportKeys, &mTransport);
306
221
#endif
307
308
221
    if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
309
221
    {
310
221
        rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength);
311
221
        VerifyOrExit(rval == 0);
312
221
    }
313
314
221
#if defined(MBEDTLS_X509_CRT_PARSE_C)
315
221
    if (!mIsServer)
316
0
    {
317
0
        mbedtls_ssl_set_hostname(&mSsl, nullptr);
318
0
    }
319
221
#endif
320
321
221
    mReceiveMessage = nullptr;
322
221
    mMessageSubType = Message::kSubTypeNone;
323
324
221
    SetState(kStateConnecting);
325
326
221
    Process();
327
328
1.97k
exit:
329
1.97k
    if (IsInitializing())
330
1.75k
    {
331
1.75k
        error = (error == kErrorNone) ? Crypto::MbedTls::MapError(rval) : error;
332
333
1.75k
        SetState(kStateDisconnected);
334
1.75k
        FreeMbedtls();
335
1.75k
        mTransport.mUpdateTask.Post();
336
1.75k
    }
337
338
1.97k
    return error;
339
221
}
340
341
void SecureSession::Disconnect(ConnectEvent aEvent)
342
1.99k
{
343
1.99k
    VerifyOrExit(mTransport.mIsOpen);
344
1.99k
    VerifyOrExit(IsConnectingOrConnected());
345
346
206
    mbedtls_ssl_close_notify(&mSsl);
347
206
    SetState(kStateDisconnecting);
348
206
    mConnectEvent = aEvent;
349
350
206
    mTimerSet    = false;
351
206
    mTimerFinish = TimerMilli::GetNow() + kGuardTimeNewConnectionMilli;
352
206
    mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
353
354
206
    FreeMbedtls();
355
356
1.99k
exit:
357
1.99k
    return;
358
206
}
359
360
Error SecureSession::Send(Message &aMessage)
361
0
{
362
0
    Error    error  = kErrorNone;
363
0
    uint16_t length = aMessage.GetLength();
364
0
    uint8_t  buffer[kApplicationDataMaxLength];
365
366
0
    VerifyOrExit(length <= sizeof(buffer), error = kErrorNoBufs);
367
368
0
    mMessageSubType = aMessage.GetSubType();
369
0
    aMessage.ReadBytes(0, buffer, length);
370
371
0
    SuccessOrExit(error = Crypto::MbedTls::MapError(mbedtls_ssl_write(&mSsl, buffer, length)));
372
373
0
    aMessage.Free();
374
375
0
exit:
376
0
    return error;
377
0
}
378
379
bool SecureSession::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext)
380
663
{
381
663
    return
382
663
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
383
663
        mbedtls_ssl_is_handshake_over(aSslContext);
384
#else
385
        (aSslContext->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER);
386
#endif
387
663
}
388
389
int SecureSession::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
390
202
{
391
202
    return static_cast<SecureSession *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
392
202
}
393
394
int SecureSession::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
395
202
{
396
202
    Message::SubType msgSubType = mMessageSubType;
397
398
202
    mMessageSubType = Message::kSubTypeNone;
399
400
202
    return mTransport.Transmit(aBuf, aLength, mMessageInfo, msgSubType);
401
202
}
402
403
int SecureSession::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
404
458
{
405
458
    return static_cast<SecureSession *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
406
458
}
407
408
int SecureSession::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
409
458
{
410
458
    int      rval = MBEDTLS_ERR_SSL_WANT_READ;
411
458
    uint16_t readLength;
412
413
458
    VerifyOrExit(mReceiveMessage != nullptr);
414
415
237
    readLength = mReceiveMessage->ReadBytes(mReceiveMessage->GetOffset(), aBuf, static_cast<uint16_t>(aLength));
416
237
    VerifyOrExit(readLength > 0);
417
418
205
    mReceiveMessage->MoveOffset(readLength);
419
205
    rval = static_cast<int>(readLength);
420
421
458
exit:
422
458
    return rval;
423
205
}
424
425
int SecureSession::HandleMbedtlsGetTimer(void *aContext)
426
458
{
427
458
    return static_cast<SecureSession *>(aContext)->HandleMbedtlsGetTimer();
428
458
}
429
430
int SecureSession::HandleMbedtlsGetTimer(void)
431
458
{
432
458
    int rval = 0;
433
434
    // `mbedtls_ssl_get_timer_t` return values:
435
    //   -1 if cancelled
436
    //    0 if none of the delays have passed,
437
    //    1 if only the intermediate delay has passed,
438
    //    2 if the final delay has passed.
439
440
458
    if (!mTimerSet)
441
458
    {
442
458
        rval = -1;
443
458
    }
444
0
    else
445
0
    {
446
0
        TimeMilli now = TimerMilli::GetNow();
447
448
0
        if (now >= mTimerFinish)
449
0
        {
450
0
            rval = 2;
451
0
        }
452
0
        else if (now >= mTimerIntermediate)
453
0
        {
454
0
            rval = 1;
455
0
        }
456
0
    }
457
458
458
    return rval;
459
458
}
460
461
void SecureSession::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
462
221
{
463
221
    static_cast<SecureSession *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
464
221
}
465
466
void SecureSession::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
467
221
{
468
221
    if (aFinish == 0)
469
221
    {
470
221
        mTimerSet = false;
471
221
    }
472
0
    else
473
0
    {
474
0
        TimeMilli now = TimerMilli::GetNow();
475
476
0
        mTimerSet          = true;
477
0
        mTimerIntermediate = now + aIntermediate;
478
0
        mTimerFinish       = now + aFinish;
479
480
0
        mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
481
0
    }
482
221
}
483
484
void SecureSession::HandleTimer(TimeMilli aNow)
485
0
{
486
0
    if (IsConnectingOrConnected())
487
0
    {
488
0
        VerifyOrExit(mTimerSet);
489
490
0
        if (aNow < mTimerFinish)
491
0
        {
492
0
            mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
493
0
            ExitNow();
494
0
        }
495
496
0
        Process();
497
0
        ExitNow();
498
0
    }
499
500
0
    if (IsDisconnecting())
501
0
    {
502
0
        if (aNow < mTimerFinish)
503
0
        {
504
0
            mTransport.mTimer.FireAtIfEarlier(mTimerFinish);
505
0
            ExitNow();
506
0
        }
507
508
0
        SetState(kStateDisconnected);
509
0
        mTransport.mUpdateTask.Post();
510
0
    }
511
512
0
exit:
513
0
    return;
514
0
}
515
516
void SecureSession::Process(void)
517
471
{
518
471
    uint8_t      buf[kMaxContentLen];
519
471
    int          rval;
520
471
    ConnectEvent disconnectEvent;
521
471
    bool         shouldReset;
522
523
471
    while (IsConnectingOrConnected())
524
458
    {
525
458
        if (IsConnecting())
526
458
        {
527
458
            rval = mbedtls_ssl_handshake(&mSsl);
528
529
458
            if (IsMbedtlsHandshakeOver(&mSsl))
530
0
            {
531
0
                SetState(kStateConnected);
532
0
                mConnectEvent = kConnected;
533
0
                mConnectedCallback.InvokeIfSet(mConnectEvent);
534
0
            }
535
458
        }
536
0
        else
537
0
        {
538
0
            rval = mbedtls_ssl_read(&mSsl, buf, sizeof(buf));
539
540
0
            if (rval > 0)
541
0
            {
542
0
                mReceiveCallback.InvokeIfSet(buf, static_cast<uint16_t>(rval));
543
0
                continue;
544
0
            }
545
0
        }
546
547
        // Check `rval` to determine if the connection should be
548
        // disconnected, reset, or if we should wait.
549
550
458
        disconnectEvent = kConnected;
551
458
        shouldReset     = true;
552
553
458
        switch (rval)
554
458
        {
555
0
        case 0:
556
253
        case MBEDTLS_ERR_SSL_WANT_READ:
557
253
        case MBEDTLS_ERR_SSL_WANT_WRITE:
558
253
            shouldReset = false;
559
253
            break;
560
561
0
        case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
562
0
            disconnectEvent = kDisconnectedPeerClosed;
563
0
            break;
564
565
0
        case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
566
0
            break;
567
568
0
        case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
569
0
            disconnectEvent = kDisconnectedError;
570
0
            break;
571
572
0
        case MBEDTLS_ERR_SSL_INVALID_MAC:
573
0
            if (!IsMbedtlsHandshakeOver(&mSsl))
574
0
            {
575
0
                mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
576
0
                                               MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);
577
0
                disconnectEvent = kDisconnectedError;
578
0
            }
579
0
            break;
580
581
205
        default:
582
205
            if (!IsMbedtlsHandshakeOver(&mSsl))
583
205
            {
584
205
                mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
585
205
                                               MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
586
205
                disconnectEvent = kDisconnectedError;
587
205
            }
588
589
205
            break;
590
458
        }
591
592
458
        if (disconnectEvent != kConnected)
593
205
        {
594
205
            Disconnect(disconnectEvent);
595
205
        }
596
253
        else if (shouldReset)
597
0
        {
598
0
            mbedtls_ssl_session_reset(&mSsl);
599
600
0
            if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8)
601
0
            {
602
0
                mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength);
603
0
            }
604
0
        }
605
606
458
        break; // from `while()` loop
607
458
    }
608
471
}
609
610
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
611
612
const char *SecureSession::StateToString(State aState)
613
{
614
    static const char *const kStateStrings[] = {
615
        "Disconnected",  // (0) kStateDisconnected
616
        "Initializing",  // (1) kStateInitializing
617
        "Connecting",    // (2) kStateConnecting
618
        "Connected",     // (3) kStateConnected
619
        "Disconnecting", // (4) kStateDisconnecting
620
    };
621
622
    struct EnumCheck
623
    {
624
        InitEnumValidatorCounter();
625
        ValidateNextEnum(kStateDisconnected);
626
        ValidateNextEnum(kStateInitializing);
627
        ValidateNextEnum(kStateConnecting);
628
        ValidateNextEnum(kStateConnected);
629
        ValidateNextEnum(kStateDisconnecting);
630
    };
631
632
    return kStateStrings[aState];
633
}
634
635
#endif
636
637
//---------------------------------------------------------------------------------------------------------------------
638
// SecureTransport
639
640
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
641
const uint16_t SecureTransport::kGroups[] = {MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE};
642
#else
643
const mbedtls_ecp_group_id SecureTransport::kCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
644
#endif
645
646
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
647
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
648
const uint16_t SecureTransport::kSignatures[] = {MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, MBEDTLS_TLS1_3_SIG_NONE};
649
#else
650
const int SecureTransport::kHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
651
#endif
652
#endif
653
654
const int SecureTransport::kCipherSuites[][2] = {
655
    /* kEcjpakeWithAes128Ccm8         */ {MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, 0},
656
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
657
    /* kPskWithAes128Ccm8             */ {MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, 0},
658
#endif
659
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
660
    /* kEcdheEcdsaWithAes128Ccm8      */ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0},
661
    /* kEcdheEcdsaWithAes128GcmSha256 */ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
662
#endif
663
};
664
665
SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport)
666
63.9k
    : mLayerTwoSecurity(aLayerTwoSecurity)
667
63.9k
    , mDatagramTransport(aDatagramTransport)
668
63.9k
    , mIsOpen(false)
669
63.9k
    , mIsClosing(false)
670
63.9k
    , mVerifyPeerCertificate(true)
671
63.9k
    , mCipherSuite(kUnspecifiedCipherSuite)
672
63.9k
    , mPskLength(0)
673
63.9k
    , mMaxConnectionAttempts(0)
674
63.9k
    , mRemainingConnectionAttempts(0)
675
63.9k
    , mSocket(aInstance, *this)
676
63.9k
    , mTimer(aInstance, HandleTimer, this)
677
63.9k
    , mUpdateTask(aInstance, HandleUpdateTask, this)
678
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
679
63.9k
    , mExtension(nullptr)
680
#endif
681
63.9k
{
682
63.9k
    ClearAllBytes(mPsk);
683
63.9k
    OT_UNUSED_VARIABLE(mVerifyPeerCertificate);
684
63.9k
}
685
686
Error SecureTransport::Open(Ip6::NetifIdentifier aNetifIdentifier)
687
6.15k
{
688
6.15k
    Error error;
689
690
6.15k
    VerifyOrExit(!mIsOpen, error = kErrorAlready);
691
692
5.66k
    SuccessOrExit(error = mSocket.Open(aNetifIdentifier));
693
5.66k
    mIsOpen                      = true;
694
5.66k
    mRemainingConnectionAttempts = mMaxConnectionAttempts;
695
696
6.15k
exit:
697
6.15k
    return error;
698
5.66k
}
699
700
Error SecureTransport::SetMaxConnectionAttempts(uint16_t aMaxAttempts, AutoCloseCallback aCallback, void *aContext)
701
0
{
702
0
    Error error = kErrorNone;
703
704
0
    VerifyOrExit(!mIsOpen, error = kErrorInvalidState);
705
706
0
    mMaxConnectionAttempts = aMaxAttempts;
707
0
    mAutoCloseCallback.Set(aCallback, aContext);
708
709
0
exit:
710
0
    return error;
711
0
}
712
713
void SecureTransport::HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
714
2.74k
{
715
2.74k
    SecureSession *session;
716
717
2.74k
    VerifyOrExit(mIsOpen);
718
719
2.74k
    session = mSessions.FindMatching(aMessageInfo);
720
721
2.74k
    if (session != nullptr)
722
321
    {
723
321
        session->HandleTransportReceive(aMessage);
724
321
        ExitNow();
725
321
    }
726
727
    // A new connection request
728
729
2.41k
    VerifyOrExit(mAcceptCallback.IsSet());
730
731
2.41k
    session = mAcceptCallback.Invoke(aMessageInfo);
732
2.41k
    VerifyOrExit(session != nullptr);
733
734
1.97k
    session->Init();
735
1.97k
    mSessions.Push(*session);
736
737
1.97k
    session->Accept(aMessage, aMessageInfo);
738
739
2.74k
exit:
740
2.74k
    return;
741
1.97k
}
742
743
Error SecureTransport::Bind(uint16_t aPort)
744
5.66k
{
745
5.66k
    Error error;
746
747
5.66k
    VerifyOrExit(mIsOpen, error = kErrorInvalidState);
748
5.66k
    VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
749
750
5.66k
    VerifyOrExit(mSessions.IsEmpty(), error = kErrorInvalidState);
751
752
5.66k
    error = mSocket.Bind(aPort);
753
754
5.66k
exit:
755
5.66k
    return error;
756
5.66k
}
757
758
Error SecureTransport::Bind(TransportCallback aCallback, void *aContext)
759
0
{
760
0
    Error error = kErrorNone;
761
762
0
    VerifyOrExit(mIsOpen, error = kErrorInvalidState);
763
0
    VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready);
764
0
    VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready);
765
766
0
    VerifyOrExit(mSessions.IsEmpty(), error = kErrorInvalidState);
767
768
0
    mTransportCallback.Set(aCallback, aContext);
769
770
0
exit:
771
0
    return error;
772
0
}
773
774
void SecureTransport::Close(void)
775
6.48k
{
776
6.48k
    VerifyOrExit(mIsOpen);
777
5.27k
    VerifyOrExit(!mIsClosing);
778
779
    // `mIsClosing` is used to protect against multiple
780
    // calls to `Close()` and re-entry. As the transport is closed,
781
    // all existing sessions are disconnected, which can trigger
782
    // connect and remove callbacks to be invoked. These callbacks
783
    // may call `Close()` again.
784
785
5.27k
    mIsClosing = true;
786
787
5.27k
    for (SecureSession &session : mSessions)
788
1.78k
    {
789
1.78k
        session.Disconnect(SecureSession::kDisconnectedLocalClosed);
790
1.78k
        session.SetState(SecureSession::kStateDisconnected);
791
1.78k
    }
792
793
5.27k
    RemoveDisconnectedSessions();
794
795
5.27k
    mIsOpen    = false;
796
5.27k
    mIsClosing = false;
797
5.27k
    mTransportCallback.Clear();
798
5.27k
    IgnoreError(mSocket.Close());
799
5.27k
    mTimer.Stop();
800
801
6.48k
exit:
802
6.48k
    return;
803
5.27k
}
804
805
void SecureTransport::RemoveDisconnectedSessions(void)
806
5.27k
{
807
5.27k
    LinkedList<SecureSession> disconnectedSessions;
808
5.27k
    SecureSession            *session;
809
810
5.27k
    mSessions.RemoveAllMatching(disconnectedSessions, SecureSession::kStateDisconnected);
811
812
7.05k
    while ((session = disconnectedSessions.Pop()) != nullptr)
813
1.78k
    {
814
1.78k
        session->mConnectedCallback.InvokeIfSet(session->mConnectEvent);
815
1.78k
        session->MarkAsNotUsed();
816
1.78k
        session->mMessageInfo.Clear();
817
1.78k
        mRemoveSessionCallback.InvokeIfSet(*session);
818
1.78k
    }
819
5.27k
}
820
821
void SecureTransport::DecremenetRemainingConnectionAttempts(void)
822
1.97k
{
823
1.97k
    if (mRemainingConnectionAttempts > 0)
824
0
    {
825
0
        mRemainingConnectionAttempts--;
826
0
    }
827
1.97k
}
828
829
bool SecureTransport::HasNoRemainingConnectionAttempts(void) const
830
1.97k
{
831
1.97k
    return (mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0);
832
1.97k
}
833
834
Error SecureTransport::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
835
5.66k
{
836
5.66k
    Error error = kErrorNone;
837
838
5.66k
    VerifyOrExit(aPskLength <= sizeof(mPsk), error = kErrorInvalidArgs);
839
840
5.66k
    memcpy(mPsk, aPsk, aPskLength);
841
5.66k
    mPskLength   = aPskLength;
842
5.66k
    mCipherSuite = kEcjpakeWithAes128Ccm8;
843
844
5.66k
exit:
845
5.66k
    return error;
846
5.66k
}
847
848
void SecureTransport::SetPsk(const JoinerPskd &aPskd)
849
5.66k
{
850
5.66k
    static_assert(JoinerPskd::kMaxLength <= kPskMaxLength, "The max DTLS PSK length is smaller than joiner PSKd");
851
852
5.66k
    IgnoreError(SetPsk(aPskd.GetBytes(), aPskd.GetLength()));
853
5.66k
}
854
855
int SecureTransport::Transmit(const unsigned char    *aBuf,
856
                              size_t                  aLength,
857
                              const Ip6::MessageInfo &aMessageInfo,
858
                              Message::SubType        aMessageSubType)
859
202
{
860
202
    Error    error   = kErrorNone;
861
202
    Message *message = mSocket.NewMessage();
862
202
    int      rval;
863
864
202
    VerifyOrExit(message != nullptr, error = kErrorNoBufs);
865
202
    message->SetSubType(aMessageSubType);
866
202
    message->SetLinkSecurityEnabled(mLayerTwoSecurity);
867
868
202
    SuccessOrExit(error = message->AppendBytes(aBuf, static_cast<uint16_t>(aLength)));
869
870
202
    if (mTransportCallback.IsSet())
871
0
    {
872
0
        error = mTransportCallback.Invoke(*message, aMessageInfo);
873
0
    }
874
202
    else
875
202
    {
876
202
        error = mSocket.SendTo(*message, aMessageInfo);
877
202
    }
878
879
202
exit:
880
202
    FreeMessageOnError(message, error);
881
882
202
    switch (error)
883
202
    {
884
193
    case kErrorNone:
885
193
        rval = static_cast<int>(aLength);
886
193
        break;
887
888
0
    case kErrorNoBufs:
889
0
        rval = MBEDTLS_ERR_SSL_WANT_WRITE;
890
0
        break;
891
892
9
    default:
893
9
        LogWarnOnError(error, "HandleMbedtlsTransmit");
894
9
        rval = MBEDTLS_ERR_NET_SEND_FAILED;
895
9
        break;
896
202
    }
897
898
202
    return rval;
899
202
}
900
901
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
902
903
void SecureTransport::HandleMbedtlsExportKeys(void                       *aContext,
904
                                              mbedtls_ssl_key_export_type aType,
905
                                              const unsigned char        *aMasterSecret,
906
                                              size_t                      aMasterSecretLen,
907
                                              const unsigned char         aClientRandom[32],
908
                                              const unsigned char         aServerRandom[32],
909
                                              mbedtls_tls_prf_types       aTlsPrfType)
910
0
{
911
0
    static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen,
912
0
                                                                      aClientRandom, aServerRandom, aTlsPrfType);
913
0
}
914
915
void SecureTransport::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType,
916
                                              const unsigned char        *aMasterSecret,
917
                                              size_t                      aMasterSecretLen,
918
                                              const unsigned char         aClientRandom[32],
919
                                              const unsigned char         aServerRandom[32],
920
                                              mbedtls_tls_prf_types       aTlsPrfType)
921
0
{
922
0
    Crypto::Sha256::Hash kek;
923
0
    Crypto::Sha256       sha256;
924
0
    unsigned char        keyBlock[kSecureTransportKeyBlockSize];
925
0
    unsigned char        randBytes[2 * kSecureTransportRandomBufferSize];
926
927
0
    VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8);
928
0
    VerifyOrExit(aType == MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET);
929
930
0
    memcpy(randBytes, aServerRandom, kSecureTransportRandomBufferSize);
931
0
    memcpy(randBytes + kSecureTransportRandomBufferSize, aClientRandom, kSecureTransportRandomBufferSize);
932
933
    // Retrieve the Key block from Master secret
934
0
    mbedtls_ssl_tls_prf(aTlsPrfType, aMasterSecret, aMasterSecretLen, "key expansion", randBytes, sizeof(randBytes),
935
0
                        keyBlock, sizeof(keyBlock));
936
937
0
    sha256.Start();
938
0
    sha256.Update(keyBlock, kSecureTransportKeyBlockSize);
939
0
    sha256.Finish(kek);
940
941
0
    mTimer.Get<KeyManager>().SetKek(kek.GetBytes());
942
943
0
exit:
944
0
    return;
945
0
}
946
947
#else
948
949
int SecureTransport::HandleMbedtlsExportKeys(void *aContext,
950
                                             const unsigned char *aMasterSecret,
951
                                             const unsigned char *aKeyBlock,
952
                                             size_t aMacLength,
953
                                             size_t aKeyLength,
954
                                             size_t aIvLength)
955
{
956
    return static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength,
957
                                                                             aKeyLength, aIvLength);
958
}
959
960
int SecureTransport::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
961
                                             const unsigned char *aKeyBlock,
962
                                             size_t aMacLength,
963
                                             size_t aKeyLength,
964
                                             size_t aIvLength)
965
{
966
    OT_UNUSED_VARIABLE(aMasterSecret);
967
968
    Crypto::Sha256::Hash kek;
969
    Crypto::Sha256 sha256;
970
971
    VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8);
972
973
    sha256.Start();
974
    sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength));
975
    sha256.Finish(kek);
976
977
    mTimer.Get<KeyManager>().SetKek(kek.GetBytes());
978
979
exit:
980
    return 0;
981
}
982
983
#endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000)
984
985
void SecureTransport::HandleUpdateTask(Tasklet &aTasklet)
986
0
{
987
0
    static_cast<SecureTransport *>(static_cast<TaskletContext &>(aTasklet).GetContext())->HandleUpdateTask();
988
0
}
989
990
void SecureTransport::HandleUpdateTask(void)
991
0
{
992
0
    RemoveDisconnectedSessions();
993
994
0
    if (mSessions.IsEmpty() && HasNoRemainingConnectionAttempts())
995
0
    {
996
0
        Close();
997
0
        mAutoCloseCallback.InvokeIfSet();
998
0
    }
999
0
}
1000
1001
void SecureTransport::HandleTimer(Timer &aTimer)
1002
0
{
1003
0
    static_cast<SecureTransport *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer();
1004
0
}
1005
1006
void SecureTransport::HandleTimer(void)
1007
0
{
1008
0
    TimeMilli now = TimerMilli::GetNow();
1009
1010
0
    VerifyOrExit(mIsOpen);
1011
1012
0
    for (SecureSession &session : mSessions)
1013
0
    {
1014
0
        session.HandleTimer(now);
1015
0
    }
1016
1017
0
exit:
1018
0
    return;
1019
0
}
1020
1021
void SecureTransport::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr)
1022
0
{
1023
0
    static_cast<SecureTransport *>(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr);
1024
0
}
1025
1026
void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr)
1027
0
{
1028
0
    LogLevel logLevel = kLogLevelDebg;
1029
1030
0
    switch (aLevel)
1031
0
    {
1032
0
    case 1:
1033
0
        logLevel = kLogLevelCrit;
1034
0
        break;
1035
1036
0
    case 2:
1037
0
        logLevel = kLogLevelWarn;
1038
0
        break;
1039
1040
0
    case 3:
1041
0
        logLevel = kLogLevelInfo;
1042
0
        break;
1043
1044
0
    case 4:
1045
0
    default:
1046
0
        break;
1047
0
    }
1048
1049
0
    LogAt(logLevel, "[%u] %s", mSocket.GetSockName().mPort, aStr);
1050
1051
0
    OT_UNUSED_VARIABLE(aStr);
1052
0
    OT_UNUSED_VARIABLE(aFile);
1053
0
    OT_UNUSED_VARIABLE(aLine);
1054
0
    OT_UNUSED_VARIABLE(logLevel);
1055
0
}
1056
1057
//---------------------------------------------------------------------------------------------------------------------
1058
// SecureTransport::Extension
1059
1060
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
1061
1062
int SecureTransport::Extension::SetApplicationSecureKeys(mbedtls_ssl_config &aConfig)
1063
0
{
1064
0
    int rval = 0;
1065
1066
0
    switch (mSecureTransport.mCipherSuite)
1067
0
    {
1068
0
    case kEcjpakeWithAes128Ccm8:
1069
        // PSK will be set on `mbedtls_ssl_context` when set up.
1070
0
        break;
1071
1072
0
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
1073
0
    case kEcdheEcdsaWithAes128Ccm8:
1074
0
    case kEcdheEcdsaWithAes128GcmSha256:
1075
0
        rval = mEcdheEcdsaInfo.SetSecureKeys(aConfig);
1076
0
        VerifyOrExit(rval == 0);
1077
0
        break;
1078
0
#endif
1079
1080
0
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
1081
0
    case kPskWithAes128Ccm8:
1082
0
        rval = mPskInfo.SetSecureKeys(aConfig);
1083
0
        VerifyOrExit(rval == 0);
1084
0
        break;
1085
0
#endif
1086
1087
0
    default:
1088
0
        LogCrit("Application Coap Secure: Not supported cipher.");
1089
0
        rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
1090
0
        ExitNow();
1091
0
    }
1092
1093
0
exit:
1094
0
    return rval;
1095
0
}
1096
1097
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
1098
1099
void SecureTransport::Extension::EcdheEcdsaInfo::Init(void)
1100
0
{
1101
0
    mbedtls_x509_crt_init(&mCaChain);
1102
0
    mbedtls_x509_crt_init(&mOwnCert);
1103
0
    mbedtls_pk_init(&mPrivateKey);
1104
0
}
1105
1106
void SecureTransport::Extension::EcdheEcdsaInfo::Free(void)
1107
0
{
1108
0
    mbedtls_x509_crt_free(&mCaChain);
1109
0
    mbedtls_x509_crt_free(&mOwnCert);
1110
0
    mbedtls_pk_free(&mPrivateKey);
1111
0
}
1112
1113
int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig)
1114
0
{
1115
0
    int rval = 0;
1116
1117
0
    if (mCaChainSrc != nullptr)
1118
0
    {
1119
0
        rval = mbedtls_x509_crt_parse(&mCaChain, static_cast<const unsigned char *>(mCaChainSrc),
1120
0
                                      static_cast<size_t>(mCaChainLength));
1121
0
        VerifyOrExit(rval == 0);
1122
0
        mbedtls_ssl_conf_ca_chain(&aConfig, &mCaChain, nullptr);
1123
0
    }
1124
1125
0
    if (mOwnCertSrc != nullptr && mPrivateKeySrc != nullptr)
1126
0
    {
1127
0
        rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast<const unsigned char *>(mOwnCertSrc),
1128
0
                                      static_cast<size_t>(mOwnCertLength));
1129
0
        VerifyOrExit(rval == 0);
1130
1131
0
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
1132
0
        rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc),
1133
0
                                    static_cast<size_t>(mPrivateKeyLength), nullptr, 0,
1134
0
                                    Crypto::MbedTls::CryptoSecurePrng, nullptr);
1135
#else
1136
        rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc),
1137
                                    static_cast<size_t>(mPrivateKeyLength), nullptr, 0);
1138
#endif
1139
0
        VerifyOrExit(rval == 0);
1140
0
        rval = mbedtls_ssl_conf_own_cert(&aConfig, &mOwnCert, &mPrivateKey);
1141
0
    }
1142
1143
0
exit:
1144
0
    return rval;
1145
0
}
1146
1147
void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate,
1148
                                                uint32_t       aX509CertLength,
1149
                                                const uint8_t *aPrivateKey,
1150
                                                uint32_t       aPrivateKeyLength)
1151
0
{
1152
0
    OT_ASSERT(aX509CertLength > 0);
1153
0
    OT_ASSERT(aX509Certificate != nullptr);
1154
1155
0
    OT_ASSERT(aPrivateKeyLength > 0);
1156
0
    OT_ASSERT(aPrivateKey != nullptr);
1157
1158
0
    mEcdheEcdsaInfo.mOwnCertSrc       = aX509Certificate;
1159
0
    mEcdheEcdsaInfo.mOwnCertLength    = aX509CertLength;
1160
0
    mEcdheEcdsaInfo.mPrivateKeySrc    = aPrivateKey;
1161
0
    mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength;
1162
1163
0
    mSecureTransport.mCipherSuite =
1164
0
        mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256;
1165
0
}
1166
1167
void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain,
1168
                                                       uint32_t       aX509CaCertChainLength)
1169
0
{
1170
0
    OT_ASSERT(aX509CaCertChainLength > 0);
1171
0
    OT_ASSERT(aX509CaCertificateChain != nullptr);
1172
1173
0
    mEcdheEcdsaInfo.mCaChainSrc    = aX509CaCertificateChain;
1174
0
    mEcdheEcdsaInfo.mCaChainLength = aX509CaCertChainLength;
1175
0
}
1176
1177
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
1178
1179
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
1180
1181
int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const
1182
0
{
1183
0
    return mbedtls_ssl_conf_psk(&aConfig, static_cast<const unsigned char *>(mPreSharedKey), mPreSharedKeyLength,
1184
0
                                static_cast<const unsigned char *>(mPreSharedKeyIdentity), mPreSharedKeyIdLength);
1185
0
}
1186
1187
void SecureTransport::Extension::SetPreSharedKey(const uint8_t *aPsk,
1188
                                                 uint16_t       aPskLength,
1189
                                                 const uint8_t *aPskIdentity,
1190
                                                 uint16_t       aPskIdLength)
1191
0
{
1192
0
    OT_ASSERT(aPsk != nullptr);
1193
0
    OT_ASSERT(aPskIdentity != nullptr);
1194
0
    OT_ASSERT(aPskLength > 0);
1195
0
    OT_ASSERT(aPskIdLength > 0);
1196
1197
0
    mPskInfo.mPreSharedKey         = aPsk;
1198
0
    mPskInfo.mPreSharedKeyLength   = aPskLength;
1199
0
    mPskInfo.mPreSharedKeyIdentity = aPskIdentity;
1200
0
    mPskInfo.mPreSharedKeyIdLength = aPskIdLength;
1201
1202
0
    mSecureTransport.mCipherSuite = kPskWithAes128Ccm8;
1203
0
}
1204
1205
#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
1206
1207
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
1208
Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert,
1209
                                                           size_t        *aCertLength,
1210
                                                           size_t         aCertBufferSize)
1211
{
1212
    Error          error   = kErrorNone;
1213
    SecureSession *session = mSecureTransport.mSessions.GetHead();
1214
1215
    VerifyOrExit(session != nullptr, error = kErrorInvalidState);
1216
    VerifyOrExit(session->IsConnected(), error = kErrorInvalidState);
1217
1218
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
1219
    VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
1220
                                       session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
1221
                                       session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) ==
1222
                     0,
1223
                 error = kErrorNoBufs);
1224
#else
1225
    VerifyOrExit(
1226
        mbedtls_base64_encode(
1227
            aPeerCert, aCertBufferSize, aCertLength,
1228
            session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
1229
            session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(
1230
                len)) == 0,
1231
        error = kErrorNoBufs);
1232
#endif
1233
1234
exit:
1235
    return error;
1236
}
1237
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
1238
1239
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
1240
Error SecureTransport::Extension::GetPeerCertificateDer(uint8_t *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
1241
{
1242
    Error          error   = kErrorNone;
1243
    SecureSession *session = mSecureTransport.mSessions.GetHead();
1244
1245
    VerifyOrExit(session->IsConnected(), error = kErrorInvalidState);
1246
1247
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
1248
    VerifyOrExit(session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len < aCertBufferSize,
1249
                 error = kErrorNoBufs);
1250
1251
    *aCertLength = session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len;
1252
    memcpy(aPeerCert, session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p, *aCertLength);
1253
1254
#else
1255
    VerifyOrExit(
1256
        session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len) <
1257
            aCertBufferSize,
1258
        error = kErrorNoBufs);
1259
1260
    *aCertLength =
1261
        session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len);
1262
    memcpy(aPeerCert,
1263
           session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
1264
           *aCertLength);
1265
#endif
1266
1267
exit:
1268
    return error;
1269
}
1270
1271
Error SecureTransport::Extension::GetPeerSubjectAttributeByOid(const char *aOid,
1272
                                                               size_t      aOidLength,
1273
                                                               uint8_t    *aAttributeBuffer,
1274
                                                               size_t     *aAttributeLength,
1275
                                                               int        *aAsn1Type)
1276
{
1277
    Error                          error = kErrorNone;
1278
    const mbedtls_asn1_named_data *data;
1279
    size_t                         length;
1280
    size_t                         attributeBufferSize;
1281
    SecureSession                 *session;
1282
    mbedtls_x509_crt              *peerCert;
1283
1284
    session = mSecureTransport.mSessions.GetHead();
1285
    VerifyOrExit(session != nullptr, error = kErrorInvalidState);
1286
1287
    peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&session->mSsl));
1288
1289
    VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
1290
    attributeBufferSize = *aAttributeLength;
1291
    *aAttributeLength   = 0;
1292
1293
    VerifyOrExit(aAttributeBuffer != nullptr, error = kErrorNoBufs);
1294
    VerifyOrExit(peerCert != nullptr, error = kErrorInvalidState);
1295
1296
    data = mbedtls_asn1_find_named_data(&peerCert->subject, aOid, aOidLength);
1297
    VerifyOrExit(data != nullptr, error = kErrorNotFound);
1298
1299
    length = data->val.len;
1300
    VerifyOrExit(length <= attributeBufferSize, error = kErrorNoBufs);
1301
    *aAttributeLength = length;
1302
1303
    if (aAsn1Type != nullptr)
1304
    {
1305
        *aAsn1Type = data->val.tag;
1306
    }
1307
1308
    memcpy(aAttributeBuffer, data->val.p, length);
1309
1310
exit:
1311
    return error;
1312
}
1313
1314
Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int      aThreadOidDescriptor,
1315
                                                                        uint8_t *aAttributeBuffer,
1316
                                                                        size_t  *aAttributeLength)
1317
{
1318
    Error                   error;
1319
    SecureSession          *session = mSecureTransport.mSessions.GetHead();
1320
    const mbedtls_x509_crt *cert;
1321
1322
    VerifyOrExit(session != nullptr, error = kErrorInvalidState);
1323
    cert  = mbedtls_ssl_get_peer_cert(&session->mSsl);
1324
    error = GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
1325
1326
exit:
1327
    return error;
1328
}
1329
1330
#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
1331
1332
Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int      aThreadOidDescriptor,
1333
                                                                       uint8_t *aAttributeBuffer,
1334
                                                                       size_t  *aAttributeLength)
1335
0
{
1336
0
    const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert;
1337
1338
0
    return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
1339
0
}
1340
1341
Error SecureTransport::Extension::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
1342
                                                                    int                     aThreadOidDescriptor,
1343
                                                                    uint8_t                *aAttributeBuffer,
1344
                                                                    size_t                 *aAttributeLength)
1345
0
{
1346
0
    Error            error  = kErrorNotFound;
1347
0
    char             oid[9] = {0x2B, 0x06, 0x01, 0x04, 0x01, static_cast<char>(0x82), static_cast<char>(0xDF),
1348
0
                               0x2A, 0x00}; // 1.3.6.1.4.1.44970.0
1349
0
    mbedtls_x509_buf v3_ext;
1350
0
    unsigned char   *p, *end, *endExtData;
1351
0
    size_t           len;
1352
0
    size_t           attributeBufferSize;
1353
0
    mbedtls_x509_buf extnOid;
1354
0
    int              ret, isCritical;
1355
1356
0
    VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
1357
0
    attributeBufferSize = *aAttributeLength;
1358
0
    *aAttributeLength   = 0;
1359
1360
0
    VerifyOrExit(aCert != nullptr, error = kErrorInvalidState);
1361
0
    v3_ext = aCert->v3_ext;
1362
0
    p      = v3_ext.p;
1363
0
    VerifyOrExit(p != nullptr, error = kErrorInvalidState);
1364
0
    end = p + v3_ext.len;
1365
0
    VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0,
1366
0
                 error = kErrorParse);
1367
0
    VerifyOrExit(end == p + len, error = kErrorParse);
1368
1369
0
    VerifyOrExit(aThreadOidDescriptor < 128, error = kErrorNotImplemented);
1370
0
    oid[sizeof(oid) - 1] = static_cast<char>(aThreadOidDescriptor);
1371
1372
0
    while (p < end)
1373
0
    {
1374
0
        isCritical = 0;
1375
0
        VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0,
1376
0
                     error = kErrorParse);
1377
0
        endExtData = p + len;
1378
1379
        // Get extension ID
1380
0
        VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &extnOid.len, MBEDTLS_ASN1_OID) == 0, error = kErrorParse);
1381
0
        extnOid.tag = MBEDTLS_ASN1_OID;
1382
0
        extnOid.p   = p;
1383
0
        p += extnOid.len;
1384
1385
        // Get optional critical
1386
0
        ret = mbedtls_asn1_get_bool(&p, endExtData, &isCritical);
1387
0
        VerifyOrExit(ret == 0 || ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = kErrorParse);
1388
1389
        // Data must be octet string type, see https://datatracker.ietf.org/doc/html/rfc5280#section-4.1
1390
0
        VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &len, MBEDTLS_ASN1_OCTET_STRING) == 0, error = kErrorParse);
1391
0
        VerifyOrExit(endExtData == p + len, error = kErrorParse);
1392
1393
        // TODO: extensions with isCritical == 1 that are unknown should lead to rejection of the entire cert.
1394
0
        if (extnOid.len == sizeof(oid) && memcmp(extnOid.p, oid, sizeof(oid)) == 0)
1395
0
        {
1396
            // per RFC 5280, octet string must contain ASN.1 Type Length Value octets
1397
0
            VerifyOrExit(len >= 2, error = kErrorParse);
1398
0
            VerifyOrExit(*(p + 1) == len - 2, error = kErrorParse); // check TLV Length, not Type.
1399
0
            *aAttributeLength = len - 2; // strip the ASN.1 Type Length bytes from embedded TLV
1400
1401
0
            if (aAttributeBuffer != nullptr)
1402
0
            {
1403
0
                VerifyOrExit(*aAttributeLength <= attributeBufferSize, error = kErrorNoBufs);
1404
0
                memcpy(aAttributeBuffer, p + 2, *aAttributeLength);
1405
0
            }
1406
1407
0
            error = kErrorNone;
1408
0
            break;
1409
0
        }
1410
0
        p += len;
1411
0
    }
1412
1413
0
exit:
1414
0
    return error;
1415
0
}
1416
1417
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
1418
1419
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
1420
1421
//---------------------------------------------------------------------------------------------------------------------
1422
// Tls
1423
1424
SecureSession *Tls::HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo)
1425
{
1426
    OT_UNUSED_VARIABLE(aMessageInfo);
1427
1428
    return static_cast<Tls *>(aContext)->HandleAccept();
1429
}
1430
1431
SecureSession *Tls::HandleAccept(void) { return IsSessionInUse() ? nullptr : static_cast<SecureSession *>(this); }
1432
1433
#endif
1434
1435
} // namespace MeshCoP
1436
} // namespace ot
1437
1438
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE