Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/src/ssl_api_dtls.c
Line
Count
Source
1
/* ssl_api_dtls.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#if !defined(WOLFSSL_SSL_API_DTLS_INCLUDED)
25
    #ifndef WOLFSSL_IGNORE_FILE_WARN
26
        #warning ssl_api_dtls.c does not need to be compiled separately from ssl.c
27
    #endif
28
#else
29
30
#ifndef WOLFCRYPT_ONLY
31
32
#ifdef WOLFSSL_DTLS
33
/* Set the file descriptor for an already connected DTLS object.
34
 *
35
 * @param [in] ssl  SSL/TLS object.
36
 * @param [in] fd   Connected socket file descriptor.
37
 * @return  WOLFSSL_SUCCESS on success.
38
 * @return  BAD_FUNC_ARG when ssl is NULL.
39
 */
40
int wolfSSL_set_dtls_fd_connected(WOLFSSL* ssl, int fd)
41
{
42
    int ret;
43
44
    WOLFSSL_ENTER("wolfSSL_set_dtls_fd_connected");
45
46
    if (ssl == NULL) {
47
        return BAD_FUNC_ARG;
48
    }
49
50
    ret = wolfSSL_set_fd(ssl, fd);
51
    if (ret == WOLFSSL_SUCCESS)
52
        ssl->buffers.dtlsCtx.connected = 1;
53
54
    return ret;
55
}
56
#endif
57
58
/* Determine whether the object is configured for DTLS.
59
 *
60
 * @param [in] ssl  SSL/TLS object.
61
 * @return  1 when using DTLS.
62
 * @return  0 otherwise, or when ssl is NULL.
63
 */
64
int wolfSSL_dtls(WOLFSSL* ssl)
65
0
{
66
0
    int dtlsOpt = 0;
67
0
    if (ssl)
68
0
        dtlsOpt = ssl->options.dtls;
69
0
    return dtlsOpt;
70
0
}
71
72
#ifndef WOLFSSL_LEANPSK
73
#if defined(WOLFSSL_DTLS) && defined(XINET_PTON) && \
74
    !defined(WOLFSSL_NO_SOCK) && defined(HAVE_SOCKADDR)
75
/* Create a DTLS peer address from a port and IPv4 address string.
76
 *
77
 * The returned object must be freed with wolfSSL_dtls_free_peer().
78
 *
79
 * @param [in] port  Port number.
80
 * @param [in] ip    Dotted-decimal IPv4 address string.
81
 * @return  Newly allocated peer address on success.
82
 * @return  NULL on allocation error or when the address is invalid.
83
 */
84
void* wolfSSL_dtls_create_peer(int port, char* ip)
85
{
86
    SOCKADDR_IN *addr;
87
    addr = (SOCKADDR_IN*)XMALLOC(sizeof(*addr), NULL,
88
            DYNAMIC_TYPE_SOCKADDR);
89
    if (addr == NULL) {
90
        return NULL;
91
    }
92
93
    addr->sin_family = AF_INET;
94
    addr->sin_port = XHTONS((word16)port);
95
    if (XINET_PTON(AF_INET, ip, &addr->sin_addr) < 1) {
96
        XFREE(addr, NULL, DYNAMIC_TYPE_SOCKADDR);
97
        return NULL;
98
    }
99
100
    return addr;
101
}
102
103
/* Free a DTLS peer address created with wolfSSL_dtls_create_peer().
104
 *
105
 * @param [in] addr  Peer address to free.
106
 * @return  WOLFSSL_SUCCESS always.
107
 */
108
int wolfSSL_dtls_free_peer(void* addr)
109
{
110
    XFREE(addr, NULL, DYNAMIC_TYPE_SOCKADDR);
111
    return WOLFSSL_SUCCESS;
112
}
113
#endif
114
115
#ifdef WOLFSSL_DTLS
116
/* Store a socket address into a socket address holder, resizing as needed.
117
 *
118
 * A NULL or zero-length peer frees the holder's buffer. An address that fits
119
 * the buffer already there is copied over it rather than reallocated:
120
 * EmbedSendTo reads peer.sa without taking peerLock, so freeing it on every
121
 * update would widen that race rather than leave it as it is.
122
 *
123
 * The record layer promotes a pending peer through this while already holding
124
 * peerLock, so it takes no lock of its own.
125
 *
126
 * @param [in, out] sockAddr  Socket address holder.
127
 * @param [in]      peer      Socket address data, may be NULL to free.
128
 * @param [in]      peerSz    Length of socket address data in bytes.
129
 * @param [in]      heap      Heap hint for dynamic memory allocation.
130
 * @return  WOLFSSL_SUCCESS on success.
131
 * @return  WOLFSSL_FAILURE on allocation error.
132
 */
133
int wolfssl_local_SockAddrSet(WOLFSSL_SOCKADDR* sockAddr, void* peer,
134
                              unsigned int peerSz, void* heap)
135
{
136
    if (peer == NULL || peerSz == 0) {
137
        if (sockAddr->sa != NULL)
138
            XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
139
        sockAddr->sa = NULL;
140
        sockAddr->sz = 0;
141
        sockAddr->bufSz = 0;
142
        return WOLFSSL_SUCCESS;
143
    }
144
145
    if (peerSz > sockAddr->bufSz) {
146
        if (sockAddr->sa != NULL)
147
            XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
148
        sockAddr->sa =
149
                (void*)XMALLOC(peerSz, heap, DYNAMIC_TYPE_SOCKADDR);
150
        if (sockAddr->sa == NULL) {
151
            sockAddr->sz = 0;
152
            sockAddr->bufSz = 0;
153
            return WOLFSSL_FAILURE;
154
        }
155
        sockAddr->bufSz = peerSz;
156
    }
157
    XMEMCPY(sockAddr->sa, peer, peerSz);
158
    sockAddr->sz = peerSz;
159
    return WOLFSSL_SUCCESS;
160
}
161
#endif
162
163
/* Set the DTLS peer address on the object.
164
 *
165
 * @param [in] ssl     SSL/TLS object.
166
 * @param [in] peer    Peer socket address, may be NULL to clear.
167
 * @param [in] peerSz  Length of peer address in bytes.
168
 * @return  WOLFSSL_SUCCESS on success.
169
 * @return  WOLFSSL_FAILURE when ssl is NULL or on error.
170
 * @return  WOLFSSL_NOT_IMPLEMENTED when DTLS is not compiled in.
171
 */
172
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
173
0
{
174
#ifdef WOLFSSL_DTLS
175
    int ret;
176
177
    if (ssl == NULL)
178
        return WOLFSSL_FAILURE;
179
#ifdef WOLFSSL_RW_THREADED
180
    if (wc_LockRwLock_Wr(&ssl->buffers.dtlsCtx.peerLock) != 0)
181
        return WOLFSSL_FAILURE;
182
#endif
183
    ret = wolfssl_local_SockAddrSet(&ssl->buffers.dtlsCtx.peer, peer, peerSz,
184
            ssl->heap);
185
    if (ret == WOLFSSL_SUCCESS && !(peer == NULL || peerSz == 0))
186
        ssl->buffers.dtlsCtx.userSet = 1;
187
    else
188
        ssl->buffers.dtlsCtx.userSet = 0;
189
#ifdef WOLFSSL_RW_THREADED
190
    if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
191
        ret = WOLFSSL_FAILURE;
192
#endif
193
    return ret;
194
#else
195
0
    (void)ssl;
196
0
    (void)peer;
197
0
    (void)peerSz;
198
0
    return WOLFSSL_NOT_IMPLEMENTED;
199
0
#endif
200
0
}
201
202
#if defined(WOLFSSL_DTLS_CID) && !defined(WOLFSSL_NO_SOCK)
203
/* Set the pending DTLS peer address on the object.
204
 *
205
 * Used with connection ID to stage a change of peer address.
206
 *
207
 * @param [in] ssl     SSL/TLS object.
208
 * @param [in] peer    Peer socket address.
209
 * @param [in] peerSz  Length of peer address in bytes.
210
 * @return  WOLFSSL_SUCCESS on success.
211
 * @return  WOLFSSL_FAILURE when ssl is NULL or on error.
212
 * @return  WOLFSSL_NOT_IMPLEMENTED when DTLS is not compiled in.
213
 */
214
int wolfSSL_dtls_set_pending_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
215
{
216
#ifdef WOLFSSL_DTLS
217
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
218
219
    if (ssl == NULL)
220
        return WOLFSSL_FAILURE;
221
#ifdef WOLFSSL_RW_THREADED
222
    if (wc_LockRwLock_Wr(&ssl->buffers.dtlsCtx.peerLock) != 0)
223
        return WOLFSSL_FAILURE;
224
#endif
225
    if (ssl->buffers.dtlsCtx.peer.sa != NULL &&
226
            ssl->buffers.dtlsCtx.peer.sz == peerSz &&
227
            sockAddrEqual((SOCKADDR_S*)ssl->buffers.dtlsCtx.peer.sa,
228
                    (XSOCKLENT)ssl->buffers.dtlsCtx.peer.sz, (SOCKADDR_S*)peer,
229
                    (XSOCKLENT)peerSz)) {
230
        /* Already the current peer. */
231
        if (ssl->buffers.dtlsCtx.pendingPeer.sa != NULL) {
232
            /* Clear any other pendingPeer */
233
            XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
234
                  DYNAMIC_TYPE_SOCKADDR);
235
            ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
236
            ssl->buffers.dtlsCtx.pendingPeer.sz = 0;
237
            ssl->buffers.dtlsCtx.pendingPeer.bufSz = 0;
238
        }
239
        ret = WOLFSSL_SUCCESS;
240
    }
241
    else {
242
        ret = wolfssl_local_SockAddrSet(&ssl->buffers.dtlsCtx.pendingPeer,
243
                peer, peerSz, ssl->heap);
244
    }
245
    if (ret == WOLFSSL_SUCCESS)
246
        ssl->buffers.dtlsCtx.processingPendingRecord = 0;
247
#ifdef WOLFSSL_RW_THREADED
248
    if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
249
        ret = WOLFSSL_FAILURE;
250
#endif
251
    return ret;
252
#else
253
    (void)ssl;
254
    (void)peer;
255
    (void)peerSz;
256
    return WOLFSSL_NOT_IMPLEMENTED;
257
#endif
258
}
259
#endif /* WOLFSSL_DTLS_CID && !WOLFSSL_NO_SOCK */
260
261
/* Get a copy of the DTLS peer address from the object.
262
 *
263
 * @param [in]      ssl     SSL/TLS object.
264
 * @param [out]     peer    Buffer to hold the peer address.
265
 * @param [in, out] peerSz  In: size of buffer. Out: length of address.
266
 * @return  WOLFSSL_SUCCESS on success.
267
 * @return  WOLFSSL_FAILURE when ssl is NULL or the buffer is too small.
268
 * @return  WOLFSSL_NOT_IMPLEMENTED when DTLS is not compiled in.
269
 */
270
int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
271
0
{
272
#ifdef WOLFSSL_DTLS
273
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
274
    if (ssl == NULL)
275
        return WOLFSSL_FAILURE;
276
#ifdef WOLFSSL_RW_THREADED
277
    if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
278
        return WOLFSSL_FAILURE;
279
#endif
280
    if (peer != NULL && peerSz != NULL
281
            && *peerSz >= ssl->buffers.dtlsCtx.peer.sz
282
            && ssl->buffers.dtlsCtx.peer.sa != NULL) {
283
        *peerSz = ssl->buffers.dtlsCtx.peer.sz;
284
        XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
285
        ret = WOLFSSL_SUCCESS;
286
    }
287
#ifdef WOLFSSL_RW_THREADED
288
    if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
289
        ret = WOLFSSL_FAILURE;
290
#endif
291
    return ret;
292
#else
293
0
    (void)ssl;
294
0
    (void)peer;
295
0
    (void)peerSz;
296
0
    return WOLFSSL_NOT_IMPLEMENTED;
297
0
#endif
298
0
}
299
300
/* Get a pointer to the DTLS peer address stored on the object.
301
 *
302
 * @param [in]  ssl     SSL/TLS object.
303
 * @param [out] peer    Pointer to the stored peer address.
304
 * @param [out] peerSz  Length of the peer address in bytes.
305
 * @return  WOLFSSL_SUCCESS on success.
306
 * @return  WOLFSSL_FAILURE when an argument is NULL.
307
 * @return  WOLFSSL_NOT_IMPLEMENTED when DTLS is not compiled in or threaded.
308
 */
309
int wolfSSL_dtls_get0_peer(WOLFSSL* ssl, const void** peer,
310
                           unsigned int* peerSz)
311
0
{
312
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_RW_THREADED)
313
    if (ssl == NULL)
314
        return WOLFSSL_FAILURE;
315
316
    if (peer == NULL || peerSz == NULL)
317
        return WOLFSSL_FAILURE;
318
319
    *peer = ssl->buffers.dtlsCtx.peer.sa;
320
    *peerSz = ssl->buffers.dtlsCtx.peer.sz;
321
    return WOLFSSL_SUCCESS;
322
#else
323
0
    (void)ssl;
324
0
    (void)peer;
325
0
    (void)peerSz;
326
0
    return WOLFSSL_NOT_IMPLEMENTED;
327
0
#endif
328
0
}
329
330
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
331
332
/* Enable DTLS over SCTP mode on the context.
333
 *
334
 * @param [in] ctx  SSL/TLS context object.
335
 * @return  WOLFSSL_SUCCESS on success.
336
 * @return  BAD_FUNC_ARG when ctx is NULL.
337
 */
338
int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx)
339
{
340
    WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp");
341
342
    if (ctx == NULL)
343
        return BAD_FUNC_ARG;
344
345
    ctx->dtlsSctp = 1;
346
    return WOLFSSL_SUCCESS;
347
}
348
349
/* Enable DTLS over SCTP mode on the object.
350
 *
351
 * @param [in] ssl  SSL/TLS object.
352
 * @return  WOLFSSL_SUCCESS on success.
353
 * @return  BAD_FUNC_ARG when ssl is NULL.
354
 */
355
int wolfSSL_dtls_set_sctp(WOLFSSL* ssl)
356
{
357
    WOLFSSL_ENTER("wolfSSL_dtls_set_sctp");
358
359
    if (ssl == NULL)
360
        return BAD_FUNC_ARG;
361
362
    ssl->options.dtlsSctp = 1;
363
    return WOLFSSL_SUCCESS;
364
}
365
366
#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */
367
368
#if (defined(WOLFSSL_SCTP) || defined(WOLFSSL_DTLS_MTU)) && \
369
                                                           defined(WOLFSSL_DTLS)
370
371
/* Set the DTLS path MTU on the context.
372
 *
373
 * @param [in] ctx     SSL/TLS context object.
374
 * @param [in] newMtu  Maximum transmission unit in bytes.
375
 * @return  WOLFSSL_SUCCESS on success.
376
 * @return  BAD_FUNC_ARG when ctx is NULL or newMtu is too large.
377
 */
378
int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu)
379
{
380
    if (ctx == NULL || newMtu > MAX_RECORD_SIZE)
381
        return BAD_FUNC_ARG;
382
383
    ctx->dtlsMtuSz = newMtu;
384
    return WOLFSSL_SUCCESS;
385
}
386
387
/* Set the DTLS path MTU on the object.
388
 *
389
 * @param [in] ssl     SSL/TLS object.
390
 * @param [in] newMtu  Maximum transmission unit in bytes.
391
 * @return  WOLFSSL_SUCCESS on success.
392
 * @return  BAD_FUNC_ARG when ssl is NULL.
393
 * @return  WOLFSSL_FAILURE when newMtu is too large.
394
 */
395
int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu)
396
{
397
    if (ssl == NULL)
398
        return BAD_FUNC_ARG;
399
400
    if (newMtu > MAX_RECORD_SIZE) {
401
        ssl->error = BAD_FUNC_ARG;
402
        return WOLFSSL_FAILURE;
403
    }
404
405
    ssl->dtlsMtuSz = newMtu;
406
    return WOLFSSL_SUCCESS;
407
}
408
409
#ifdef OPENSSL_EXTRA
410
/* Set the DTLS path MTU on the object.
411
 *
412
 * Maps to the compatibility API SSL_set_mtu. Same as wolfSSL_dtls_set_mtu()
413
 * but returns only success or failure.
414
 *
415
 * @param [in] ssl  SSL/TLS object.
416
 * @param [in] mtu  Maximum transmission unit in bytes.
417
 * @return  WOLFSSL_SUCCESS on success.
418
 * @return  WOLFSSL_FAILURE on error.
419
 */
420
int wolfSSL_set_mtu_compat(WOLFSSL* ssl, unsigned short mtu)
421
{
422
    if (wolfSSL_dtls_set_mtu(ssl, mtu) == WOLFSSL_SUCCESS)
423
        return WOLFSSL_SUCCESS;
424
    else
425
        return WOLFSSL_FAILURE;
426
}
427
#endif /* OPENSSL_EXTRA */
428
429
#endif /* WOLFSSL_DTLS && (WOLFSSL_SCTP || WOLFSSL_DTLS_MTU) */
430
431
#ifdef WOLFSSL_SRTP
432
433
static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = {
434
    /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 80-bits
435
     * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */
436
    {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80,
437
     (((128 + 112) * 2) / 8) },
438
    /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 32-bits
439
     * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */
440
    {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32,
441
     (((128 + 112) * 2) / 8) },
442
    /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 80-bits */
443
    {"SRTP_NULL_SHA1_80", SRTP_NULL_SHA1_80, ((112 * 2) / 8)},
444
    /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 32-bits */
445
    {"SRTP_NULL_SHA1_32", SRTP_NULL_SHA1_32, ((112 * 2) / 8)},
446
    /* AES GCM 128, Salt: 96-bits, Auth GCM Tag 128-bits
447
     * (master_key:128bits + master_salt:96bits) * 2 = 448 bits (56) */
448
    {"SRTP_AEAD_AES_128_GCM", SRTP_AEAD_AES_128_GCM, (((128 + 96) * 2) / 8) },
449
    /* AES GCM 256, Salt: 96-bits, Auth GCM Tag 128-bits
450
     * (master_key:256bits + master_salt:96bits) * 2 = 704 bits (88) */
451
    {"SRTP_AEAD_AES_256_GCM", SRTP_AEAD_AES_256_GCM, (((256 + 96) * 2) / 8) },
452
};
453
454
/* Find an SRTP protection profile by name or by id.
455
 *
456
 * @param [in] profile_str      Profile name, or NULL to search by id.
457
 * @param [in] profile_str_len  Length of profile name in bytes.
458
 * @param [in] id               Profile id to search for when name is NULL.
459
 * @return  Matching SRTP protection profile on success.
460
 * @return  NULL when no profile matches.
461
 */
462
static const WOLFSSL_SRTP_PROTECTION_PROFILE* DtlsSrtpFindProfile(
463
    const char* profile_str, word32 profile_str_len, unsigned long id)
464
{
465
    int i;
466
    const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
467
    for (i=0;
468
         i<(int)(sizeof(gSrtpProfiles)/sizeof(WOLFSSL_SRTP_PROTECTION_PROFILE));
469
         i++) {
470
        if (profile_str != NULL) {
471
            word32 srtp_profile_len = (word32)XSTRLEN(gSrtpProfiles[i].name);
472
            if (srtp_profile_len == profile_str_len &&
473
                XMEMCMP(gSrtpProfiles[i].name, profile_str, profile_str_len)
474
                                                                         == 0) {
475
                profile = &gSrtpProfiles[i];
476
                break;
477
            }
478
        }
479
        else if (id != 0 && gSrtpProfiles[i].id == id) {
480
            profile = &gSrtpProfiles[i];
481
            break;
482
        }
483
    }
484
    return profile;
485
}
486
487
/* Select SRTP protection profiles from a colon-separated name list.
488
 *
489
 * @param [out] id           Bitmask of selected profile ids.
490
 * @param [in]  profile_str  Colon-separated list of SRTP profile names.
491
 * @return  WOLFSSL_SUCCESS on success.
492
 * @return  WOLFSSL_FAILURE when profile_str is NULL.
493
 */
494
static int DtlsSrtpSelProfiles(word16* id, const char* profile_str)
495
{
496
    const WOLFSSL_SRTP_PROTECTION_PROFILE* profile;
497
    const char *current, *next = NULL;
498
    word32 length = 0, current_length;
499
500
    *id = 0; /* reset destination ID's */
501
502
    if (profile_str == NULL) {
503
        return WOLFSSL_FAILURE;
504
    }
505
506
    /* loop on end of line or colon ":" */
507
    next = profile_str;
508
    length = (word32)XSTRLEN(profile_str);
509
    do {
510
        current = next;
511
        next = XSTRSTR(current, ":");
512
        if (next) {
513
            current_length = (word32)(next - current);
514
            ++next; /* ++ needed to skip ':' */
515
        } else {
516
            current_length = (word32)XSTRLEN(current);
517
        }
518
        if (current_length < length)
519
            length = current_length;
520
        profile = DtlsSrtpFindProfile(current, current_length, 0);
521
        if (profile != NULL) {
522
            *id |= (1 << profile->id); /* selected bit based on ID */
523
        }
524
    } while (next != NULL);
525
    return WOLFSSL_SUCCESS;
526
}
527
528
/* Set the SRTP protection profiles for DTLS on the context.
529
 *
530
 * @param [in] ctx          SSL/TLS context object.
531
 * @param [in] profile_str  Colon-separated list of SRTP profile names.
532
 * @return  0 on success, to match OpenSSL.
533
 * @return  1 on error, to match OpenSSL.
534
 */
535
int wolfSSL_CTX_set_tlsext_use_srtp(WOLFSSL_CTX* ctx, const char* profile_str)
536
{
537
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
538
    if (ctx != NULL) {
539
        ret = DtlsSrtpSelProfiles(&ctx->dtlsSrtpProfiles, profile_str);
540
    }
541
542
    if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
543
        ret = 1;
544
    } else {
545
        ret = 0;
546
    }
547
548
    return ret;
549
}
550
551
/* Set the SRTP protection profiles for DTLS on the object.
552
 *
553
 * @param [in] ssl          SSL/TLS object.
554
 * @param [in] profile_str  Colon-separated list of SRTP profile names.
555
 * @return  0 on success, to match OpenSSL.
556
 * @return  1 on error, to match OpenSSL.
557
 */
558
int wolfSSL_set_tlsext_use_srtp(WOLFSSL* ssl, const char* profile_str)
559
{
560
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
561
    if (ssl != NULL) {
562
        ret = DtlsSrtpSelProfiles(&ssl->dtlsSrtpProfiles, profile_str);
563
    }
564
565
    if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
566
        ret = 1;
567
    } else {
568
        ret = 0;
569
    }
570
571
    return ret;
572
}
573
574
/* Get the SRTP protection profile selected for the object.
575
 *
576
 * @param [in] ssl  SSL/TLS object.
577
 * @return  Selected SRTP protection profile on success.
578
 * @return  NULL when ssl is NULL or none is selected.
579
 */
580
const WOLFSSL_SRTP_PROTECTION_PROFILE* wolfSSL_get_selected_srtp_profile(
581
    WOLFSSL* ssl)
582
{
583
    const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
584
    if (ssl) {
585
        profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId);
586
    }
587
    return profile;
588
}
589
#ifndef NO_WOLFSSL_STUB
590
/* Get the list of SRTP protection profiles set on the object.
591
 *
592
 * Not implemented - stub.
593
 *
594
 * @param [in] ssl  SSL/TLS object.
595
 * @return  NULL always.
596
 */
597
WOLF_STACK_OF(WOLFSSL_SRTP_PROTECTION_PROFILE)* wolfSSL_get_srtp_profiles(
598
    WOLFSSL* ssl)
599
{
600
    /* Not yet implemented - should return list of available SRTP profiles
601
     * ssl->dtlsSrtpProfiles */
602
    (void)ssl;
603
    return NULL;
604
}
605
#endif
606
607
#define DTLS_SRTP_KEYING_MATERIAL_LABEL "EXTRACTOR-dtls_srtp"
608
609
/* Export the DTLS-SRTP keying material for the object.
610
 *
611
 * When out is NULL, the length required is returned in olen.
612
 *
613
 * @param [in]      ssl   SSL/TLS object.
614
 * @param [out]     out   Buffer to hold keying material. May be NULL.
615
 * @param [in, out] olen  In: size of buffer. Out: length of keying material.
616
 * @return  WOLFSSL_SUCCESS on success.
617
 * @return  BAD_FUNC_ARG when ssl or olen is NULL.
618
 * @return  EXT_MISSING when DTLS-SRTP is not in use.
619
 * @return  LENGTH_ONLY_E when out is NULL and olen has been set.
620
 * @return  BUFFER_E when the buffer is too small.
621
 */
622
int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl,
623
    unsigned char* out, size_t* olen)
624
{
625
    const WOLFSSL_SRTP_PROTECTION_PROFILE* profile = NULL;
626
627
    if (ssl == NULL || olen == NULL) {
628
        return BAD_FUNC_ARG;
629
    }
630
631
    profile = DtlsSrtpFindProfile(NULL, 0, ssl->dtlsSrtpId);
632
    if (profile == NULL) {
633
        WOLFSSL_MSG("Not using DTLS SRTP");
634
        return EXT_MISSING;
635
    }
636
    if (out == NULL) {
637
        *olen = (size_t)profile->kdfBits;
638
        return WC_NO_ERR_TRACE(LENGTH_ONLY_E);
639
    }
640
641
    if (*olen < (size_t)profile->kdfBits) {
642
        return BUFFER_E;
643
    }
644
645
    return wolfSSL_export_keying_material(ssl, out, (size_t)profile->kdfBits,
646
            DTLS_SRTP_KEYING_MATERIAL_LABEL,
647
            XSTR_SIZEOF(DTLS_SRTP_KEYING_MATERIAL_LABEL), NULL, 0, 0);
648
}
649
650
#endif /* WOLFSSL_SRTP */
651
652
#ifdef WOLFSSL_DTLS_DROP_STATS
653
654
/* Get the DTLS dropped-record statistics for the object.
655
 *
656
 * @param [in]  ssl              SSL/TLS object.
657
 * @param [out] macDropCount     Number of records dropped on MAC failure.
658
 * @param [out] replayDropCount  Number of records dropped as replays.
659
 * @return  WOLFSSL_SUCCESS on success.
660
 * @return  BAD_FUNC_ARG when ssl is NULL.
661
 */
662
int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
663
                                word32* macDropCount, word32* replayDropCount)
664
{
665
    int ret;
666
667
    WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats");
668
669
    if (ssl == NULL)
670
        ret = BAD_FUNC_ARG;
671
    else {
672
        ret = WOLFSSL_SUCCESS;
673
        if (macDropCount != NULL)
674
            *macDropCount = ssl->macDropCount;
675
        if (replayDropCount != NULL)
676
            *replayDropCount = ssl->replayDropCount;
677
    }
678
679
    WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats", ret);
680
    return ret;
681
}
682
683
#endif /* WOLFSSL_DTLS_DROP_STATS */
684
685
#if defined(WOLFSSL_MULTICAST)
686
687
/* Set the multicast member id on the context and enable multicast.
688
 *
689
 * @param [in] ctx  SSL/TLS context object.
690
 * @param [in] id   Multicast member id.
691
 * @return  WOLFSSL_SUCCESS on success.
692
 * @return  BAD_FUNC_ARG when ctx is NULL or id is out of range.
693
 */
694
int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id)
695
{
696
    int ret = 0;
697
698
    WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id");
699
700
    if (ctx == NULL || id > WOLFSSL_MAX_8BIT)
701
        ret = BAD_FUNC_ARG;
702
703
    if (ret == 0) {
704
        ctx->haveEMS = 0;
705
        ctx->haveMcast = 1;
706
        ctx->mcastID = (byte)id;
707
#ifndef WOLFSSL_USER_IO
708
        ctx->CBIORecv = EmbedReceiveFromMcast;
709
#endif /* WOLFSSL_USER_IO */
710
711
        ret = WOLFSSL_SUCCESS;
712
    }
713
    WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id", ret);
714
    return ret;
715
}
716
717
/* Get the maximum number of multicast peers supported.
718
 *
719
 * @return  Maximum number of multicast peers.
720
 */
721
int wolfSSL_mcast_get_max_peers(void)
722
{
723
    return WOLFSSL_MULTICAST_PEERS;
724
}
725
726
#ifdef WOLFSSL_DTLS
727
/* Determine the next highwater mark from the current sequence number.
728
 *
729
 * @param [in] cur     Current sequence number.
730
 * @param [in] first   First highwater threshold.
731
 * @param [in] second  Second highwater threshold.
732
 * @param [in] high    Maximum highwater threshold.
733
 * @return  Next highwater mark, or 0 when cur is at or above high.
734
 */
735
static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first,
736
                                         word32 second, word32 high)
737
{
738
    word32 newCur = 0;
739
740
    if (cur < first)
741
        newCur = first;
742
    else if (cur < second)
743
        newCur = second;
744
    else if (cur < high)
745
        newCur = high;
746
747
    return newCur;
748
}
749
#endif /* WOLFSSL_DTLS */
750
751
/* Set the master secret and derived keys directly on the object.
752
 *
753
 * Used with multicast to install externally derived keys.
754
 *
755
 * @param [in, out] ssl              SSL/TLS object.
756
 * @param [in]      epoch            DTLS epoch to use.
757
 * @param [in]      preMasterSecret  Pre-master secret data.
758
 * @param [in]      preMasterSz      Length of pre-master secret in bytes.
759
 * @param [in]      clientRandom     Client random data (RAN_LEN bytes).
760
 * @param [in]      serverRandom     Server random data (RAN_LEN bytes).
761
 * @param [in]      suite            Cipher suite bytes (2).
762
 * @return  WOLFSSL_SUCCESS on success.
763
 * @return  WOLFSSL_FATAL_ERROR on error, including invalid arguments and a
764
 *          failure to allocate the pre-master secret. The specific code is
765
 *          recorded in ssl->error and can be read with wolfSSL_get_error().
766
 */
767
int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch,
768
                       const byte* preMasterSecret, word32 preMasterSz,
769
                       const byte* clientRandom, const byte* serverRandom,
770
                       const byte* suite)
771
{
772
    int ret = 0;
773
774
    WOLFSSL_ENTER("wolfSSL_set_secret");
775
776
    if (ssl == NULL || preMasterSecret == NULL ||
777
        preMasterSz == 0 || preMasterSz > ENCRYPT_LEN ||
778
        clientRandom == NULL || serverRandom == NULL || suite == NULL) {
779
780
        ret = BAD_FUNC_ARG;
781
    }
782
783
    /* The handshake arrays are released once the handshake resources are
784
     * freed, so a reused object may not have them any more. */
785
    if (ret == 0 && ssl->arrays == NULL) {
786
        WOLFSSL_MSG("Handshake arrays not available");
787
        ret = BAD_FUNC_ARG;
788
    }
789
790
    if (ret == 0 && ssl->arrays->preMasterSecret == NULL) {
791
        ssl->arrays->preMasterSz = ENCRYPT_LEN;
792
        ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap,
793
            DYNAMIC_TYPE_SECRET);
794
        if (ssl->arrays->preMasterSecret == NULL) {
795
            ret = MEMORY_E;
796
        }
797
    }
798
799
    if (ret == 0) {
800
        XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz);
801
        XMEMSET(ssl->arrays->preMasterSecret + preMasterSz, 0,
802
            ENCRYPT_LEN - preMasterSz);
803
        ssl->arrays->preMasterSz = preMasterSz;
804
        XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN);
805
        XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN);
806
        ssl->options.cipherSuite0 = suite[0];
807
        ssl->options.cipherSuite = suite[1];
808
809
        ret = SetCipherSpecs(ssl);
810
    }
811
812
    if (ret == 0)
813
        ret = MakeTlsMasterSecret(ssl);
814
815
    if (ret == 0) {
816
        ssl->keys.encryptionOn = 1;
817
        ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
818
    }
819
820
    if (ret == 0) {
821
        if (ssl->options.dtls) {
822
        #ifdef WOLFSSL_DTLS
823
            WOLFSSL_DTLS_PEERSEQ* peerSeq;
824
            int i;
825
826
            ssl->keys.dtls_epoch = epoch;
827
            for (i = 0, peerSeq = ssl->keys.peerSeq;
828
                 i < WOLFSSL_DTLS_PEERSEQ_SZ;
829
                 i++, peerSeq++) {
830
831
                peerSeq->nextEpoch = epoch;
832
                peerSeq->prevSeq_lo = peerSeq->nextSeq_lo;
833
                peerSeq->prevSeq_hi = peerSeq->nextSeq_hi;
834
                peerSeq->nextSeq_lo = 0;
835
                peerSeq->nextSeq_hi = 0;
836
                XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ);
837
                XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ);
838
                peerSeq->highwaterMark = UpdateHighwaterMark(0,
839
                        ssl->ctx->mcastFirstSeq,
840
                        ssl->ctx->mcastSecondSeq,
841
                        ssl->ctx->mcastMaxSeq);
842
            }
843
        #else
844
            (void)epoch;
845
        #endif
846
        }
847
        FreeHandshakeResources(ssl);
848
        ret = WOLFSSL_SUCCESS;
849
    }
850
    else {
851
        if (ssl)
852
            ssl->error = ret;
853
        ret = WOLFSSL_FATAL_ERROR;
854
    }
855
    WOLFSSL_LEAVE("wolfSSL_set_secret", ret);
856
    return ret;
857
}
858
859
#ifdef WOLFSSL_DTLS
860
861
/* Add or remove a peer from the multicast peer list.
862
 *
863
 * @param [in] ssl     SSL/TLS object.
864
 * @param [in] peerId  Peer id to add or remove.
865
 * @param [in] sub     0 to add the peer, non-zero to remove it.
866
 * @return  WOLFSSL_SUCCESS on success.
867
 * @return  BAD_FUNC_ARG when ssl is NULL or peerId is out of range.
868
 * @return  WOLFSSL_FATAL_ERROR when the peer list is full.
869
 */
870
int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int sub)
871
{
872
    WOLFSSL_DTLS_PEERSEQ* p = NULL;
873
    int ret = WOLFSSL_SUCCESS;
874
    int i;
875
876
    WOLFSSL_ENTER("wolfSSL_mcast_peer_add");
877
    if (ssl == NULL || peerId > WOLFSSL_MAX_8BIT)
878
        return BAD_FUNC_ARG;
879
880
    if (!sub) {
881
        /* Make sure it isn't already present, while keeping the first
882
         * open spot. */
883
        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
884
            if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID)
885
                p = &ssl->keys.peerSeq[i];
886
            if (ssl->keys.peerSeq[i].peerId == peerId) {
887
                WOLFSSL_MSG("Peer ID already in multicast peer list.");
888
                p = NULL;
889
            }
890
        }
891
892
        if (p != NULL) {
893
            XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ));
894
            p->peerId = peerId;
895
            p->highwaterMark = UpdateHighwaterMark(0,
896
                ssl->ctx->mcastFirstSeq,
897
                ssl->ctx->mcastSecondSeq,
898
                ssl->ctx->mcastMaxSeq);
899
        }
900
        else {
901
            WOLFSSL_MSG("No room in peer list.");
902
            ret = WOLFSSL_FATAL_ERROR;
903
        }
904
    }
905
    else {
906
        for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
907
            if (ssl->keys.peerSeq[i].peerId == peerId)
908
                p = &ssl->keys.peerSeq[i];
909
        }
910
911
        if (p != NULL) {
912
            p->peerId = INVALID_PEER_ID;
913
        }
914
        else {
915
            WOLFSSL_MSG("Peer not found in list.");
916
        }
917
    }
918
919
    WOLFSSL_LEAVE("wolfSSL_mcast_peer_add", ret);
920
    return ret;
921
}
922
923
/* Determine whether a multicast peer is known and active.
924
 *
925
 * @param [in] ssl     SSL/TLS object.
926
 * @param [in] peerId  Peer id to look up.
927
 * @return  1 when the peer is in the list with a non-zero sequence number.
928
 * @return  0 when the peer is not known or has not sent data.
929
 * @return  BAD_FUNC_ARG when ssl is NULL or peerId is out of range.
930
 */
931
int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId)
932
{
933
    int known = 0;
934
    int i;
935
936
    WOLFSSL_ENTER("wolfSSL_mcast_peer_known");
937
938
    if (ssl == NULL || peerId > WOLFSSL_MAX_8BIT) {
939
        return BAD_FUNC_ARG;
940
    }
941
942
    for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) {
943
        if (ssl->keys.peerSeq[i].peerId == peerId) {
944
            if (ssl->keys.peerSeq[i].nextSeq_hi ||
945
                ssl->keys.peerSeq[i].nextSeq_lo) {
946
947
                known = 1;
948
            }
949
            break;
950
        }
951
    }
952
953
    WOLFSSL_LEAVE("wolfSSL_mcast_peer_known", known);
954
    return known;
955
}
956
957
/* Set the multicast highwater callback and thresholds on the context.
958
 *
959
 * @param [in] ctx     SSL/TLS context object.
960
 * @param [in] maxSeq  Maximum sequence number threshold.
961
 * @param [in] first   First sequence number threshold.
962
 * @param [in] second  Second sequence number threshold.
963
 * @param [in] cb      Highwater callback.
964
 * @return  WOLFSSL_SUCCESS on success.
965
 * @return  BAD_FUNC_ARG when an argument is NULL or thresholds are invalid.
966
 */
967
int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq,
968
                                       word32 first, word32 second,
969
                                       CallbackMcastHighwater cb)
970
{
971
    if (ctx == NULL || (second && first > second) ||
972
        first > maxSeq || second > maxSeq || cb == NULL) {
973
974
        return BAD_FUNC_ARG;
975
    }
976
977
    ctx->mcastHwCb = cb;
978
    ctx->mcastFirstSeq = first;
979
    ctx->mcastSecondSeq = second;
980
    ctx->mcastMaxSeq = maxSeq;
981
982
    return WOLFSSL_SUCCESS;
983
}
984
985
/* Set the user context passed to the multicast highwater callback.
986
 *
987
 * @param [in] ssl  SSL/TLS object.
988
 * @param [in] ctx  User context for the highwater callback.
989
 * @return  WOLFSSL_SUCCESS on success.
990
 * @return  BAD_FUNC_ARG when ssl or ctx is NULL.
991
 */
992
int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx)
993
{
994
    if (ssl == NULL || ctx == NULL)
995
        return BAD_FUNC_ARG;
996
997
    ssl->mcastHwCbCtx = ctx;
998
999
    return WOLFSSL_SUCCESS;
1000
}
1001
1002
#endif /* WOLFSSL_DTLS */
1003
1004
#endif /* WOLFSSL_MULTICAST */
1005
1006
#endif /* WOLFSSL_LEANPSK */
1007
1008
#ifndef NO_TLS
1009
#ifdef WOLFSSL_MULTICAST
1010
1011
/* Read application data from a multicast DTLS object.
1012
 *
1013
 * @param [in]  ssl   SSL/TLS object.
1014
 * @param [out] id    Peer id the data was received from. May be NULL.
1015
 * @param [out] data  Buffer to hold the data read.
1016
 * @param [in]  sz    Size of the buffer in bytes.
1017
 * @return  Number of bytes read on success.
1018
 * @return  BAD_FUNC_ARG when ssl is NULL or sz is negative.
1019
 * @return  Negative value on error.
1020
 */
1021
int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz)
1022
{
1023
    int ret = 0;
1024
1025
    WOLFSSL_ENTER("wolfSSL_mcast_read");
1026
1027
    if ((ssl == NULL) || (sz < 0))
1028
        return BAD_FUNC_ARG;
1029
1030
    ret = wolfSSL_read_internal(ssl, data, (size_t)sz, FALSE);
1031
    if (ssl->options.dtls && ssl->options.haveMcast && id != NULL)
1032
        *id = ssl->keys.curPeerId;
1033
    return ret;
1034
}
1035
1036
#endif /* WOLFSSL_MULTICAST */
1037
#endif /* !NO_TLS */
1038
1039
#ifdef WOLFSSL_DTLS
1040
/* Get the DTLS MAC secret for the requested side and epoch.
1041
 *
1042
 * @param [in] ssl         SSL/TLS object.
1043
 * @param [in] verify      1 for the verify (read) secret, 0 for the write one.
1044
 * @param [in] epochOrder  Epoch order: PEER_ORDER, PREV_ORDER or CUR_ORDER.
1045
 * @return  MAC secret on success.
1046
 * @return  NULL when ssl is NULL, AEAD-only build, or epoch order is unknown.
1047
 */
1048
const byte* wolfSSL_GetDtlsMacSecret(WOLFSSL* ssl, int verify, int epochOrder)
1049
{
1050
#ifndef WOLFSSL_AEAD_ONLY
1051
    Keys* keys = NULL;
1052
1053
    (void)epochOrder;
1054
1055
    if (ssl == NULL)
1056
        return NULL;
1057
1058
#ifdef HAVE_SECURE_RENEGOTIATION
1059
    switch (epochOrder) {
1060
    case PEER_ORDER:
1061
        if (IsDtlsMsgSCRKeys(ssl))
1062
            keys = &ssl->secure_renegotiation->tmp_keys;
1063
        else
1064
            keys = &ssl->keys;
1065
        break;
1066
    case PREV_ORDER:
1067
        keys = &ssl->keys;
1068
        break;
1069
    case CUR_ORDER:
1070
        if (DtlsUseSCRKeys(ssl))
1071
            keys = &ssl->secure_renegotiation->tmp_keys;
1072
        else
1073
            keys = &ssl->keys;
1074
        break;
1075
    default:
1076
        WOLFSSL_MSG("Unknown epoch order");
1077
        return NULL;
1078
    }
1079
#else
1080
    keys = &ssl->keys;
1081
#endif
1082
1083
    if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) ||
1084
         (ssl->options.side == WOLFSSL_SERVER_END &&  verify) )
1085
        return keys->client_write_MAC_secret;
1086
    else
1087
        return keys->server_write_MAC_secret;
1088
#else
1089
    (void)ssl;
1090
    (void)verify;
1091
    (void)epochOrder;
1092
1093
    return NULL;
1094
#endif
1095
}
1096
#endif /* WOLFSSL_DTLS */
1097
1098
/* Get whether the DTLS object is using non-blocking I/O.
1099
 *
1100
 * @param [in] ssl  SSL/TLS object.
1101
 * @return  1 when non-blocking I/O is enabled.
1102
 * @return  0 when disabled or not a DTLS object.
1103
 * @return  WOLFSSL_FAILURE when ssl is NULL.
1104
 */
1105
int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
1106
0
{
1107
0
    int useNb = 0;
1108
1109
0
    if (ssl == NULL)
1110
0
        return WOLFSSL_FAILURE;
1111
1112
0
    WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
1113
0
    if (ssl->options.dtls) {
1114
#ifdef WOLFSSL_DTLS
1115
        useNb = ssl->options.dtlsUseNonblock;
1116
#endif
1117
0
    }
1118
0
    else {
1119
0
        WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
1120
0
                    "DEPRECATED for non-DTLS use.");
1121
0
    }
1122
0
    return useNb;
1123
0
}
1124
1125
#ifndef WOLFSSL_LEANPSK
1126
1127
/* Set whether the DTLS object uses non-blocking I/O.
1128
 *
1129
 * @param [in] ssl       SSL/TLS object.
1130
 * @param [in] nonblock  1 to use non-blocking I/O, 0 otherwise.
1131
 */
1132
void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
1133
0
{
1134
0
    (void)nonblock;
1135
1136
0
    WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
1137
1138
0
    if (ssl == NULL)
1139
0
        return;
1140
1141
0
    if (ssl->options.dtls) {
1142
#ifdef WOLFSSL_DTLS
1143
        ssl->options.dtlsUseNonblock = (nonblock != 0);
1144
#endif
1145
0
    }
1146
0
    else {
1147
0
        WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
1148
0
                    "DEPRECATED for non-DTLS use.");
1149
0
    }
1150
0
}
1151
1152
#ifdef WOLFSSL_DTLS
1153
1154
/* Get the current DTLS receive timeout, in seconds.
1155
 *
1156
 * @param [in] ssl  SSL/TLS object.
1157
 * @return  Current timeout in seconds, or 0 when ssl is NULL.
1158
 */
1159
int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
1160
{
1161
    int timeout = 0;
1162
    if (ssl)
1163
        timeout = ssl->dtls_timeout;
1164
1165
    WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout", timeout);
1166
    return timeout;
1167
}
1168
1169
#ifdef WOLFSSL_DTLS13
1170
1171
/* Determine whether a short receive timeout should be used.
1172
 *
1173
 * Recommended to be at most 1/4 of wolfSSL_dtls_get_current_timeout().
1174
 *
1175
 * @param [in] ssl  SSL/TLS object.
1176
 * @return  1 when a short timeout should be used.
1177
 * @return  0 otherwise, or when ssl is NULL.
1178
 */
1179
int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl)
1180
{
1181
    return ssl != NULL && ssl->dtls13FastTimeout;
1182
}
1183
1184
/* Set whether a DTLS 1.3 connection sends acks immediately on a disruption.
1185
 *
1186
 * Sending more acks may increase traffic but can speed up the handshake.
1187
 *
1188
 * @param [in] ssl    SSL/TLS object.
1189
 * @param [in] value  Non-zero to send more acks, 0 otherwise.
1190
 */
1191
void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value)
1192
{
1193
    if (ssl != NULL)
1194
        ssl->options.dtls13SendMoreAcks = !!value;
1195
}
1196
#endif /* WOLFSSL_DTLS13 */
1197
1198
/* Get the time left until the next DTLS timeout.
1199
 *
1200
 * @param [in]  ssl       SSL/TLS object.
1201
 * @param [out] timeleft  Time left until the next timeout.
1202
 * @return  0 always.
1203
 */
1204
int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft)
1205
{
1206
    if (ssl && timeleft) {
1207
        XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL));
1208
        timeleft->tv_sec = ssl->dtls_timeout;
1209
    }
1210
    return 0;
1211
}
1212
1213
#ifndef NO_WOLFSSL_STUB
1214
/* Handle a DTLS timeout.
1215
 *
1216
 * Not implemented - stub for OpenSSL compatibility.
1217
 *
1218
 * @param [in] ssl  SSL/TLS object.
1219
 * @return  0 always.
1220
 */
1221
int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl)
1222
{
1223
    WOLFSSL_STUB("SSL_DTLSv1_handle_timeout");
1224
    (void)ssl;
1225
    return 0;
1226
}
1227
1228
/* Set the initial DTLS timeout duration.
1229
 *
1230
 * Not implemented - stub for OpenSSL compatibility.
1231
 *
1232
 * @param [in] ssl          SSL/TLS object.
1233
 * @param [in] duration_ms  Initial timeout duration in milliseconds.
1234
 */
1235
void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl,
1236
    word32 duration_ms)
1237
{
1238
    WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration");
1239
    (void)ssl;
1240
    (void)duration_ms;
1241
}
1242
#endif
1243
1244
/* Set the initial DTLS receive timeout, in seconds, on the object.
1245
 *
1246
 * @param [in] ssl      SSL/TLS object.
1247
 * @param [in] timeout  Initial timeout in seconds.
1248
 * @return  WOLFSSL_SUCCESS on success.
1249
 * @return  BAD_FUNC_ARG when ssl is NULL, timeout is negative or greater than
1250
 *          the maximum timeout.
1251
 */
1252
int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout)
1253
{
1254
    if (ssl == NULL || timeout < 0)
1255
        return BAD_FUNC_ARG;
1256
1257
    if (timeout > ssl->dtls_timeout_max) {
1258
        WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout "
1259
                    "max");
1260
        return BAD_FUNC_ARG;
1261
    }
1262
1263
    ssl->dtls_timeout_init = timeout;
1264
    ssl->dtls_timeout = timeout;
1265
1266
    return WOLFSSL_SUCCESS;
1267
}
1268
1269
/* Set the maximum DTLS receive timeout, in seconds, on the object.
1270
 *
1271
 * @param [in] ssl      SSL/TLS object.
1272
 * @param [in] timeout  Maximum timeout in seconds.
1273
 * @return  WOLFSSL_SUCCESS on success.
1274
 * @return  BAD_FUNC_ARG when ssl is NULL, timeout is negative or less than
1275
 *          the initial timeout.
1276
 */
1277
int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout)
1278
{
1279
    if (ssl == NULL || timeout < 0)
1280
        return BAD_FUNC_ARG;
1281
1282
    if (timeout < ssl->dtls_timeout_init) {
1283
        WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init");
1284
        return BAD_FUNC_ARG;
1285
    }
1286
1287
    ssl->dtls_timeout_max = timeout;
1288
1289
    return WOLFSSL_SUCCESS;
1290
}
1291
1292
/* Process a DTLS timeout, retransmitting messages as needed.
1293
 *
1294
 * @param [in] ssl  SSL/TLS object.
1295
 * @return  WOLFSSL_SUCCESS on success.
1296
 * @return  WOLFSSL_FATAL_ERROR when ssl is NULL, not DTLS, or on error.
1297
 */
1298
int wolfSSL_dtls_got_timeout(WOLFSSL* ssl)
1299
{
1300
    int result = WOLFSSL_SUCCESS;
1301
    WOLFSSL_ENTER("wolfSSL_dtls_got_timeout");
1302
1303
    if (ssl == NULL || !ssl->options.dtls)
1304
        return WOLFSSL_FATAL_ERROR;
1305
1306
#ifdef WOLFSSL_DTLS13
1307
    if (IsAtLeastTLSv1_3(ssl->version)) {
1308
        result = Dtls13RtxTimeout(ssl);
1309
        if (result < 0) {
1310
            if (result == WC_NO_ERR_TRACE(WANT_WRITE))
1311
                ssl->dtls13SendingAckOrRtx = 1;
1312
            ssl->error = result;
1313
            WOLFSSL_ERROR(result);
1314
            return WOLFSSL_FATAL_ERROR;
1315
        }
1316
1317
        return WOLFSSL_SUCCESS;
1318
    }
1319
#endif /* WOLFSSL_DTLS13 */
1320
1321
    /* Do we have any 1.2 messages stored? */
1322
    if (ssl->dtls_tx_msg_list != NULL || ssl->dtls_tx_msg != NULL) {
1323
        if (DtlsMsgPoolTimeout(ssl) < 0){
1324
            ssl->error = SOCKET_ERROR_E;
1325
            WOLFSSL_ERROR(ssl->error);
1326
            result = WOLFSSL_FATAL_ERROR;
1327
        }
1328
        else if ((result = DtlsMsgPoolSend(ssl, 0)) < 0)  {
1329
            ssl->error = result;
1330
            WOLFSSL_ERROR(result);
1331
            result = WOLFSSL_FATAL_ERROR;
1332
        }
1333
        else {
1334
            /* Reset return value to success */
1335
            result = WOLFSSL_SUCCESS;
1336
        }
1337
    }
1338
1339
    WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout", result);
1340
    return result;
1341
}
1342
1343
/* Retransmit all stored DTLS handshake messages.
1344
 *
1345
 * @param [in] ssl  SSL/TLS object.
1346
 * @return  WOLFSSL_SUCCESS on success.
1347
 * @return  WOLFSSL_FATAL_ERROR when ssl is NULL or on error.
1348
 */
1349
int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
1350
{
1351
    WOLFSSL_ENTER("wolfSSL_dtls_retransmit");
1352
1353
    if (ssl == NULL)
1354
        return WOLFSSL_FATAL_ERROR;
1355
1356
    if (!ssl->options.handShakeDone) {
1357
        int result;
1358
#ifdef WOLFSSL_DTLS13
1359
        if (IsAtLeastTLSv1_3(ssl->version))
1360
            result = Dtls13DoScheduledWork(ssl);
1361
        else
1362
#endif
1363
            result = DtlsMsgPoolSend(ssl, 0);
1364
        if (result < 0) {
1365
            ssl->error = result;
1366
            WOLFSSL_ERROR(result);
1367
            return WOLFSSL_FATAL_ERROR;
1368
        }
1369
    }
1370
1371
    return WOLFSSL_SUCCESS;
1372
}
1373
1374
#ifdef WOLFSSL_DTLS13
1375
/* Is this object the kind the scheduled-work API operates on?
1376
 *
1377
 * A write-dup pair parks the read side's scheduled work in the shared WriteDup
1378
 * struct, and only wolfSSL_write() reconciles it back onto the write side.
1379
 * Such applications already have a working drain and are deliberately out of
1380
 * scope here, on either side of the pair.
1381
 */
1382
static int Dtls13ScheduledWorkObject(WOLFSSL* ssl)
1383
{
1384
    if (!ssl->options.dtls || !IsAtLeastTLSv1_3(ssl->version))
1385
        return 0;
1386
#ifdef HAVE_WRITE_DUP
1387
    if (ssl->dupWrite != NULL)
1388
        return 0;
1389
#endif
1390
1391
    return 1;
1392
}
1393
1394
/* Is there any point running the scheduled work now?
1395
 *
1396
 * While the handshake runs, wolfSSL_connect()/wolfSSL_accept() and
1397
 * wolfSSL_dtls_retransmit() already drive it. Kept separate from the object
1398
 * check above so the pump can tell a caller error, which it reports, from
1399
 * simply having nothing to do yet, which it does not.
1400
 */
1401
static int Dtls13ScheduledWorkReady(WOLFSSL* ssl)
1402
{
1403
    return Dtls13ScheduledWorkObject(ssl) && ssl->options.handShakeDone;
1404
}
1405
1406
/* Can a key update be sent right now?
1407
 *
1408
 * DTLS must not have two in flight, so not while one of ours is still
1409
 * unacknowledged. This governs both an update we scheduled ourselves and
1410
 * answering one the peer asked for, because Tls13UpdateKeys() silently drops
1411
 * the former in that state. Both entry points ask this same question: the
1412
 * predicate must not report work the pump then declines or discards, or a
1413
 * drain loop over the pair never terminates and the caller is misled about
1414
 * what was done.
1415
 */
1416
static int Dtls13CanSendKeyUpdate(WOLFSSL* ssl)
1417
{
1418
    return !ssl->dtls13WaitKeyUpdateAck;
1419
}
1420
1421
/* Check whether the object has DTLS 1.3 work waiting to be sent.
1422
 *
1423
 * Only meaningful with WOLFSSL_RW_THREADED, where the read path does not
1424
 * transmit. The answer is advisory: it can change as soon as it is returned,
1425
 * and wolfSSL_dtls13_do_scheduled_work() is safe to call regardless.
1426
 *
1427
 * Reports only work that wolfSSL_dtls13_do_scheduled_work() can carry out, so
1428
 * that a drain loop over the pair terminates.
1429
 *
1430
 * @param [in] ssl  SSL/TLS object.
1431
 * @return  1 when there is work to send, or when it could not be determined.
1432
 * @return  0 when there is nothing to do, or ssl is not supported here.
1433
 */
1434
int wolfSSL_dtls13_pending_work(WOLFSSL* ssl)
1435
{
1436
    int pending = 0;
1437
1438
    WOLFSSL_ENTER("wolfSSL_dtls13_pending_work");
1439
1440
    if (ssl == NULL || !Dtls13ScheduledWorkReady(ssl))
1441
        return 0;
1442
1443
    /* A record this API built but could only write in part. The pump retries
1444
     * it, so a drain loop has to be told the retry is still owed. */
1445
    if (ssl->buffers.outputBuffer.length > 0 && ssl->dtls13SendingAckOrRtx)
1446
        pending = 1;
1447
1448
    /* dtls13WaitKeyUpdateAck deliberately does not count as work: it says we
1449
     * are waiting on the peer, not that we have anything to send. */
1450
    if (!pending && (ssl->dtls13DoKeyUpdate || ssl->options.sendKeyUpdate) &&
1451
            Dtls13CanSendKeyUpdate(ssl)) {
1452
        pending = 1;
1453
    }
1454
1455
    if (!pending) {
1456
    #ifdef WOLFSSL_RW_THREADED
1457
        if (wc_LockMutex(&ssl->dtls13Rtx.mutex) != 0) {
1458
            /* Report work rather than nothing, so a drain loop calls the pump
1459
             * and surfaces the error instead of stopping silently. */
1460
            return 1;
1461
        }
1462
    #endif
1463
        pending = ssl->dtls13Rtx.sendAcks || ssl->dtls13Rtx.retransmit;
1464
    #ifdef WOLFSSL_RW_THREADED
1465
        (void)wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
1466
    #endif
1467
    }
1468
1469
    WOLFSSL_LEAVE("wolfSSL_dtls13_pending_work", pending);
1470
1471
    return pending;
1472
}
1473
1474
/* Send any DTLS 1.3 work that was scheduled while reading.
1475
 *
1476
 * Covers pending ACKs, retransmissions and key updates, including the
1477
 * KeyUpdate response a peer asked for. With WOLFSSL_RW_THREADED the read path
1478
 * never transmits, because doing so would race the write thread over the
1479
 * output buffer and the sending key schedule, so this work is only performed
1480
 * from the write side. An application that reads without writing has to call
1481
 * this or those messages are never sent, and the peer keeps retransmitting
1482
 * what it is waiting to have acknowledged.
1483
 *
1484
 * Call it from the same thread used for writing. Calling it concurrently with
1485
 * a write on another thread has the same effect as two concurrent writes.
1486
 *
1487
 * Not for write-dup applications: those park the read side's work in the
1488
 * shared WriteDup struct, which only wolfSSL_write() reconciles, so they
1489
 * already have a drain and get WOLFSSL_FATAL_ERROR here rather than a call
1490
 * that quietly does nothing.
1491
 *
1492
 * Note that a key update started from our own side still needs the peer's ACK
1493
 * to be processed before it completes, and that processing rotates the sending
1494
 * keys, so it cannot run here.
1495
 *
1496
 * A send that only wrote part of a record reports WANT_WRITE through
1497
 * wolfSSL_get_error(). The record is held and the next call sends the rest,
1498
 * so that is a retry rather than a reason to stop draining.
1499
 *
1500
 * @param [in] ssl  SSL/TLS object.
1501
 * @return  WOLFSSL_SUCCESS on success, including when there was nothing to do.
1502
 * @return  WOLFSSL_FATAL_ERROR when ssl is NULL, unsupported, or on error.
1503
 */
1504
int wolfSSL_dtls13_do_scheduled_work(WOLFSSL* ssl)
1505
{
1506
    int ret;
1507
1508
    WOLFSSL_ENTER("wolfSSL_dtls13_do_scheduled_work");
1509
1510
    if (ssl == NULL)
1511
        return WOLFSSL_FATAL_ERROR;
1512
1513
    /* Rejecting the object is a usage error, not something that happened to
1514
     * the connection, so leave ssl->error alone. It is sticky: SendData()
1515
     * only clears it for WANT_WRITE, WC_PENDING_E and the DTLS MAC/decrypt
1516
     * cases, and wolfSSL_write() skips the write-dup drain entirely while it
1517
     * is set, so recording one here would disable the very drain a write-dup
1518
     * application relies on. */
1519
#ifdef HAVE_WRITE_DUP
1520
    if (ssl->dupWrite != NULL) {
1521
        WOLFSSL_MSG("Write dup objects drain through wolfSSL_write");
1522
        WOLFSSL_LEAVE("wolfSSL_dtls13_do_scheduled_work", WOLFSSL_FATAL_ERROR);
1523
        return WOLFSSL_FATAL_ERROR;
1524
    }
1525
#endif
1526
1527
    if (!Dtls13ScheduledWorkObject(ssl)) {
1528
        WOLFSSL_MSG("Not a DTLS 1.3 object this API handles");
1529
        WOLFSSL_LEAVE("wolfSSL_dtls13_do_scheduled_work", WOLFSSL_FATAL_ERROR);
1530
        return WOLFSSL_FATAL_ERROR;
1531
    }
1532
1533
    if (!Dtls13ScheduledWorkReady(ssl))
1534
        return WOLFSSL_SUCCESS;
1535
1536
    /* An earlier call may have left a record only partly written. Retry it
1537
     * first: the request that produced it has already been consumed, so
1538
     * nothing else would send it, and every other caller of
1539
     * Dtls13DoScheduledWork() pairs it with this same flush. Only a record
1540
     * this API built is retried here, which is what dtls13SendingAckOrRtx
1541
     * marks, so a partly written application record is left to the
1542
     * wolfSSL_write() the caller has to repeat anyway. */
1543
    if (ssl->buffers.outputBuffer.length > 0 && ssl->dtls13SendingAckOrRtx) {
1544
        ret = SendBuffered(ssl);
1545
        if (ret != 0) {
1546
            ssl->error = ret;
1547
            WOLFSSL_ERROR(ret);
1548
            return WOLFSSL_FATAL_ERROR;
1549
        }
1550
        ssl->dtls13SendingAckOrRtx = 0;
1551
    }
1552
1553
    ret = Dtls13DoScheduledWork(ssl);
1554
    if (ret < 0) {
1555
        ssl->error = ret;
1556
        WOLFSSL_ERROR(ret);
1557
        return WOLFSSL_FATAL_ERROR;
1558
    }
1559
1560
    /* Answer a KeyUpdate the peer requested. The read path defers this the
1561
     * same way, and SendData() is otherwise the only thing that clears it.
1562
     * Skip it while one of ours is still unacknowledged: DTLS must not have
1563
     * two KeyUpdates in flight, and Dtls13DoScheduledWork() above may have
1564
     * just started one. */
1565
    if (ssl->options.sendKeyUpdate && Dtls13CanSendKeyUpdate(ssl)) {
1566
        /* Drop the request before sending, as SendData() does. DTLS commits
1567
         * the record to the retransmit queue and consumes the handshake
1568
         * number on WANT_WRITE as well, and sets dtls13WaitKeyUpdateAck
1569
         * unconditionally, so the update is under way from that point on.
1570
         * Leaving the request set would send a second one once the peer
1571
         * acknowledges the first. */
1572
        ssl->options.sendKeyUpdate = 0;
1573
        /* Mark the record as ours so a short write is retried by the flush
1574
         * above rather than waiting for a retransmission timer. */
1575
        ssl->dtls13SendingAckOrRtx = 1;
1576
        ret = SendTls13KeyUpdate(ssl);
1577
        if (ret != 0) {
1578
            /* Keep the mark only while there is something left to send, so a
1579
             * failure that wrote nothing does not leave it standing. */
1580
            ssl->dtls13SendingAckOrRtx =
1581
                (ssl->buffers.outputBuffer.length > 0);
1582
            ssl->error = ret;
1583
            WOLFSSL_ERROR(ret);
1584
            return WOLFSSL_FATAL_ERROR;
1585
        }
1586
        ssl->dtls13SendingAckOrRtx = 0;
1587
    }
1588
1589
    WOLFSSL_LEAVE("wolfSSL_dtls13_do_scheduled_work", WOLFSSL_SUCCESS);
1590
1591
    return WOLFSSL_SUCCESS;
1592
}
1593
#endif /* WOLFSSL_DTLS13 */
1594
1595
#endif /* DTLS */
1596
#endif /* LEANPSK */
1597
1598
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
1599
1600
/* Set the DTLS cookie secret used to generate HelloVerifyRequest cookies.
1601
 *
1602
 * When secret is NULL a new secret is randomly generated. The object's RNG
1603
 * must be initialized. This is not an SSL function.
1604
 *
1605
 * @param [in] ssl       SSL/TLS object.
1606
 * @param [in] secret    Cookie secret data, or NULL to generate one.
1607
 * @param [in] secretSz  Length of secret in bytes, 0 to use the default.
1608
 * @return  0 on success.
1609
 * @return  BAD_FUNC_ARG when ssl is NULL or secret is set with size 0.
1610
 * @return  MEMORY_ERROR on allocation failure.
1611
 */
1612
int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
1613
                                 const byte* secret, word32 secretSz)
1614
{
1615
    int ret = 0;
1616
1617
    WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret");
1618
1619
    if (ssl == NULL) {
1620
        WOLFSSL_MSG("need a SSL object");
1621
        return BAD_FUNC_ARG;
1622
    }
1623
1624
    if (secret != NULL && secretSz == 0) {
1625
        WOLFSSL_MSG("can't have a new secret without a size");
1626
        return BAD_FUNC_ARG;
1627
    }
1628
1629
    /* If secretSz is 0, use the default size. */
1630
    if (secretSz == 0)
1631
        secretSz = COOKIE_SECRET_SZ;
1632
1633
    if (secretSz != ssl->buffers.dtlsCookieSecret.length) {
1634
        byte* newSecret;
1635
1636
        if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
1637
            ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
1638
                      ssl->buffers.dtlsCookieSecret.length);
1639
            XFREE(ssl->buffers.dtlsCookieSecret.buffer,
1640
                  ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
1641
        }
1642
1643
        newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD);
1644
        if (newSecret == NULL) {
1645
            ssl->buffers.dtlsCookieSecret.buffer = NULL;
1646
            ssl->buffers.dtlsCookieSecret.length = 0;
1647
            WOLFSSL_MSG("couldn't allocate new cookie secret");
1648
            return MEMORY_ERROR;
1649
        }
1650
        ssl->buffers.dtlsCookieSecret.buffer = newSecret;
1651
        ssl->buffers.dtlsCookieSecret.length = secretSz;
1652
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1653
        wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecret secret",
1654
            ssl->buffers.dtlsCookieSecret.buffer,
1655
            ssl->buffers.dtlsCookieSecret.length);
1656
    #endif
1657
    }
1658
1659
    /* If the supplied secret is NULL, randomly generate a new secret. */
1660
    if (secret == NULL) {
1661
        ret = wc_RNG_GenerateBlock(ssl->rng,
1662
                             ssl->buffers.dtlsCookieSecret.buffer, secretSz);
1663
    }
1664
    else
1665
        XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz);
1666
1667
    WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0);
1668
    return ret;
1669
}
1670
1671
struct chGoodDisableReadCbCtx {
1672
    ClientHelloGoodCb userCb;
1673
    void*             userCtx;
1674
};
1675
1676
/* ClientHello good callback that stops reading.
1677
 *
1678
 * Wraps the user's callback so that reading is disabled once a ClientHello
1679
 * with a valid cookie has been received. Used by wolfDTLS_accept_stateless().
1680
 *
1681
 * @param [in] ssl  SSL/TLS object.
1682
 * @param [in] ctx  Context with user callback and its context.
1683
 * @return  0 on success or when no user callback set.
1684
 * @return  Value returned by the user callback when negative.
1685
 */
1686
static int chGoodDisableReadCB(WOLFSSL* ssl, void* ctx)
1687
{
1688
    struct chGoodDisableReadCbCtx* cb = (struct chGoodDisableReadCbCtx*)ctx;
1689
    int ret = 0;
1690
    if (cb->userCb != NULL)
1691
        ret = cb->userCb(ssl, cb->userCtx);
1692
    if (ret >= 0)
1693
        wolfSSL_SSLDisableRead(ssl);
1694
    return ret;
1695
}
1696
1697
/**
1698
 * Statelessly listen for a connection
1699
 * @param ssl The ssl object to use for listening to connections
1700
 * @return WOLFSSL_SUCCESS - ClientHello containing a valid cookie was received
1701
 *                           The connection can be continued with wolfSSL_accept
1702
 *         WOLFSSL_FAILURE - The I/O layer returned WANT_READ. This is either
1703
 *                           because there is no data to read and we are using
1704
 *                           non-blocking sockets or we sent a cookie request
1705
 *                           and we are waiting for a reply. The user should
1706
 *                           call wolfDTLS_accept_stateless again after data
1707
 *                           becomes available in the I/O layer.
1708
 *         WOLFSSL_FATAL_ERROR - A fatal error occurred. The ssl object should
1709
 *                           be free'd and allocated again to continue.
1710
 */
1711
int wolfDTLS_accept_stateless(WOLFSSL* ssl)
1712
{
1713
    byte disableRead;
1714
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
1715
    struct chGoodDisableReadCbCtx cb;
1716
1717
    WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
1718
1719
    if (ssl == NULL)
1720
        return WOLFSSL_FATAL_ERROR;
1721
1722
    /* Save this to restore it later */
1723
    disableRead = (byte)ssl->options.disableRead;
1724
    cb.userCb = ssl->chGoodCb;
1725
    cb.userCtx = ssl->chGoodCtx;
1726
1727
    /* Register our own callback so that we can disable reading */
1728
    if (wolfDTLS_SetChGoodCb(ssl, chGoodDisableReadCB, &cb) != WOLFSSL_SUCCESS)
1729
        return WOLFSSL_FATAL_ERROR;
1730
1731
    ssl->options.returnOnGoodCh = 1;
1732
    ret = wolfSSL_accept(ssl);
1733
    ssl->options.returnOnGoodCh = 0;
1734
    /* restore user options */
1735
    ssl->options.disableRead = disableRead;
1736
    (void)wolfDTLS_SetChGoodCb(ssl, cb.userCb, cb.userCtx);
1737
    if (ret == WOLFSSL_SUCCESS) {
1738
        WOLFSSL_MSG("should not happen. maybe the user called "
1739
                    "wolfDTLS_accept_stateless instead of wolfSSL_accept");
1740
    }
1741
    else if (ssl->error == WC_NO_ERR_TRACE(WANT_READ) ||
1742
             ssl->error == WC_NO_ERR_TRACE(WANT_WRITE)) {
1743
        ssl->error = 0;
1744
        if (ssl->options.dtlsStateful)
1745
            ret = WOLFSSL_SUCCESS;
1746
        else
1747
            ret = WOLFSSL_FAILURE;
1748
    }
1749
    else {
1750
        ret = WOLFSSL_FATAL_ERROR;
1751
    }
1752
    return ret;
1753
}
1754
1755
/* Set the callback to call when a ClientHello with a valid cookie is received.
1756
 *
1757
 * WC_NO_INLINE: wolfDTLS_accept_stateless passes the address of a stack-local
1758
 * context here; the restore call before return clears it again. Preventing
1759
 * inlining hides that cross-frame assignment from GCC's -Wdangling-pointer
1760
 * analysis, which otherwise flags a false positive on GCC 14+.
1761
 *
1762
 * @param [in] ssl       SSL/TLS object.
1763
 * @param [in] cb        Callback to call. NULL to clear.
1764
 * @param [in] user_ctx  Context to pass to the callback.
1765
 * @return  WOLFSSL_SUCCESS on success.
1766
 * @return  BAD_FUNC_ARG when ssl is NULL.
1767
 */
1768
WC_NO_INLINE
1769
int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
1770
{
1771
    WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
1772
1773
    if (ssl == NULL)
1774
        return BAD_FUNC_ARG;
1775
1776
    ssl->chGoodCb  = cb;
1777
    ssl->chGoodCtx = user_ctx;
1778
1779
    return WOLFSSL_SUCCESS;
1780
}
1781
1782
/* Set a secondary DTLS 1.2 cookie secret used only when verifying a received
1783
 * HelloVerifyRequest cookie, and only if the primary secret (set by
1784
 * wolfSSL_DTLS_SetCookieSecret()) fails to verify it.
1785
 *
1786
 * This supports an application-driven cookie-secret rotation on a stateless
1787
 * server: after rotating the primary secret, install the previous secret here
1788
 * so that cookies already issued under it are still accepted for an overlap
1789
 * window.  It is never used to issue cookies.
1790
 *
1791
 * This is the DTLS 1.2 counterpart of wolfSSL_set_hrr_cookie_secret_secondary()
1792
 * (which covers the DTLS 1.3 HelloRetryRequest cookie); the two cookie
1793
 * mechanisms keep separate secrets, so a server that handles both versions sets
1794
 * both secondary secrets.
1795
 *
1796
 * @param [in] ssl       SSL/TLS object.
1797
 * @param [in] secret    Secondary secret to verify cookies against.  A value
1798
 *                       of NULL (or a secretSz of 0) clears any previously set
1799
 *                       secondary secret.
1800
 * @param [in] secretSz  Size of secret data in bytes.
1801
 * @return  0 on success.
1802
 * @return  BAD_FUNC_ARG when ssl is NULL.
1803
 * @return  MEMORY_ERROR on allocation failure.
1804
 */
1805
int wolfSSL_DTLS_SetCookieSecretSecondary(WOLFSSL* ssl,
1806
                                          const byte* secret, word32 secretSz)
1807
{
1808
    byte* newSecret;
1809
1810
    WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecretSecondary");
1811
1812
    if (ssl == NULL) {
1813
        WOLFSSL_MSG("need a SSL object");
1814
        return BAD_FUNC_ARG;
1815
    }
1816
1817
    /* Clear any existing secondary secret. */
1818
    if (ssl->buffers.dtlsCookieSecretSecondary.buffer != NULL) {
1819
        ForceZero(ssl->buffers.dtlsCookieSecretSecondary.buffer,
1820
                  ssl->buffers.dtlsCookieSecretSecondary.length);
1821
        XFREE(ssl->buffers.dtlsCookieSecretSecondary.buffer,
1822
              ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
1823
        ssl->buffers.dtlsCookieSecretSecondary.buffer = NULL;
1824
        ssl->buffers.dtlsCookieSecretSecondary.length = 0;
1825
    }
1826
1827
    /* A NULL/empty secret just clears the secondary secret. */
1828
    if (secret == NULL || secretSz == 0) {
1829
        WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecretSecondary", 0);
1830
        return 0;
1831
    }
1832
1833
    newSecret = (byte*)XMALLOC(secretSz, ssl->heap, DYNAMIC_TYPE_COOKIE_PWD);
1834
    if (newSecret == NULL) {
1835
        WOLFSSL_MSG("couldn't allocate secondary cookie secret");
1836
        return MEMORY_ERROR;
1837
    }
1838
    XMEMCPY(newSecret, secret, secretSz);
1839
    ssl->buffers.dtlsCookieSecretSecondary.buffer = newSecret;
1840
    ssl->buffers.dtlsCookieSecretSecondary.length = secretSz;
1841
#ifdef WOLFSSL_CHECK_MEM_ZERO
1842
    wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecretSecondary secret",
1843
        ssl->buffers.dtlsCookieSecretSecondary.buffer,
1844
        ssl->buffers.dtlsCookieSecretSecondary.length);
1845
#endif
1846
1847
    WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecretSecondary", 0);
1848
    return 0;
1849
}
1850
1851
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
1852
1853
#endif /* !WOLFCRYPT_ONLY */
1854
1855
#endif /* !WOLFSSL_SSL_API_DTLS_INCLUDED */