Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-sp-math-all/src/wolfio.c
Line
Count
Source
1
/* wolfio.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
23
#ifndef WOLFSSL_STRERROR_BUFFER_SIZE
24
#define WOLFSSL_STRERROR_BUFFER_SIZE 256
25
#endif
26
27
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
28
29
#ifndef WOLFCRYPT_ONLY
30
31
#if defined(HAVE_ERRNO_H) && defined(WOLFSSL_NO_SOCK) && \
32
    (defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT))
33
    /* error codes are needed for TranslateIoReturnCode() and
34
     * wolfIO_TcpConnect() even if defined(WOLFSSL_NO_SOCK), which inhibits
35
     * inclusion of errno.h by wolfio.h.
36
     */
37
    #include <errno.h>
38
#endif
39
40
#include <wolfssl/internal.h>
41
#include <wolfssl/error-ssl.h>
42
#include <wolfssl/wolfio.h>
43
#include <wolfssl/wolfcrypt/logging.h>
44
45
46
#ifdef NUCLEUS_PLUS_2_3
47
/* Holds last Nucleus networking error number */
48
int Nucleus_Net_Errno;
49
#endif
50
51
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
52
    #ifdef USE_WINDOWS_API
53
        #include <winsock2.h>
54
    #else
55
        #if defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT)
56
        #elif defined(ARDUINO)
57
        #elif defined(FREESCALE_MQX)
58
        #elif defined(FREESCALE_KSDK_MQX)
59
        #elif (defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET))
60
        #elif defined(WOLFSSL_CMSIS_RTOS)
61
        #elif defined(WOLFSSL_CMSIS_RTOSv2)
62
        #elif defined(WOLFSSL_TIRTOS)
63
        #elif defined(FREERTOS_TCP)
64
        #elif defined(WOLFSSL_IAR_ARM)
65
        #elif defined(HAVE_NETX_BSD)
66
        #elif defined(WOLFSSL_VXWORKS)
67
        #elif defined(WOLFSSL_NUCLEUS_1_2)
68
        #elif defined(WOLFSSL_LINUXKM)
69
            /* the requisite linux/net.h is included in wc_port.h, with incompatible warnings masked out. */
70
        #elif defined(WOLFSSL_ATMEL)
71
        #elif defined(INTIME_RTOS)
72
            #include <netdb.h>
73
        #elif defined(WOLFSSL_PRCONNECT_PRO)
74
            #include <netdb.h>
75
            #include <sys/ioctl.h>
76
        #elif defined(WOLFSSL_SGX)
77
        #elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
78
        #elif defined(WOLFSSL_DEOS)
79
        #elif defined(WOLFSSL_ZEPHYR)
80
        #elif defined(MICROCHIP_PIC32)
81
        #elif defined(HAVE_NETX)
82
        #elif defined(FUSION_RTOS)
83
        #elif !defined(WOLFSSL_NO_SOCK)
84
            #if defined(HAVE_RTP_SYS)
85
            #elif defined(EBSNET)
86
            #elif defined(NETOS)
87
            #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) \
88
                    && !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_WICED) \
89
                    && !defined(WOLFSSL_GNRC) && !defined(WOLFSSL_RIOT_OS)
90
                #ifdef HAVE_NETDB_H
91
                    #include <netdb.h>
92
                #endif
93
                #ifdef __PPU
94
                    #include <netex/errno.h>
95
                #else
96
                    #ifdef HAVE_SYS_IOCTL_H
97
                        #include <sys/ioctl.h>
98
                    #endif
99
                #endif
100
            #endif
101
        #endif
102
103
    #endif /* USE_WINDOWS_API */
104
#endif /* defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) */
105
106
107
#if defined(HAVE_HTTP_CLIENT)
108
    #include <stdlib.h>   /* strtol() */
109
#endif
110
111
/*
112
Possible IO enable options:
113
 * WOLFSSL_USER_IO:     Disables default Embed* callbacks and     default: off
114
                        allows user to define their own using
115
                        wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
116
 * USE_WOLFSSL_IO:      Enables the wolfSSL IO functions          default: on
117
 * HAVE_HTTP_CLIENT:    Enables HTTP client API's                 default: off
118
                                     (unless HAVE_OCSP or HAVE_CRL_IO defined)
119
 * HAVE_IO_TIMEOUT:     Enables support for connect timeout       default: off
120
 *
121
 * DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
122
 * ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
123
 * indefinitely. If not enabled EmbedReceiveFrom will return timeout after
124
 * DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
125
 * enabled, without a timer, EmbedReceivefrom can't check if the timeout is
126
 * expired and it may never return under a continuous flow of invalid packets.
127
 *                                                                default: off
128
 */
129
130
131
/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
132
   automatic setting of default I/O functions EmbedSend() and EmbedReceive()
133
   but they'll still need SetCallback xxx() at end of file
134
*/
135
136
#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
137
  && !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
138
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
139
#endif
140
141
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
142
143
static WC_INLINE int wolfSSL_LastError(int err, SOCKET_T sd)
144
0
{
145
0
    (void)sd;
146
147
0
    if (err > 0)
148
0
        return 0;
149
150
#ifdef USE_WINDOWS_API
151
    return WSAGetLastError();
152
#elif defined(EBSNET)
153
    return xn_getlasterror();
154
#elif defined(WOLFSSL_LINUXKM)
155
    return -err; /* Return provided error value with corrected sign. */
156
#elif defined(WOLFSSL_EMNET)
157
    /* Any negative recv/send return is a SOCKET_ERROR sentinel under
158
     * emNET; the canonical IP_ERR_* lives in the socket SO_ERROR.
159
     * Retrieving it via IP_SOCK_getsockopt works across both emNET
160
     * integrator conventions (native: recv returns IP_ERR_* directly;
161
     * POSIX facade: recv returns -1 with errno set). If the lookup
162
     * itself fails, fall back to IP_ERR_FAULT rather than returning
163
     * the raw -1 sentinel - the latter matches no SOCKET_E* constant
164
     * and would regress into WOLFSSL_CBIO_ERR_GENERAL. */
165
    if (err < 0) {
166
        int sock_err = err;
167
        if (IP_SOCK_getsockopt(sd, SOL_SOCKET, SO_ERROR, &sock_err,
168
                               (int)sizeof(sock_err)) == 0) {
169
            err = sock_err;
170
        }
171
        else if (err == -1) {
172
            err = IP_ERR_FAULT;
173
        }
174
    }
175
    return err;
176
#elif defined(FUSION_RTOS)
177
    #include <fclerrno.h>
178
    return FCL_GET_ERRNO;
179
#elif defined(NUCLEUS_PLUS_2_3)
180
    return Nucleus_Net_Errno;
181
#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
182
    if ((err == 0) || (err == -SOCKET_EWOULDBLOCK)) {
183
        return SOCKET_EWOULDBLOCK; /* convert to BSD style wouldblock */
184
    } else {
185
        err = RTCS_geterror(sd);
186
        if ((err == RTCSERR_TCP_CONN_CLOSING) ||
187
            (err == RTCSERR_TCP_CONN_RLSD))
188
        {
189
            err = SOCKET_ECONNRESET;
190
        }
191
        return err;
192
    }
193
#else
194
0
    return errno;
195
0
#endif
196
0
}
197
198
/* Translates return codes returned from
199
 * send(), recv(), and other network I/O calls.
200
 */
201
static int TranslateIoReturnCode(int err, SOCKET_T sd, int direction)
202
0
{
203
#if defined(_WIN32) && !defined(__WATCOMC__) && !defined(_WIN32_WCE) && \
204
    !defined(INTIME_RTOS)
205
    size_t errstr_offset;
206
    char errstr[WOLFSSL_STRERROR_BUFFER_SIZE];
207
#endif /* _WIN32 */
208
209
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
210
    if (err > 0)
211
        return err;
212
#else
213
0
    if (err >= 0)
214
0
        return err;
215
0
#endif
216
217
0
    err = wolfSSL_LastError(err, sd);
218
219
#if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN
220
    if ((err == SOCKET_EWOULDBLOCK) || (err == SOCKET_EAGAIN))
221
#else
222
0
    if (err == SOCKET_EWOULDBLOCK)
223
0
#endif
224
0
    {
225
0
        WOLFSSL_MSG("\tWould block");
226
0
        if (direction == SOCKET_SENDING)
227
0
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
228
0
        else if (direction == SOCKET_RECEIVING)
229
0
            return WOLFSSL_CBIO_ERR_WANT_READ;
230
0
        else
231
0
            return WOLFSSL_CBIO_ERR_GENERAL;
232
0
    }
233
234
0
#ifdef SOCKET_ETIMEDOUT
235
0
    else if (err == SOCKET_ETIMEDOUT) {
236
0
        WOLFSSL_MSG("\tTimed out");
237
0
        if (direction == SOCKET_SENDING)
238
0
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
239
0
        else if (direction == SOCKET_RECEIVING)
240
0
            return WOLFSSL_CBIO_ERR_WANT_READ;
241
0
        else
242
0
            return WOLFSSL_CBIO_ERR_TIMEOUT;
243
0
    }
244
0
#endif /* SOCKET_ETIMEDOUT */
245
246
0
    else if (err == SOCKET_ECONNRESET) {
247
0
        WOLFSSL_MSG("\tConnection reset");
248
0
        return WOLFSSL_CBIO_ERR_CONN_RST;
249
0
    }
250
0
    else if (err == SOCKET_EINTR) {
251
0
        WOLFSSL_MSG("\tSocket interrupted");
252
0
        return WOLFSSL_CBIO_ERR_ISR;
253
0
    }
254
0
    else if (err == SOCKET_EPIPE) {
255
0
        WOLFSSL_MSG("\tBroken pipe");
256
0
        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
257
0
    }
258
0
    else if (err == SOCKET_ECONNABORTED) {
259
0
        WOLFSSL_MSG("\tConnection aborted");
260
0
        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
261
0
    }
262
263
#if defined(_WIN32) && !defined(__WATCOMC__) && !defined(_WIN32_WCE) && \
264
    !defined(INTIME_RTOS)
265
    strcpy_s(errstr, sizeof(errstr), "\tGeneral error: ");
266
    errstr_offset = strlen(errstr);
267
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
268
        NULL,
269
        err,
270
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
271
        (LPSTR)(errstr + errstr_offset),
272
        (DWORD)(sizeof(errstr) - errstr_offset),
273
        NULL);
274
    WOLFSSL_MSG(errstr);
275
#else
276
0
    WOLFSSL_MSG_EX("\tGeneral error: %d", err);
277
0
#endif
278
0
    return WOLFSSL_CBIO_ERR_GENERAL;
279
0
}
280
#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
281
282
#ifdef OPENSSL_EXTRA
283
#ifndef NO_BIO
284
285
int wolfSSL_BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
286
{
287
    return SslBioSend(ssl, buf, sz, ctx);
288
}
289
290
int wolfSSL_BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
291
{
292
    return SslBioReceive(ssl, buf, sz, ctx);
293
}
294
295
int BioReceiveInternal(WOLFSSL_BIO* biord, WOLFSSL_BIO* biowr, char* buf,
296
                       int sz)
297
{
298
    int recvd = WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_GENERAL);
299
300
    WOLFSSL_ENTER("SslBioReceive");
301
302
    if (biord == NULL) {
303
        WOLFSSL_MSG("WOLFSSL biord not set");
304
        return WOLFSSL_CBIO_ERR_GENERAL;
305
    }
306
307
    recvd = wolfSSL_BIO_read(biord, buf, sz);
308
    if (recvd <= 0) {
309
        if (biowr != NULL &&
310
            /* ssl->biowr->wrIdx is checked for Bind9 */
311
            wolfSSL_BIO_method_type(biowr) == WOLFSSL_BIO_BIO &&
312
            wolfSSL_BIO_wpending(biowr) != 0 &&
313
            /* Not sure this pending check is necessary but let's double
314
             * check that the read BIO is empty before we signal a write
315
             * need */
316
            wolfSSL_BIO_supports_pending(biord) &&
317
            wolfSSL_BIO_ctrl_pending(biord) == 0) {
318
            /* Let's signal to the app layer that we have
319
             * data pending that needs to be sent. */
320
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
321
        }
322
        else if (biord->type == WOLFSSL_BIO_SOCKET) {
323
            if (recvd == 0) {
324
                WOLFSSL_MSG("SslBioReceive connection closed");
325
                return WOLFSSL_CBIO_ERR_CONN_CLOSE;
326
            }
327
        #ifdef USE_WOLFSSL_IO
328
            recvd = TranslateIoReturnCode(recvd, biord->num.fd,
329
                                          SOCKET_RECEIVING);
330
        #endif
331
            return recvd;
332
        }
333
334
        /* If retry and read flags are set, return WANT_READ */
335
        if ((biord->flags & WOLFSSL_BIO_FLAG_READ) &&
336
            (biord->flags & WOLFSSL_BIO_FLAG_RETRY)) {
337
            return WOLFSSL_CBIO_ERR_WANT_READ;
338
        }
339
340
        WOLFSSL_MSG("BIO general error");
341
        return WOLFSSL_CBIO_ERR_GENERAL;
342
    }
343
344
    return recvd;
345
}
346
347
/* Use the WOLFSSL read BIO for receiving data. This is set by the function
348
 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
349
 *
350
 * ssl  WOLFSSL struct passed in that has this function set as the receive
351
 *      callback.
352
 * buf  buffer to fill with data read
353
 * sz   size of buf buffer
354
 * ctx  a user set context
355
 *
356
 * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
357
 */
358
int SslBioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
359
{
360
    WOLFSSL_ENTER("SslBioReceive");
361
    (void)ctx;
362
    return BioReceiveInternal(ssl->biord, ssl->biowr, buf, sz);
363
}
364
365
366
/* Use the WOLFSSL write BIO for sending data. This is set by the function
367
 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
368
 *
369
 * ssl  WOLFSSL struct passed in that has this function set as the send callback.
370
 * buf  buffer with data to write out
371
 * sz   size of buf buffer
372
 * ctx  a user set context
373
 *
374
 * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
375
 */
376
int SslBioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
377
{
378
    int sent = WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_GENERAL);
379
380
    WOLFSSL_ENTER("SslBioSend");
381
382
    if (ssl->biowr == NULL) {
383
        WOLFSSL_MSG("WOLFSSL biowr not set");
384
        return WOLFSSL_CBIO_ERR_GENERAL;
385
    }
386
387
    sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
388
    if (sent <= 0) {
389
        if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) {
390
        #ifdef USE_WOLFSSL_IO
391
            sent = TranslateIoReturnCode(sent, ssl->biowr->num.fd,
392
                                         SOCKET_SENDING);
393
        #endif
394
            return sent;
395
        }
396
        else if (ssl->biowr->type == WOLFSSL_BIO_BIO) {
397
            if (sent == WOLFSSL_BIO_ERROR) {
398
                WOLFSSL_MSG("\tWould Block");
399
                return WOLFSSL_CBIO_ERR_WANT_WRITE;
400
            }
401
        }
402
403
        /* If retry and write flags are set, return WANT_WRITE */
404
        if ((ssl->biowr->flags & WOLFSSL_BIO_FLAG_WRITE) &&
405
            (ssl->biowr->flags & WOLFSSL_BIO_FLAG_RETRY)) {
406
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
407
        }
408
409
        return WOLFSSL_CBIO_ERR_GENERAL;
410
    }
411
    (void)ctx;
412
413
    return sent;
414
}
415
#endif /* !NO_BIO */
416
#endif /* OPENSSL_EXTRA */
417
418
419
#ifdef USE_WOLFSSL_IO
420
421
#ifndef WOLFSSL_DTLS_ONLY
422
/* The receive embedded callback
423
 *  return : nb bytes read, or error
424
 */
425
int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
426
0
{
427
0
    int recvd;
428
0
#ifndef WOLFSSL_LINUXKM
429
0
    int sd = *(int*)ctx;
430
#else
431
    struct socket *sd = (struct socket*)ctx;
432
#endif
433
434
0
    recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
435
0
    if (recvd < 0) {
436
0
        WOLFSSL_MSG("Embed Receive error");
437
0
    }
438
0
    else if (recvd == 0) {
439
0
        WOLFSSL_MSG("Embed receive connection closed");
440
0
        return WOLFSSL_CBIO_ERR_CONN_CLOSE;
441
0
    }
442
443
0
    return recvd;
444
0
}
445
446
/* The send embedded callback
447
 *  return : nb bytes sent, or error
448
 */
449
int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
450
0
{
451
0
    int sent;
452
0
#ifndef WOLFSSL_LINUXKM
453
0
    int sd = *(int*)ctx;
454
#else
455
    struct socket *sd = (struct socket*)ctx;
456
#endif
457
458
#ifdef WOLFSSL_MAX_SEND_SZ
459
    if (sz > WOLFSSL_MAX_SEND_SZ)
460
        sz = WOLFSSL_MAX_SEND_SZ;
461
#endif
462
463
0
    sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
464
0
    if (sent < 0) {
465
0
        WOLFSSL_MSG("Embed Send error");
466
0
    }
467
468
0
    return sent;
469
0
}
470
#endif /* !WOLFSSL_DTLS_ONLY */
471
472
473
#ifdef WOLFSSL_DTLS
474
475
#include <wolfssl/wolfcrypt/sha.h>
476
477
#if defined(NUCLEUS_PLUS_2_3)
478
STATIC INT32 nucyassl_recv(INT sd, CHAR *buf, UINT16 sz, INT16 flags)
479
{
480
    int recvd;
481
482
    /* Read data from socket */
483
    recvd = NU_Recv(sd, buf, sz, flags);
484
    if (recvd < 0) {
485
        if (recvd == NU_NOT_CONNECTED) {
486
            recvd = 0;
487
        } else {
488
            Nucleus_Net_Errno = recvd;
489
            recvd = WOLFSSL_FATAL_ERROR;
490
        }
491
    } else {
492
        Nucleus_Net_Errno = 0;
493
    }
494
495
    return (recvd);
496
}
497
498
499
STATIC int nucyassl_send(INT sd, CHAR *buf, UINT16 sz, INT16 flags)
500
{
501
    int sent;
502
503
    /* Write data to socket */
504
    sent = NU_Send(sd, buf, sz, flags);
505
506
    if (sent < 0) {
507
        Nucleus_Net_Errno = sent;
508
        sent = WOLFSSL_FATAL_ERROR;
509
    } else {
510
        Nucleus_Net_Errno = 0;
511
    }
512
513
    return sent;
514
}
515
516
#define SELECT_FUNCTION     nucyassl_select
517
518
int nucyassl_select(INT sd, UINT32 timeout)
519
{
520
    FD_SET readfs;
521
    STATUS status;
522
523
    /* Init fs data for socket */
524
    NU_FD_Init(&readfs);
525
    NU_FD_Set(sd, &readfs);
526
527
    /* Wait for data to arrive */
528
    status = NU_Select((sd + 1), &readfs, NU_NULL, NU_NULL,
529
                            (timeout * NU_TICKS_PER_SECOND));
530
531
    if (status < 0) {
532
        Nucleus_Net_Errno = status;
533
        status = WOLFSSL_FATAL_ERROR;
534
    }
535
536
    return status;
537
}
538
539
#define sockaddr_storage    addr_struct
540
#define sockaddr            addr_struct
541
542
STATIC INT32 nucyassl_recvfrom(INT sd, CHAR *buf, UINT16 sz, INT16 flags,
543
                              SOCKADDR *peer, XSOCKLENT *peersz)
544
{
545
    int recvd;
546
547
    memset(peer, 0, sizeof(struct addr_struct));
548
549
    recvd = NU_Recv_From(sd, buf, sz, flags, (struct addr_struct *) peer,
550
                            (INT16*) peersz);
551
    if (recvd < 0) {
552
        Nucleus_Net_Errno = recvd;
553
        recvd = WOLFSSL_FATAL_ERROR;
554
    } else {
555
        Nucleus_Net_Errno = 0;
556
    }
557
558
    return recvd;
559
560
}
561
562
STATIC int nucyassl_sendto(INT sd, CHAR *buf, UINT16 sz, INT16 flags,
563
                          const SOCKADDR *peer, INT16 peersz)
564
{
565
    int sent;
566
567
    sent = NU_Send_To(sd, buf, sz, flags, (const struct addr_struct *) peer,
568
                            peersz);
569
570
    if (sent < 0) {
571
        Nucleus_Net_Errno = sent;
572
        sent = WOLFSSL_FATAL_ERROR;
573
    } else {
574
        Nucleus_Net_Errno = 0;
575
    }
576
577
    return sent;
578
}
579
#endif /* NUCLEUS_PLUS_2_3 */
580
581
#ifndef DTLS_SENDTO_FUNCTION
582
    #define DTLS_SENDTO_FUNCTION sendto
583
#endif
584
#ifndef DTLS_RECVFROM_FUNCTION
585
    #define DTLS_RECVFROM_FUNCTION recvfrom
586
#endif
587
588
int sockAddrEqual(
589
    SOCKADDR_S *a, XSOCKLENT aLen, SOCKADDR_S *b, XSOCKLENT bLen)
590
{
591
    if (aLen != bLen)
592
        return 0;
593
594
    if (a->ss_family != b->ss_family)
595
        return 0;
596
597
    if (a->ss_family == WOLFSSL_IP4) {
598
599
        if (aLen < (XSOCKLENT)sizeof(SOCKADDR_IN))
600
            return 0;
601
602
        if (((SOCKADDR_IN*)a)->sin_port != ((SOCKADDR_IN*)b)->sin_port)
603
            return 0;
604
605
        if (((SOCKADDR_IN*)a)->sin_addr.s_addr !=
606
            ((SOCKADDR_IN*)b)->sin_addr.s_addr)
607
            return 0;
608
609
        return 1;
610
    }
611
612
#ifdef WOLFSSL_IPV6
613
    if (a->ss_family == WOLFSSL_IP6) {
614
        SOCKADDR_IN6 *a6, *b6;
615
616
        if (aLen < (XSOCKLENT)sizeof(SOCKADDR_IN6))
617
            return 0;
618
619
        a6 = (SOCKADDR_IN6*)a;
620
        b6 = (SOCKADDR_IN6*)b;
621
622
        if (((SOCKADDR_IN6*)a)->sin6_port != ((SOCKADDR_IN6*)b)->sin6_port)
623
            return 0;
624
625
        if (XMEMCMP((void*)&a6->sin6_addr, (void*)&b6->sin6_addr,
626
                sizeof(a6->sin6_addr)) != 0)
627
            return 0;
628
629
        return 1;
630
    }
631
#endif /* WOLFSSL_IPV6 */
632
633
    return 0;
634
}
635
636
#ifndef WOLFSSL_IPV6
637
static int PeerIsIpv6(const SOCKADDR_S *peer, XSOCKLENT len)
638
{
639
    if (len < (XSOCKLENT)sizeof(peer->ss_family))
640
        return 0;
641
    return peer->ss_family == WOLFSSL_IP6;
642
}
643
#endif /* !WOLFSSL_IPV6 */
644
645
/* Return non-zero iff sfd is a SOCK_DGRAM socket. A descriptor's type is
646
 * fixed for its lifetime, so the probe runs where dtlsCtx.rfd/wfd is
647
 * assigned and the result is stored alongside the descriptor, keeping the
648
 * getsockopt() syscall out of the I/O callbacks. */
649
int wolfIO_SockIsDGram(int sfd)
650
{
651
    int type = 0;
652
    /* optvalue 'type' is of size int */
653
    XSOCKLENT length = (XSOCKLENT)sizeof(type);
654
655
    if (XSOCKET_GETSOCKOPT(sfd, SOL_SOCKET, SO_TYPE,
656
            (XSOCKOPT_TYPE_OPTVAL_TYPE)&type, &length) == 0 &&
657
            type != SOCK_DGRAM) {
658
        return 0;
659
    }
660
    else {
661
        return 1;
662
    }
663
}
664
665
void wolfSSL_SetRecvFrom(WOLFSSL* ssl, WolfSSLRecvFrom recvFrom)
666
{
667
    if (ssl != NULL)
668
        ssl->buffers.dtlsCtx.recvfrom = recvFrom;
669
}
670
671
void wolfSSL_SetSendTo(WOLFSSL* ssl, WolfSSLSento sendTo)
672
{
673
    if (ssl != NULL)
674
        ssl->buffers.dtlsCtx.sendto = sendTo;
675
}
676
677
/* The receive embedded callback
678
 *  return : nb bytes read, or error
679
 */
680
int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
681
{
682
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
683
    int recvd;
684
    int sd = dtlsCtx->rfd;
685
    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
686
    byte doDtlsTimeout;
687
    SOCKADDR_S lclPeer;
688
    SOCKADDR_S* peer;
689
    XSOCKLENT peerSz = 0;
690
#ifndef NO_ASN_TIME
691
    word32 start = 0;
692
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
693
    word32 invalidPeerPackets = 0;
694
#endif
695
    int newPeer = 0;
696
    int ret = 0;
697
698
    WOLFSSL_ENTER("EmbedReceiveFrom");
699
    (void)ret; /* possibly unused */
700
701
    if (sz < 0)
702
        return WOLFSSL_CBIO_ERR_GENERAL;
703
704
    XMEMSET(&lclPeer, 0, sizeof(lclPeer));
705
706
#ifdef WOLFSSL_RW_THREADED
707
    if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
708
        return WOLFSSL_CBIO_ERR_GENERAL;
709
#endif
710
711
    if (dtlsCtx->connected) {
712
        peer = NULL;
713
    }
714
    else if (dtlsCtx->userSet) {
715
#ifndef WOLFSSL_IPV6
716
        if (PeerIsIpv6((SOCKADDR_S*)dtlsCtx->peer.sa, dtlsCtx->peer.sz)) {
717
            WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
718
            ret = WOLFSSL_CBIO_ERR_GENERAL;
719
        }
720
#endif
721
        peer = &lclPeer;
722
        peerSz = sizeof(lclPeer);
723
    }
724
    else {
725
        /* Store the peer address. It is used to calculate the DTLS cookie. */
726
        newPeer = dtlsCtx->peer.sa == NULL || !ssl->options.dtlsStateful;
727
        peer = &lclPeer;
728
        peerSz = sizeof(lclPeer);
729
    }
730
731
#ifdef WOLFSSL_RW_THREADED
732
    /* We make a copy above to avoid holding the lock for the entire function */
733
    if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
734
        return WOLFSSL_CBIO_ERR_GENERAL;
735
#endif
736
737
    if (ret != 0)
738
        return ret;
739
740
    /* Don't use ssl->options.handShakeDone since it is true even if
741
     * we are in the process of renegotiation */
742
    doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
743
744
#ifdef WOLFSSL_DTLS13
745
    if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
746
        doDtlsTimeout = doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL;
747
#ifdef WOLFSSL_RW_THREADED
748
        ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
749
        if (ret != 0)
750
            return ret;
751
#endif
752
        doDtlsTimeout = doDtlsTimeout ||
753
            (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
754
#ifdef WOLFSSL_RW_THREADED
755
        wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
756
#endif
757
    }
758
#endif /* WOLFSSL_DTLS13 */
759
760
    do {
761
762
        if (!doDtlsTimeout) {
763
            dtls_timeout = 0;
764
        }
765
        else {
766
#ifndef NO_ASN_TIME
767
            if (start == 0) {
768
                start = LowResTimer();
769
            }
770
            else {
771
                dtls_timeout -= (int) (LowResTimer() - start);
772
                start = LowResTimer();
773
                if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
774
                    return WOLFSSL_CBIO_ERR_TIMEOUT;
775
            }
776
#endif
777
        }
778
779
        if (!wolfSSL_get_using_nonblock(ssl)) {
780
        #ifdef USE_WINDOWS_API
781
            DWORD timeout = dtls_timeout * 1000;
782
            #ifdef WOLFSSL_DTLS13
783
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
784
                IsAtLeastTLSv1_3(ssl->version))
785
                timeout /= 4;
786
            #endif /* WOLFSSL_DTLS13 */
787
        #else
788
            struct timeval timeout;
789
            XMEMSET(&timeout, 0, sizeof(timeout));
790
            #ifdef WOLFSSL_DTLS13
791
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
792
                IsAtLeastTLSv1_3(ssl->version)) {
793
                if (dtls_timeout >= 4)
794
                    timeout.tv_sec = dtls_timeout / 4;
795
                else
796
                    timeout.tv_usec = dtls_timeout * 1000000 / 4;
797
            }
798
            else
799
            #endif /* WOLFSSL_DTLS13 */
800
                timeout.tv_sec = dtls_timeout;
801
        #endif /* USE_WINDOWS_API */
802
            if (XSOCKET_SETSOCKOPT(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
803
                    sizeof(timeout)) != 0) {
804
                WOLFSSL_MSG("setsockopt rcvtimeo failed");
805
            }
806
        }
807
#ifndef NO_ASN_TIME
808
        else if (IsSCR(ssl)) {
809
            if (ssl->dtls_start_timeout &&
810
                LowResTimer() - ssl->dtls_start_timeout >
811
                    (word32)dtls_timeout) {
812
                ssl->dtls_start_timeout = 0;
813
                return WOLFSSL_CBIO_ERR_TIMEOUT;
814
            }
815
            else if (!ssl->dtls_start_timeout) {
816
                ssl->dtls_start_timeout = LowResTimer();
817
            }
818
        }
819
#endif /* !NO_ASN_TIME */
820
821
        {
822
            XSOCKLENT inPeerSz = peerSz;
823
            if (dtlsCtx->recvfrom == NULL) {
824
                recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz,
825
                        ssl->rflags, (SOCKADDR*)peer,
826
                        peer != NULL ? &inPeerSz : NULL);
827
            }
828
            else {
829
                recvd = (int)dtlsCtx->recvfrom(sd, buf, (size_t) sz,
830
                        ssl->rflags, (SOCKADDR*) peer,
831
                        peer != NULL ? &inPeerSz : NULL);
832
            }
833
            /* Truncate peerSz. From the RECV(2) man page
834
             * The returned address is truncated if the buffer provided is too
835
             * small; in this case, addrlen will return a value greater than was
836
             * supplied to the call.
837
             */
838
            peerSz = MIN(peerSz, inPeerSz);
839
        }
840
841
        recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
842
843
        if (recvd < 0) {
844
            WOLFSSL_MSG("Embed Receive From error");
845
            if (recvd == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) &&
846
                !wolfSSL_dtls_get_using_nonblock(ssl)) {
847
                recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
848
            }
849
            return recvd;
850
        }
851
        else if (recvd == 0) {
852
            if (!dtlsCtx->rfdIsDGram) {
853
                /* Closed TCP connection */
854
                recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
855
            }
856
            else {
857
                WOLFSSL_MSG("Ignoring 0-length datagram");
858
                continue;
859
            }
860
            return recvd;
861
        }
862
        else if (dtlsCtx->connected) {
863
            /* Nothing to do */
864
        }
865
        else if (dtlsCtx->userSet) {
866
            /* Check we received the packet from the correct peer */
867
            int ignore = 0;
868
#ifdef WOLFSSL_RW_THREADED
869
            if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
870
                return WOLFSSL_CBIO_ERR_GENERAL;
871
#endif
872
            if (dtlsCtx->peer.sz > 0 &&
873
                (peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
874
                    !sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
875
                        dtlsCtx->peer.sz))) {
876
                WOLFSSL_MSG("    Ignored packet from invalid peer");
877
                ignore = 1;
878
            }
879
#ifdef WOLFSSL_RW_THREADED
880
            if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
881
                return WOLFSSL_CBIO_ERR_GENERAL;
882
#endif
883
            if (ignore) {
884
#if defined(NO_ASN_TIME) &&                                                    \
885
    !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
886
                if (doDtlsTimeout) {
887
                    invalidPeerPackets++;
888
                    if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
889
                        return wolfSSL_dtls_get_using_nonblock(ssl)
890
                                   ? WOLFSSL_CBIO_ERR_WANT_READ
891
                                   : WOLFSSL_CBIO_ERR_TIMEOUT;
892
                }
893
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
894
                continue;
895
            }
896
        }
897
        else {
898
            if (newPeer) {
899
                /* Store size of saved address. Locking handled internally. */
900
                if (wolfSSL_dtls_set_peer(ssl, peer, peerSz) != WOLFSSL_SUCCESS)
901
                    return WOLFSSL_CBIO_ERR_GENERAL;
902
                dtlsCtx->userSet = 0;
903
            }
904
#ifndef WOLFSSL_PEER_ADDRESS_CHANGES
905
            else {
906
                ret = 0;
907
    #ifdef WOLFSSL_RW_THREADED
908
                if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
909
                    return WOLFSSL_CBIO_ERR_GENERAL;
910
    #endif /* WOLFSSL_RW_THREADED */
911
                if (!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
912
                                    dtlsCtx->peer.sz)) {
913
                    ret = WOLFSSL_CBIO_ERR_GENERAL;
914
                }
915
    #ifdef WOLFSSL_RW_THREADED
916
                if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
917
                    return WOLFSSL_CBIO_ERR_GENERAL;
918
    #endif /* WOLFSSL_RW_THREADED */
919
                if (ret != 0)
920
                    return ret;
921
            }
922
#endif /* !WOLFSSL_PEER_ADDRESS_CHANGES */
923
        }
924
#ifndef NO_ASN_TIME
925
        ssl->dtls_start_timeout = 0;
926
#endif /* !NO_ASN_TIME */
927
        break;
928
    } while (1);
929
930
    return recvd;
931
}
932
933
934
/* The send embedded callback
935
 *  return : nb bytes sent, or error
936
 */
937
int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
938
{
939
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
940
    int sd = dtlsCtx->wfd;
941
    int sent;
942
    const SOCKADDR_S* peer = NULL;
943
    XSOCKLENT peerSz = 0;
944
945
    WOLFSSL_ENTER("EmbedSendTo");
946
947
    if (sz < 0)
948
        return WOLFSSL_CBIO_ERR_GENERAL;
949
950
    if (!dtlsCtx->wfdIsDGram) {
951
        /* Probably a TCP socket. peer and peerSz MUST be NULL and 0 */
952
    }
953
    else if (!dtlsCtx->connected) {
954
        peer   = (const SOCKADDR_S*)dtlsCtx->peer.sa;
955
        peerSz = dtlsCtx->peer.sz;
956
#ifndef WOLFSSL_IPV6
957
        if (PeerIsIpv6(peer, peerSz)) {
958
            WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
959
            return NOT_COMPILED_IN;
960
        }
961
#endif
962
    }
963
964
    if (dtlsCtx->sendto == NULL) {
965
        sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags,
966
                (const SOCKADDR*)peer, peerSz);
967
    }
968
    else {
969
        sent = (int)dtlsCtx->sendto(sd, buf, (size_t)sz, ssl->wflags,
970
                (const SOCKADDR*)peer, peerSz);
971
    }
972
973
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
974
975
    if (sent < 0) {
976
        WOLFSSL_MSG("Embed Send To error");
977
    }
978
979
    return sent;
980
}
981
982
983
#ifdef WOLFSSL_MULTICAST
984
985
/* The alternate receive embedded callback for Multicast
986
 *  return : nb bytes read, or error
987
 */
988
int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
989
{
990
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
991
    int recvd;
992
    int sd = dtlsCtx->rfd;
993
994
    WOLFSSL_ENTER("EmbedReceiveFromMcast");
995
996
    if (sz < 0)
997
        return WOLFSSL_CBIO_ERR_GENERAL;
998
999
    recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, NULL, NULL);
1000
1001
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1002
1003
    if (recvd < 0) {
1004
        WOLFSSL_MSG("Embed Receive From error");
1005
        if (recvd == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) &&
1006
            !wolfSSL_dtls_get_using_nonblock(ssl)) {
1007
            recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
1008
        }
1009
    }
1010
1011
    return recvd;
1012
}
1013
#endif /* WOLFSSL_MULTICAST */
1014
1015
1016
/* The DTLS Generate Cookie callback
1017
 *  return : number of bytes copied into buf, or error
1018
 */
1019
int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
1020
{
1021
    int sd = ssl->wfd;
1022
    SOCKADDR_S peer;
1023
    XSOCKLENT peerSz = sizeof(peer);
1024
    byte digest[WC_SHA256_DIGEST_SIZE];
1025
    int  ret = 0;
1026
1027
    (void)ctx;
1028
1029
    if (sz < 0)
1030
        return BAD_FUNC_ARG;
1031
1032
    XMEMSET(&peer, 0, sizeof(peer));
1033
    if (XSOCKET_GETPEERNAME(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
1034
        WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
1035
        return GEN_COOKIE_E;
1036
    }
1037
1038
    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
1039
    if (ret != 0)
1040
        return ret;
1041
1042
    if (sz > WC_SHA256_DIGEST_SIZE)
1043
        sz = WC_SHA256_DIGEST_SIZE;
1044
    XMEMCPY(buf, digest, (size_t)sz);
1045
1046
    return sz;
1047
}
1048
#endif /* WOLFSSL_DTLS */
1049
1050
#ifdef WOLFSSL_SESSION_EXPORT
1051
1052
#ifdef WOLFSSL_DTLS
1053
    static int EmbedGetPeerDTLS(WOLFSSL* ssl, char* ip, int* ipSz,
1054
                                                 unsigned short* port, int* fam)
1055
    {
1056
        SOCKADDR_S peer;
1057
        word32     peerSz;
1058
        int        ret;
1059
1060
        /* get peer information stored in ssl struct */
1061
        peerSz = sizeof(SOCKADDR_S);
1062
        if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
1063
                                                               != WOLFSSL_SUCCESS) {
1064
            return ret;
1065
        }
1066
1067
        /* extract family, ip, and port */
1068
        *fam = ((SOCKADDR_S*)&peer)->ss_family;
1069
        switch (*fam) {
1070
            case WOLFSSL_IP4:
1071
                if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
1072
                                                           ip, *ipSz) == NULL) {
1073
                    WOLFSSL_MSG("XINET_NTOP error");
1074
                    return SOCKET_ERROR_E;
1075
                }
1076
                *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
1077
                break;
1078
1079
            case WOLFSSL_IP6:
1080
            #ifdef WOLFSSL_IPV6
1081
                if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
1082
                                                           ip, *ipSz) == NULL) {
1083
                    WOLFSSL_MSG("XINET_NTOP error");
1084
                    return SOCKET_ERROR_E;
1085
                }
1086
                *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
1087
            #endif /* WOLFSSL_IPV6 */
1088
                break;
1089
1090
            default:
1091
                WOLFSSL_MSG("Unknown family type");
1092
                return SOCKET_ERROR_E;
1093
        }
1094
        ip[*ipSz - 1] = '\0'; /* make sure has terminator */
1095
        *ipSz = (word16)XSTRLEN(ip);
1096
1097
        return WOLFSSL_SUCCESS;
1098
    }
1099
1100
    static int EmbedSetPeerDTLS(WOLFSSL* ssl, char* ip, int ipSz,
1101
                                                   unsigned short port, int fam)
1102
    {
1103
        int    ret;
1104
        SOCKADDR_S addr;
1105
1106
        /* sanity checks on arguments */
1107
        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
1108
            return BAD_FUNC_ARG;
1109
        }
1110
1111
        addr.ss_family = fam;
1112
        switch (addr.ss_family) {
1113
            case WOLFSSL_IP4:
1114
                if (XINET_PTON(addr.ss_family, ip,
1115
                                     &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
1116
                    WOLFSSL_MSG("XINET_PTON error");
1117
                    return SOCKET_ERROR_E;
1118
                }
1119
                ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
1120
1121
                /* peer sa is free'd in wolfSSL_ResourceFree */
1122
                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
1123
                                          sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
1124
                    WOLFSSL_MSG("Import DTLS peer info error");
1125
                    return ret;
1126
                }
1127
                break;
1128
1129
            case WOLFSSL_IP6:
1130
            #ifdef WOLFSSL_IPV6
1131
                if (XINET_PTON(addr.ss_family, ip,
1132
                                   &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
1133
                    WOLFSSL_MSG("XINET_PTON error");
1134
                    return SOCKET_ERROR_E;
1135
                }
1136
                ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
1137
1138
                /* peer sa is free'd in wolfSSL_ResourceFree */
1139
                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
1140
                                         sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
1141
                    WOLFSSL_MSG("Import DTLS peer info error");
1142
                    return ret;
1143
                }
1144
            #endif /* WOLFSSL_IPV6 */
1145
                break;
1146
1147
            default:
1148
                WOLFSSL_MSG("Unknown address family");
1149
                return BUFFER_E;
1150
        }
1151
1152
        return WOLFSSL_SUCCESS;
1153
    }
1154
#endif /* WOLFSSL_DTLS */
1155
1156
    /* get the peer information in human readable form (ip, port, family)
1157
     * default function assumes BSD sockets
1158
     * can be overridden with wolfSSL_CTX_SetIOGetPeer
1159
     */
1160
    int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
1161
                                                 unsigned short* port, int* fam)
1162
    {
1163
        if (ssl == NULL || ip == NULL || ipSz == NULL ||
1164
                                                  port == NULL || fam == NULL) {
1165
            return BAD_FUNC_ARG;
1166
        }
1167
1168
        if (ssl->options.dtls) {
1169
        #ifdef WOLFSSL_DTLS
1170
            return EmbedGetPeerDTLS(ssl, ip, ipSz, port, fam);
1171
        #else
1172
            return NOT_COMPILED_IN;
1173
        #endif
1174
        }
1175
        else {
1176
            *port = wolfSSL_get_fd(ssl);
1177
            ip[0] = '\0';
1178
            *ipSz = 0;
1179
            *fam  = 0;
1180
            return WOLFSSL_SUCCESS;
1181
        }
1182
    }
1183
1184
    /* set the peer information in human readable form (ip, port, family)
1185
     * default function assumes BSD sockets
1186
     * can be overridden with wolfSSL_CTX_SetIOSetPeer
1187
     */
1188
    int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
1189
                                                   unsigned short port, int fam)
1190
    {
1191
        /* sanity checks on arguments */
1192
        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
1193
            return BAD_FUNC_ARG;
1194
        }
1195
1196
        if (ssl->options.dtls) {
1197
        #ifdef WOLFSSL_DTLS
1198
            return EmbedSetPeerDTLS(ssl, ip, ipSz, port, fam);
1199
        #else
1200
            return NOT_COMPILED_IN;
1201
        #endif
1202
        }
1203
        else {
1204
            wolfSSL_set_fd(ssl, port);
1205
            (void)fam;
1206
            return WOLFSSL_SUCCESS;
1207
        }
1208
    }
1209
#endif /* WOLFSSL_SESSION_EXPORT */
1210
1211
#ifdef WOLFSSL_LINUXKM
1212
static int linuxkm_send(struct socket *socket, void *buf, int size,
1213
    unsigned int flags)
1214
{
1215
    size_t len;
1216
    int ret;
1217
    struct kvec vec;
1218
    struct msghdr msg = { .msg_flags = flags };
1219
1220
    if (size < 0)
1221
        return -EINVAL;
1222
    if (size == 0)
1223
        return 0;
1224
1225
    len = (size_t)size;
1226
    vec.iov_base = buf;
1227
    vec.iov_len  = len;
1228
1229
    ret = kernel_sendmsg(socket, &msg, &vec, 1, len);
1230
    return ret;
1231
}
1232
1233
static int linuxkm_recv(struct socket *socket, void *buf, int size,
1234
    unsigned int flags)
1235
{
1236
    size_t len;
1237
    int ret;
1238
    struct kvec vec;
1239
    struct msghdr msg = { .msg_flags = flags };
1240
1241
    if (size < 0)
1242
        return -EINVAL;
1243
    if (size == 0)
1244
        return 0;
1245
1246
    len = (size_t)size;
1247
    vec.iov_base = buf;
1248
    vec.iov_len  = len;
1249
1250
    ret = kernel_recvmsg(socket, &msg, &vec, 1, len, msg.msg_flags);
1251
    return ret;
1252
}
1253
#endif /* WOLFSSL_LINUXKM */
1254
1255
1256
int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
1257
0
{
1258
0
    int recvd;
1259
1260
0
    if (sz < 0)
1261
0
        return WOLFSSL_CBIO_ERR_GENERAL;
1262
1263
0
    recvd = (int)RECV_FUNCTION(sd, buf, (size_t)sz, rdFlags);
1264
0
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1265
1266
0
    return recvd;
1267
0
}
1268
1269
int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
1270
0
{
1271
0
    int sent;
1272
1273
0
    if (sz < 0)
1274
0
        return WOLFSSL_CBIO_ERR_GENERAL;
1275
1276
0
    sent = (int)SEND_FUNCTION(sd, buf, (size_t)sz, wrFlags);
1277
0
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
1278
1279
0
    return sent;
1280
0
}
1281
1282
#if defined(WOLFSSL_HAVE_BIO_ADDR) && defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA)
1283
1284
int wolfIO_RecvFrom(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int rdFlags)
1285
{
1286
    int recvd;
1287
    socklen_t addr_len = (socklen_t)sizeof(*addr);
1288
1289
    if (sz < 0)
1290
        return WOLFSSL_CBIO_ERR_GENERAL;
1291
1292
    recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, rdFlags,
1293
                                            addr ? &addr->sa : NULL,
1294
                                            addr ? &addr_len : 0);
1295
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1296
1297
    return recvd;
1298
}
1299
1300
int wolfIO_SendTo(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int wrFlags)
1301
{
1302
    int sent;
1303
    socklen_t addr_len = addr ? wolfSSL_BIO_ADDR_size(addr) : 0;
1304
1305
    if (sz < 0)
1306
        return WOLFSSL_CBIO_ERR_GENERAL;
1307
1308
    sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, wrFlags,
1309
                                         addr ? &addr->sa : NULL,
1310
                                         addr_len);
1311
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
1312
1313
    return sent;
1314
}
1315
1316
#endif /* WOLFSSL_HAVE_BIO_ADDR && WOLFSSL_DTLS && OPENSSL_EXTRA */
1317
1318
#endif /* USE_WOLFSSL_IO */
1319
1320
1321
#ifdef HAVE_HTTP_CLIENT
1322
1323
#ifndef HAVE_IO_TIMEOUT
1324
    #define io_timeout_sec 0
1325
#else
1326
1327
    #ifndef DEFAULT_TIMEOUT_SEC
1328
        #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
1329
    #endif
1330
1331
    static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
1332
1333
    void wolfIO_SetTimeout(int to_sec)
1334
    {
1335
        io_timeout_sec = to_sec;
1336
    }
1337
1338
    int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
1339
    {
1340
        int ret = 0;
1341
1342
    #ifdef USE_WINDOWS_API
1343
        unsigned long blocking = non_blocking;
1344
        ret = ioctlsocket(sockfd, FIONBIO, &blocking);
1345
        if (ret == SOCKET_ERROR)
1346
            ret = WOLFSSL_FATAL_ERROR;
1347
    #elif defined(__WATCOMC__) && defined(__OS2__)
1348
        if (ioctl(sockfd, FIONBIO, &non_blocking) == -1)
1349
            ret = WOLFSSL_FATAL_ERROR;
1350
    #else
1351
        ret = fcntl(sockfd, F_GETFL, 0);
1352
        if (ret >= 0) {
1353
            if (non_blocking)
1354
                ret |= O_NONBLOCK;
1355
            else
1356
                ret &= ~O_NONBLOCK;
1357
            ret = fcntl(sockfd, F_SETFL, ret);
1358
        }
1359
    #endif
1360
        if (ret < 0) {
1361
            WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
1362
        }
1363
1364
        return ret;
1365
    }
1366
1367
    int wolfIO_Select(SOCKET_T sockfd, int to_sec)
1368
    {
1369
        fd_set rfds, wfds;
1370
        int nfds = 0;
1371
        struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
1372
        int ret;
1373
1374
    #ifndef USE_WINDOWS_API
1375
        nfds = (int)sockfd + 1;
1376
1377
        if ((sockfd < 0) || (sockfd >= FD_SETSIZE)) {
1378
            WOLFSSL_MSG("socket fd out of FDSET range");
1379
            return WOLFSSL_FATAL_ERROR;
1380
        }
1381
    #endif
1382
1383
        FD_ZERO(&rfds);
1384
        FD_SET(sockfd, &rfds);
1385
        wfds = rfds;
1386
1387
        ret = select(nfds, &rfds, &wfds, NULL, &timeout);
1388
        if (ret == 0) {
1389
    #ifdef DEBUG_HTTP
1390
            fprintf(stderr, "Timeout: %d\n", ret);
1391
    #endif
1392
            return HTTP_TIMEOUT;
1393
        }
1394
        else if (ret > 0) {
1395
            if (FD_ISSET(sockfd, &wfds)) {
1396
                if (!FD_ISSET(sockfd, &rfds)) {
1397
                    return 0;
1398
                }
1399
            }
1400
        }
1401
1402
        WOLFSSL_MSG("Select error");
1403
        return SOCKET_ERROR_E;
1404
    }
1405
#endif /* HAVE_IO_TIMEOUT */
1406
1407
static word32 wolfIO_Word16ToString(char* d, word16 number)
1408
{
1409
    word32 i = 0;
1410
    word16 order = 10000;
1411
    word16 digit;
1412
1413
    if (d == NULL)
1414
        return i;
1415
1416
    if (number == 0)
1417
        d[i++] = '0';
1418
    else {
1419
        while (order) {
1420
            digit = number / order;
1421
            if (i > 0 || digit != 0)
1422
                d[i++] = (char)digit + '0';
1423
            if (digit != 0)
1424
                number = (word16) (number % (digit * order));
1425
1426
            order = (order > 1) ? order / 10 : 0;
1427
        }
1428
    }
1429
    d[i] = 0; /* null terminate */
1430
1431
    return i;
1432
}
1433
1434
int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
1435
{
1436
#ifdef HAVE_SOCKADDR
1437
    int ret = 0;
1438
    SOCKADDR_S addr;
1439
    socklen_t sockaddr_len;
1440
#if defined(HAVE_GETADDRINFO)
1441
    /* use getaddrinfo */
1442
    ADDRINFO hints;
1443
    ADDRINFO* answer = NULL;
1444
    char strPort[6];
1445
#else
1446
    /* use gethostbyname */
1447
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1448
    !defined(SINGLE_THREADED)
1449
    HOSTENT entry_buf, *entry = NULL;
1450
    char *ghbn_r_buf = NULL;
1451
    int ghbn_r_errno;
1452
#else
1453
    HOSTENT *entry;
1454
#endif
1455
#ifdef WOLFSSL_IPV6
1456
    SOCKADDR_IN6 *sin;
1457
#else
1458
    SOCKADDR_IN *sin;
1459
#endif /* WOLFSSL_IPV6 */
1460
#endif /* HAVE_GETADDRINFO */
1461
1462
    if (sockfd == NULL || ip == NULL) {
1463
        return WOLFSSL_FATAL_ERROR;
1464
    }
1465
1466
#if !defined(HAVE_GETADDRINFO)
1467
#ifdef WOLFSSL_IPV6
1468
    sockaddr_len = sizeof(SOCKADDR_IN6);
1469
#else
1470
    sockaddr_len = sizeof(SOCKADDR_IN);
1471
#endif /* WOLFSSL_IPV6 */
1472
#endif /* !HAVE_GETADDRINFO */
1473
    XMEMSET(&addr, 0, sizeof(addr));
1474
1475
#ifdef WOLFIO_DEBUG
1476
    printf("TCP Connect: %s:%d\n", ip, port);
1477
#endif
1478
1479
    /* use gethostbyname for c99 */
1480
#if defined(HAVE_GETADDRINFO)
1481
    XMEMSET(&hints, 0, sizeof(hints));
1482
#ifdef WOLFSSL_IPV6
1483
    hints.ai_family = AF_UNSPEC; /* detect IPv4 or IPv6 */
1484
#else
1485
    hints.ai_family = AF_INET;   /* detect only IPv4 */
1486
#endif
1487
    hints.ai_socktype = SOCK_STREAM;
1488
    hints.ai_protocol = IPPROTO_TCP;
1489
1490
    if (wolfIO_Word16ToString(strPort, port) == 0) {
1491
        WOLFSSL_MSG("invalid port number for responder");
1492
        return WOLFSSL_FATAL_ERROR;
1493
    }
1494
1495
    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
1496
        WOLFSSL_MSG("no addr info for responder");
1497
        return WOLFSSL_FATAL_ERROR;
1498
    }
1499
1500
    sockaddr_len = answer->ai_addrlen;
1501
    XMEMCPY(&addr, answer->ai_addr, (size_t)sockaddr_len);
1502
    freeaddrinfo(answer);
1503
#else
1504
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1505
    !defined(SINGLE_THREADED)
1506
    /* 2048 is a magic number that empirically works.  the header and
1507
     * documentation provide no guidance on appropriate buffer size other than
1508
     * "if buf is too small, the functions will return ERANGE, and the call
1509
     * should be retried with a larger buffer."
1510
     */
1511
    ghbn_r_buf = (char *)XMALLOC(2048, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1512
    if (ghbn_r_buf != NULL) {
1513
        gethostbyname_r(ip, &entry_buf, ghbn_r_buf, 2048, &entry, &ghbn_r_errno);
1514
    }
1515
#else
1516
    entry = gethostbyname(ip);
1517
#endif
1518
1519
    if (entry) {
1520
    #ifdef WOLFSSL_IPV6
1521
        sin = (SOCKADDR_IN6 *)&addr;
1522
        sin->sin6_family = AF_INET6;
1523
        sin->sin6_port = XHTONS(port);
1524
        XMEMCPY(&sin->sin6_addr, entry->h_addr_list[0], entry->h_length);
1525
    #else
1526
        sin = (SOCKADDR_IN *)&addr;
1527
        sin->sin_family = AF_INET;
1528
        sin->sin_port = XHTONS(port);
1529
        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
1530
                (size_t)entry->h_length);
1531
    #endif
1532
    }
1533
1534
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1535
    !defined(SINGLE_THREADED)
1536
    XFREE(ghbn_r_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1537
#endif
1538
1539
    if (entry == NULL) {
1540
        WOLFSSL_MSG("no addr info for responder");
1541
        return WOLFSSL_FATAL_ERROR;
1542
    }
1543
#endif
1544
1545
    *sockfd = (SOCKET_T)wc_socket_cloexec(addr.ss_family, SOCK_STREAM, 0);
1546
#ifdef USE_WINDOWS_API
1547
    if (*sockfd == SOCKET_INVALID)
1548
#else
1549
    if (*sockfd <= SOCKET_INVALID)
1550
#endif
1551
    {
1552
        WOLFSSL_MSG("bad socket fd, out of fds?");
1553
        *sockfd = SOCKET_INVALID;
1554
        return WOLFSSL_FATAL_ERROR;
1555
    }
1556
1557
#ifdef HAVE_IO_TIMEOUT
1558
    /* if timeout value provided then set socket non-blocking */
1559
    if (to_sec > 0) {
1560
        wolfIO_SetBlockingMode(*sockfd, 1);
1561
    }
1562
#else
1563
    (void)to_sec;
1564
#endif /* HAVE_IO_TIMEOUT */
1565
1566
    ret = XSOCKET_CONNECT(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
1567
#ifdef HAVE_IO_TIMEOUT
1568
    if ((ret != 0) && (to_sec > 0)) {
1569
#ifdef USE_WINDOWS_API
1570
        if ((ret == SOCKET_ERROR) &&
1571
            (wolfSSL_LastError(ret, *sockfd) == SOCKET_EWOULDBLOCK))
1572
#else
1573
        if (errno == EINPROGRESS)
1574
#endif
1575
        {
1576
            /* wait for connect to complete */
1577
            ret = wolfIO_Select(*sockfd, to_sec);
1578
1579
            /* restore blocking mode */
1580
            wolfIO_SetBlockingMode(*sockfd, 0);
1581
        }
1582
    }
1583
#endif /* HAVE_IO_TIMEOUT */
1584
    if (ret != 0) {
1585
        WOLFSSL_MSG("Responder tcp connect failed");
1586
        CloseSocket(*sockfd);
1587
        *sockfd = SOCKET_INVALID;
1588
        return WOLFSSL_FATAL_ERROR;
1589
    }
1590
    return ret;
1591
#else
1592
    (void)sockfd;
1593
    (void)ip;
1594
    (void)port;
1595
    (void)to_sec;
1596
    return WOLFSSL_FATAL_ERROR;
1597
#endif /* HAVE_SOCKADDR */
1598
}
1599
1600
int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
1601
{
1602
#ifdef HAVE_SOCKADDR
1603
    int ret = 0;
1604
    SOCKADDR_S addr;
1605
#ifdef WOLFSSL_IPV6
1606
    socklen_t sockaddr_len = sizeof(SOCKADDR_IN6);
1607
    SOCKADDR_IN6 *sin = (SOCKADDR_IN6 *)&addr;
1608
#else
1609
    socklen_t sockaddr_len = sizeof(SOCKADDR_IN);
1610
    SOCKADDR_IN *sin = (SOCKADDR_IN *)&addr;
1611
#endif
1612
1613
    if (sockfd == NULL || port < 1) {
1614
        return WOLFSSL_FATAL_ERROR;
1615
    }
1616
1617
    XMEMSET(&addr, 0, sizeof(addr));
1618
1619
#ifdef WOLFSSL_IPV6
1620
    sin->sin6_family = AF_INET6;
1621
    sin->sin6_addr = in6addr_any;
1622
    sin->sin6_port = XHTONS(port);
1623
    *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET6, SOCK_STREAM, 0);
1624
#else
1625
    sin->sin_family = AF_INET;
1626
    sin->sin_addr.s_addr = INADDR_ANY;
1627
    sin->sin_port = XHTONS(port);
1628
    *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET, SOCK_STREAM, 0);
1629
#endif
1630
1631
#ifdef USE_WINDOWS_API
1632
    if (*sockfd == SOCKET_INVALID)
1633
#else
1634
    if (*sockfd <= SOCKET_INVALID)
1635
#endif
1636
    {
1637
        WOLFSSL_MSG("socket failed");
1638
        *sockfd = SOCKET_INVALID;
1639
        return WOLFSSL_FATAL_ERROR;
1640
    }
1641
1642
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
1643
                   && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
1644
    {
1645
        int optval  = 1;
1646
        XSOCKLENT optlen = sizeof(optval);
1647
        ret = XSOCKET_SETSOCKOPT(*sockfd, SOL_SOCKET, SO_REUSEADDR, &optval,
1648
                                 optlen);
1649
    }
1650
#endif
1651
1652
    if (ret == 0)
1653
        ret = XSOCKET_BIND(*sockfd, (SOCKADDR *)sin, sockaddr_len);
1654
    if (ret == 0)
1655
        ret = XSOCKET_LISTEN(*sockfd, SOMAXCONN);
1656
1657
    if (ret != 0) {
1658
        WOLFSSL_MSG("wolfIO_TcpBind failed");
1659
        CloseSocket(*sockfd);
1660
        *sockfd = SOCKET_INVALID;
1661
        ret = WOLFSSL_FATAL_ERROR;
1662
    }
1663
1664
    return ret;
1665
#else
1666
    (void)sockfd;
1667
    (void)port;
1668
    return WOLFSSL_FATAL_ERROR;
1669
#endif /* HAVE_SOCKADDR */
1670
}
1671
1672
#ifdef HAVE_SOCKADDR
1673
int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
1674
{
1675
    return (int)wc_accept_cloexec((int)sockfd, peer_addr, peer_len);
1676
}
1677
#endif /* HAVE_SOCKADDR */
1678
1679
#ifndef HTTP_SCRATCH_BUFFER_SIZE
1680
    #define HTTP_SCRATCH_BUFFER_SIZE 512
1681
#endif
1682
#ifndef MAX_URL_ITEM_SIZE
1683
    #define MAX_URL_ITEM_SIZE   80
1684
#endif
1685
1686
int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
1687
    word16* outPort)
1688
{
1689
    int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
1690
1691
    if (url == NULL || urlSz == 0) {
1692
        if (outName)
1693
            *outName = 0;
1694
        if (outPath)
1695
            *outPath = 0;
1696
        if (outPort)
1697
            *outPort = 0;
1698
    }
1699
    else {
1700
        int i, cur;
1701
1702
        /* need to break the url down into scheme, address, and port */
1703
        /*     "http://example.com:8080/" */
1704
        /*     "http://[::1]:443/"        */
1705
        if (XSTRNCMP(url, "http://", 7) == 0) {
1706
            cur = 7;
1707
        } else cur = 0;
1708
1709
        i = 0;
1710
        if (url[cur] == '[') {
1711
            cur++;
1712
            /* copy until ']' */
1713
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1714
                    url[cur] != ']') {
1715
                if (url[cur] == '\r' || url[cur] == '\n')
1716
                    return WOLFSSL_FATAL_ERROR;
1717
                if (outName)
1718
                    outName[i] = url[cur];
1719
                i++; cur++;
1720
            }
1721
            /* A bracketed IPv6 literal must be terminated by ']'. The loop
1722
             * above can also stop on end-of-buffer, NUL, or the length cap,
1723
             * none of which represent a well-formed host. Reject those cases
1724
             * rather than accepting the unterminated tail as the hostname. */
1725
            if (cur >= urlSz || url[cur] != ']')
1726
                return WOLFSSL_FATAL_ERROR;
1727
            cur++; /* skip ']' */
1728
        }
1729
        else {
1730
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1731
                    url[cur] != ':' && url[cur] != '/') {
1732
                if (url[cur] == '\r' || url[cur] == '\n')
1733
                    return WOLFSSL_FATAL_ERROR;
1734
                if (outName)
1735
                    outName[i] = url[cur];
1736
                i++; cur++;
1737
            }
1738
        }
1739
        if (outName)
1740
            outName[i] = 0;
1741
        /* Need to pick out the path after the domain name */
1742
1743
        if (cur < urlSz && url[cur] == ':') {
1744
            char port[5];
1745
            int j;
1746
            word32 bigPort = 0;
1747
            i = 0;
1748
            cur++;
1749
1750
            XMEMSET(port, 0, sizeof(port));
1751
1752
            while (i < 5 && cur < urlSz && url[cur] != 0 && url[cur] != '/') {
1753
                port[i] = url[cur];
1754
                i++; cur++;
1755
            }
1756
1757
            /* A valid port is at most 5 digits; if more characters remain
1758
             * before the path/terminator the port field is malformed (e.g.
1759
             * a 6-digit port) and must be rejected rather than parsed from a
1760
             * truncated digit string. */
1761
            if (cur < urlSz && url[cur] != 0 && url[cur] != '/')
1762
                return WOLFSSL_FATAL_ERROR;
1763
1764
            for (j = 0; j < i; j++) {
1765
                if (port[j] < '0' || port[j] > '9') return WOLFSSL_FATAL_ERROR;
1766
                bigPort = (bigPort * 10) + (word32)(port[j] - '0');
1767
            }
1768
            /* Reject out-of-range ports rather than silently truncating to
1769
             * word16, which would otherwise wrap (e.g. 65536 -> 0) and
1770
             * connect to an unintended port. */
1771
            if (bigPort > WOLFSSL_MAX_16BIT)
1772
                return WOLFSSL_FATAL_ERROR;
1773
            if (outPort)
1774
                *outPort = (word16)bigPort;
1775
        }
1776
        else if (outPort)
1777
            *outPort = 80;
1778
1779
1780
        if (cur < urlSz && url[cur] == '/') {
1781
            i = 0;
1782
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) {
1783
                if (url[cur] == '\r' || url[cur] == '\n')
1784
                    return WOLFSSL_FATAL_ERROR;
1785
                if (outPath)
1786
                    outPath[i] = url[cur];
1787
                i++; cur++;
1788
            }
1789
            if (outPath)
1790
                outPath[i] = 0;
1791
        }
1792
        else if (outPath) {
1793
            outPath[0] = '/';
1794
            outPath[1] = 0;
1795
        }
1796
1797
        result = 0;
1798
    }
1799
1800
    return result;
1801
}
1802
1803
#ifndef WOLFIO_HTTP_MAX_BODY
1804
/* Upper bound on an HTTP body that will be buffered in memory. */
1805
#define WOLFIO_HTTP_MAX_BODY (32 * 1024 * 1024)
1806
#endif
1807
1808
static int wolfIO_HttpProcessResponseBuf(WolfSSLGenericIORecvCb ioCb,
1809
    void* ioCbCtx, byte **recvBuf, int* recvBufSz, int chunkSz, char* start,
1810
    int len, int dynType, void* heap)
1811
{
1812
    byte* newRecvBuf = NULL;
1813
    int newRecvSz;
1814
    int pos = 0;
1815
1816
    WOLFSSL_MSG("Processing HTTP response");
1817
#ifdef WOLFIO_DEBUG
1818
    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
1819
#endif
1820
1821
    (void)heap;
1822
    (void)dynType;
1823
1824
    if (chunkSz < 0 || len < 0) {
1825
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size");
1826
        return MEMORY_E;
1827
    }
1828
1829
    if (chunkSz > WOLFIO_HTTP_MAX_BODY) {
1830
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf chunk too large");
1831
        return BUFFER_ERROR;
1832
    }
1833
1834
    if (*recvBufSz < 0 || *recvBufSz > WOLFIO_HTTP_MAX_BODY - chunkSz) {
1835
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf aggregate body too large");
1836
        return BUFFER_ERROR;
1837
    }
1838
1839
    if (len > chunkSz) {
1840
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf len exceeds chunk size");
1841
        return WOLFSSL_FATAL_ERROR;
1842
    }
1843
1844
    newRecvSz = *recvBufSz + chunkSz;
1845
1846
    if (newRecvSz <= 0) {
1847
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow");
1848
        return MEMORY_E;
1849
    }
1850
1851
    newRecvBuf = (byte*)XMALLOC((size_t)newRecvSz, heap, dynType);
1852
    if (newRecvBuf == NULL) {
1853
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
1854
        return MEMORY_E;
1855
    }
1856
1857
    /* if buffer already exists, then we are growing it */
1858
    if (*recvBuf) {
1859
        XMEMCPY(&newRecvBuf[pos], *recvBuf, (size_t) *recvBufSz);
1860
        XFREE(*recvBuf, heap, dynType);
1861
        pos += *recvBufSz;
1862
        *recvBuf = NULL;
1863
    }
1864
1865
    /* copy the remainder of the httpBuf into the respBuf */
1866
    if (len != 0) {
1867
        if (pos + len <= newRecvSz) {
1868
            XMEMCPY(&newRecvBuf[pos], start, (size_t)len);
1869
            pos += len;
1870
        }
1871
        else {
1872
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size");
1873
            XFREE(newRecvBuf, heap, dynType);
1874
            return WOLFSSL_FATAL_ERROR;
1875
        }
1876
    }
1877
1878
    /* receive the remainder of chunk */
1879
    while (len < chunkSz) {
1880
        int rxSz = ioCb((char*)&newRecvBuf[pos], chunkSz-len, ioCbCtx);
1881
        if (rxSz > 0) {
1882
            len += rxSz;
1883
            pos += rxSz;
1884
        }
1885
        else {
1886
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
1887
            XFREE(newRecvBuf, heap, dynType);
1888
            return WOLFSSL_FATAL_ERROR;
1889
        }
1890
    }
1891
1892
    *recvBuf = newRecvBuf;
1893
    *recvBufSz = newRecvSz;
1894
1895
    return 0;
1896
}
1897
1898
int wolfIO_HttpProcessResponseGenericIO(WolfSSLGenericIORecvCb ioCb,
1899
    void* ioCbCtx, const char** appStrList, unsigned char** respBuf,
1900
    unsigned char* httpBuf, int httpBufSz, int dynType, void* heap)
1901
{
1902
    static const char HTTP_PROTO[] = "HTTP/1.";
1903
    static const char HTTP_STATUS_200[] = "200";
1904
    int result = 0;
1905
    int len = 0;
1906
    char *start, *end;
1907
    int respBufSz = 0;
1908
    int isChunked = 0, chunkSz = 0;
1909
    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
1910
                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
1911
                     phr_http_end
1912
    } state = phr_init;
1913
1914
    WOLFSSL_ENTER("wolfIO_HttpProcessResponse");
1915
1916
    *respBuf = NULL;
1917
    start = end = NULL;
1918
    do {
1919
        if (state == phr_get_chunk_data) {
1920
            /* get chunk of data */
1921
            result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
1922
                &respBufSz, chunkSz, start, len, dynType, heap);
1923
1924
            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
1925
            end = NULL;
1926
            len = 0;
1927
        }
1928
1929
        /* read data if no \r\n or first time */
1930
        if ((start == NULL) || (end == NULL)) {
1931
            if (httpBufSz < len + 1) {
1932
                return BUFFER_ERROR; /* can't happen, but Coverity thinks it
1933
                                      * can.
1934
                                      */
1935
            }
1936
            result = ioCb((char*)httpBuf+len, httpBufSz-len-1, ioCbCtx);
1937
            if (result > 0) {
1938
                len += result;
1939
                start = (char*)httpBuf;
1940
                start[len] = 0;
1941
            }
1942
            else {
1943
                if (result == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
1944
                    return OCSP_WANT_READ;
1945
                }
1946
1947
                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
1948
                return HTTP_RECV_ERR;
1949
            }
1950
        }
1951
        end = XSTRSTR(start, "\r\n"); /* locate end */
1952
1953
        /* handle incomplete rx */
1954
        if (end == NULL) {
1955
            if (len != 0)
1956
                XMEMMOVE(httpBuf, start, (size_t)len);
1957
            start = end = NULL;
1958
        }
1959
        /* when start is "\r\n" */
1960
        else if (end == start) {
1961
            /* if waiting for end or need chunk len */
1962
            if (state == phr_wait_end || state == phr_get_chunk_len) {
1963
                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
1964
                len -= 2; start += 2; /* skip \r\n */
1965
             }
1966
             else {
1967
                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
1968
                return HTTP_HEADER_ERR;
1969
             }
1970
        }
1971
        else {
1972
            *end = 0; /* null terminate */
1973
            len -= (int)(end - start) + 2;
1974
                /* adjust len to remove the first line including the /r/n */
1975
1976
        #ifdef WOLFIO_DEBUG
1977
            printf("HTTP Resp: %s\n", start);
1978
        #endif
1979
1980
            switch (state) {
1981
                case phr_init:
1982
                    /* length of "HTTP/1.x 200" == 12*/
1983
                    if (XSTRLEN(start) < 12) {
1984
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1985
                            "too short.");
1986
                        return HTTP_HEADER_ERR;
1987
                    }
1988
                    if (XSTRNCASECMP(start, HTTP_PROTO,
1989
                                     sizeof(HTTP_PROTO) - 1) != 0) {
1990
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1991
                            "doesn't start with HTTP/1.");
1992
                        return HTTP_PROTO_ERR;
1993
                    }
1994
                    /* +2 for HTTP minor version and space between version and
1995
                     * status code. */
1996
                    start += sizeof(HTTP_PROTO) - 1 + 2 ;
1997
                    if (XSTRNCASECMP(start, HTTP_STATUS_200,
1998
                                     sizeof(HTTP_STATUS_200) - 1) != 0) {
1999
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
2000
                            "doesn't have status code 200.");
2001
                        return HTTP_STATUS_ERR;
2002
                    }
2003
                    state = phr_http_start;
2004
                    break;
2005
                case phr_http_start:
2006
                case phr_have_length:
2007
                case phr_have_type:
2008
                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
2009
                        int i;
2010
2011
                        start += 13;
2012
                        while (*start == ' ') start++;
2013
2014
                        /* try and match against appStrList */
2015
                        i = 0;
2016
                        while (appStrList[i] != NULL) {
2017
                            if (XSTRNCASECMP(start, appStrList[i],
2018
                                                XSTRLEN(appStrList[i])) == 0) {
2019
                                break;
2020
                            }
2021
                            i++;
2022
                        }
2023
                        if (appStrList[i] == NULL) {
2024
                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
2025
                            return HTTP_APPSTR_ERR;
2026
                        }
2027
                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
2028
                    }
2029
                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
2030
                        start += 15;
2031
                        while (*start == ' ') start++;
2032
                        chunkSz = XATOI(start);
2033
                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
2034
                    }
2035
                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
2036
                        start += 18;
2037
                        while (*start == ' ') start++;
2038
                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
2039
                            isChunked = 1;
2040
                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
2041
                        }
2042
                    }
2043
                    break;
2044
                case phr_get_chunk_len:
2045
                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
2046
                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
2047
                    break;
2048
                case phr_get_chunk_data:
2049
                    /* processing for chunk data done above, since \r\n isn't required */
2050
                case phr_wait_end:
2051
                case phr_http_end:
2052
                    /* do nothing */
2053
                    break;
2054
            } /* switch (state) */
2055
2056
            /* skip to end plus \r\n */
2057
            start = end + 2;
2058
        }
2059
    } while (state != phr_http_end);
2060
2061
    if (!isChunked) {
2062
        result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
2063
                &respBufSz, chunkSz, start, len, dynType, heap);
2064
    }
2065
2066
    if (result >= 0) {
2067
        result = respBufSz;
2068
    }
2069
    else {
2070
        WOLFSSL_ERROR(result);
2071
    }
2072
2073
    return result;
2074
}
2075
2076
static int httpResponseIoCb(char* buf, int sz, void* ctx)
2077
{
2078
    /* Double cast to silence the compiler int/pointer width msg */
2079
    return wolfIO_Recv((SOCKET_T)(uintptr_t)ctx, buf, sz, 0);
2080
}
2081
2082
int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
2083
    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
2084
{
2085
    return wolfIO_HttpProcessResponseGenericIO(httpResponseIoCb,
2086
            /* Double cast to silence the compiler int/pointer width msg */
2087
            (void*)(uintptr_t)sfd, appStrList, respBuf, httpBuf, httpBufSz,
2088
            dynType, heap);
2089
}
2090
2091
int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
2092
                               const char *path, int pathLen, int reqSz, const char *contentType,
2093
                               byte *buf, int bufSize)
2094
{
2095
    return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize);
2096
}
2097
2098
/* Returns 1 if the buffer contains a CR or LF byte, 0 otherwise. Used to
2099
 * reject attacker-controlled URL components that would allow HTTP header
2100
 * injection or request splitting. */
2101
static int wolfIO_UrlHasCrlf(const char* in, int inSz)
2102
{
2103
    int i = 0;
2104
    if (in == NULL)
2105
        return 0;
2106
    for (i = 0; i < inSz; i++) {
2107
        if (in[i] == '\r' || in[i] == '\n')
2108
            return 1;
2109
    }
2110
    return 0;
2111
}
2112
2113
int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
2114
                                const char *path, int pathLen, int reqSz, const char *contentType,
2115
                                const char *exHdrs, byte *buf, int bufSize)
2116
    {
2117
    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen;
2118
    char reqSzStr[6];
2119
    char* req = (char*)buf;
2120
    const char* blankStr = " ";
2121
    const char* http11Str = " HTTP/1.1";
2122
    const char* hostStr = "\r\nHost: ";
2123
    const char* contentLenStr = "\r\nContent-Length: ";
2124
    const char* contentTypeStr = "\r\nContent-Type: ";
2125
    const char* singleCrLfStr = "\r\n";
2126
    const char* doubleCrLfStr = "\r\n\r\n";
2127
    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
2128
        contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen;
2129
2130
    /* reject NULL pointers and invalid lengths before any deref or length
2131
     * math: the XSTRLEN/copy calls below assume non-NULL inputs */
2132
    if (reqType == NULL || domainName == NULL || path == NULL ||
2133
            contentType == NULL || pathLen < 0 || bufSize <= 0)
2134
        return 0;
2135
2136
    reqTypeLen = (word32)XSTRLEN(reqType);
2137
    domainNameLen = (word32)XSTRLEN(domainName);
2138
    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
2139
    contentTypeLen = (word32)XSTRLEN(contentType);
2140
2141
    /* reject CR/LF in the path or host to prevent HTTP header injection or
2142
     * request splitting from attacker-controlled URL components */
2143
    if (wolfIO_UrlHasCrlf(path, pathLen) ||
2144
            wolfIO_UrlHasCrlf(domainName, (int)domainNameLen)) {
2145
        return 0;
2146
    }
2147
2148
    blankStrLen = (word32)XSTRLEN(blankStr);
2149
    http11StrLen = (word32)XSTRLEN(http11Str);
2150
    hostStrLen = (word32)XSTRLEN(hostStr);
2151
    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
2152
    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
2153
2154
    if(exHdrs){
2155
        singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr);
2156
        exHdrsLen = (word32)XSTRLEN(exHdrs);
2157
    } else {
2158
        singleCrLfStrLen = 0;
2159
        exHdrsLen = 0;
2160
    }
2161
2162
    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
2163
2164
    /* determine max length and check it */
2165
    maxLen =
2166
        reqTypeLen +
2167
        blankStrLen +
2168
        (word32)pathLen +
2169
        http11StrLen +
2170
        hostStrLen +
2171
        domainNameLen +
2172
        contentLenStrLen +
2173
        reqSzStrLen +
2174
        contentTypeStrLen +
2175
        contentTypeLen +
2176
        singleCrLfStrLen +
2177
        exHdrsLen +
2178
        doubleCrLfStrLen +
2179
        (word32)1 /* null term */;
2180
    if (maxLen > (word32)bufSize)
2181
        return 0;
2182
2183
    XSTRNCPY((char*)buf, reqType, (size_t)bufSize);
2184
    buf += reqTypeLen; bufSize -= (int)reqTypeLen;
2185
    XSTRNCPY((char*)buf, blankStr, (size_t)bufSize);
2186
    buf += blankStrLen; bufSize -= (int)blankStrLen;
2187
    /* path may not be NUL terminated (CRL raw-URL case passes a pointer into
2188
     * the certificate with only pathLen valid bytes), so bound the copy to
2189
     * pathLen rather than scanning for a NUL */
2190
    XMEMCPY((char*)buf, path, (size_t)pathLen);
2191
    buf += pathLen; bufSize -= (int)pathLen;
2192
    XSTRNCPY((char*)buf, http11Str, (size_t)bufSize);
2193
    buf += http11StrLen; bufSize -= (int)http11StrLen;
2194
    if (domainNameLen > 0) {
2195
        XSTRNCPY((char*)buf, hostStr, (size_t)bufSize);
2196
        buf += hostStrLen; bufSize -= (int)hostStrLen;
2197
        XSTRNCPY((char*)buf, domainName, (size_t)bufSize);
2198
        buf += domainNameLen; bufSize -= (int)domainNameLen;
2199
    }
2200
    if (reqSz > 0 && reqSzStrLen > 0) {
2201
        XSTRNCPY((char*)buf, contentLenStr, (size_t)bufSize);
2202
        buf += contentLenStrLen; bufSize -= (int)contentLenStrLen;
2203
        XSTRNCPY((char*)buf, reqSzStr, (size_t)bufSize);
2204
        buf += reqSzStrLen; bufSize -= (int)reqSzStrLen;
2205
    }
2206
    if (contentTypeLen > 0) {
2207
        XSTRNCPY((char*)buf, contentTypeStr, (size_t)bufSize);
2208
        buf += contentTypeStrLen; bufSize -= (int)contentTypeStrLen;
2209
        XSTRNCPY((char*)buf, contentType, (size_t)bufSize);
2210
        buf += contentTypeLen; bufSize -= (int)contentTypeLen;
2211
    }
2212
    if (exHdrsLen > 0)
2213
    {
2214
        XSTRNCPY((char *)buf, singleCrLfStr, (size_t)bufSize);
2215
        buf += singleCrLfStrLen;
2216
        bufSize -= (int)singleCrLfStrLen;
2217
        XSTRNCPY((char *)buf, exHdrs, (size_t)bufSize);
2218
        buf += exHdrsLen;
2219
        bufSize -= (int)exHdrsLen;
2220
    }
2221
    XSTRNCPY((char*)buf, doubleCrLfStr, (size_t)bufSize);
2222
    buf += doubleCrLfStrLen;
2223
2224
#ifdef WOLFIO_DEBUG
2225
    printf("HTTP %s: %s", reqType, req);
2226
#endif
2227
2228
    /* calculate actual length based on original and new pointer */
2229
    return (int)((char*)buf - req);
2230
}
2231
2232
2233
#ifdef HAVE_OCSP
2234
2235
int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
2236
                                    int ocspReqSz, byte* buf, int bufSize)
2237
{
2238
    const char *cacheCtl = "Cache-Control: no-cache";
2239
    return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path),
2240
        ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize);
2241
}
2242
2243
static const char* ocspAppStrList[] = {
2244
    "application/ocsp-response",
2245
    NULL
2246
};
2247
2248
int wolfIO_HttpProcessResponseOcspGenericIO(
2249
    WolfSSLGenericIORecvCb ioCb, void* ioCbCtx, unsigned char** respBuf,
2250
    unsigned char* httpBuf, int httpBufSz, void* heap)
2251
{
2252
    return wolfIO_HttpProcessResponseGenericIO(ioCb, ioCbCtx,
2253
          ocspAppStrList, respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2254
}
2255
2256
/* return: >0 OCSP Response Size
2257
 *         -1 error */
2258
int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
2259
                                       byte* httpBuf, int httpBufSz, void* heap)
2260
{
2261
    return wolfIO_HttpProcessResponse(sfd, ocspAppStrList,
2262
        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2263
}
2264
2265
#if defined(WOLFSSL_OCSP_SCREEN_RESPONDER) && defined(HAVE_SOCKADDR)
2266
2267
/* Return 1 if the given IPv4 address (4 octets, network byte order) falls in a
2268
 * loopback/private/link-local/reserved range that an OCSP responder must not
2269
 * live in, else 0. */
2270
static int wolfIO_OcspIPv4Blocked(const unsigned char a[4])
2271
{
2272
    if (a[0] == 0)                                 /* 0.0.0.0/8    "this" net */
2273
        return 1;
2274
    if (a[0] == 127)                               /* 127.0.0.0/8  loopback */
2275
        return 1;
2276
    if (a[0] == 10)                                /* 10.0.0.0/8   private */
2277
        return 1;
2278
    if (a[0] == 172 && (a[1] & 0xF0) == 16)        /* 172.16.0.0/12 private */
2279
        return 1;
2280
    if (a[0] == 192 && a[1] == 168)                /* 192.168.0.0/16 private */
2281
        return 1;
2282
    if (a[0] == 169 && a[1] == 254)                /* 169.254.0.0/16 link-local
2283
                                                    * (incl. cloud metadata) */
2284
        return 1;
2285
    if (a[0] == 100 && (a[1] & 0xC0) == 64)        /* 100.64.0.0/10 CGNAT */
2286
        return 1;
2287
    if (a[0] >= 224)                               /* 224.0.0.0/4 multicast,
2288
                                                    * 240.0.0.0/4 reserved,
2289
                                                    * 255.255.255.255 bcast */
2290
        return 1;
2291
    return 0;
2292
}
2293
2294
/* Only the getaddrinfo resolver path yields AF_INET6 results; the gethostbyname
2295
 * fallback is IPv4-only. Guard on HAVE_GETADDRINFO so this is not compiled as an
2296
 * unused function in a WOLFSSL_IPV6 + gethostbyname-fallback build. */
2297
#if defined(WOLFSSL_IPV6) && defined(HAVE_GETADDRINFO)
2298
/* Return 1 if the given IPv6 address (16 octets, network byte order) falls in a
2299
 * loopback/unspecified/unique-local/link-local/multicast range, else 0.
2300
 * IPv4-mapped (::ffff:0:0/96), IPv4-compatible (::a.b.c.d), and NAT64
2301
 * (64:ff9b::/96) embeddings are unwrapped and screened as IPv4. */
2302
static int wolfIO_OcspIPv6Blocked(const unsigned char a[16])
2303
{
2304
    static const unsigned char v4mapped[12] =
2305
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
2306
    int i;
2307
    int zeroPrefix = 1;  /* bytes 0..11 all zero (IPv4-compatible prefix) */
2308
2309
    for (i = 0; i < 12; i++) {
2310
        if (a[i] != 0) {
2311
            zeroPrefix = 0;
2312
            break;
2313
        }
2314
    }
2315
    if ((a[0] & 0xFE) == 0xFC)                     /* fc00::/7 unique local */
2316
        return 1;
2317
    if (a[0] == 0xFE && (a[1] & 0xC0) == 0x80)     /* fe80::/10 link-local */
2318
        return 1;
2319
    if (a[0] == 0xFF)                              /* ff00::/8 multicast */
2320
        return 1;
2321
    if (XMEMCMP(a, v4mapped, sizeof(v4mapped)) == 0) /* ::ffff:0:0/96 mapped */
2322
        return wolfIO_OcspIPv4Blocked(a + 12);
2323
    /* :: unspecified, ::1 loopback, and deprecated IPv4-compatible ::a.b.c.d
2324
     * all have 96 zero leading bits; screen the embedded IPv4 (covers them,
2325
     * since 0.0.0.0/8 is blocked). No public unicast address looks like this. */
2326
    if (zeroPrefix)
2327
        return wolfIO_OcspIPv4Blocked(a + 12);
2328
    if (a[0] == 0x00 && a[1] == 0x64 && a[2] == 0xFF && a[3] == 0x9B) {
2329
        /* NAT64 well-known prefix 64:ff9b::/96 -> screen embedded IPv4 */
2330
        int zeroMid = 1;
2331
        for (i = 4; i < 12; i++) {
2332
            if (a[i] != 0) {
2333
                zeroMid = 0;
2334
                break;
2335
            }
2336
        }
2337
        if (zeroMid)
2338
            return wolfIO_OcspIPv4Blocked(a + 12);
2339
    }
2340
    return 0;
2341
}
2342
#endif /* WOLFSSL_IPV6 && HAVE_GETADDRINFO */
2343
2344
#endif /* WOLFSSL_OCSP_SCREEN_RESPONDER && HAVE_SOCKADDR */
2345
2346
#ifdef WOLFSSL_OCSP_SCREEN_RESPONDER
2347
2348
/* Screen an OCSP responder host before connecting, so that a certificate-
2349
 * supplied AIA URL cannot steer the request at an internal/reserved address
2350
 * (SSRF, CWE-918). The host is resolved and every returned address is checked;
2351
 * the destination is rejected if ANY resolved address is in a blocked range.
2352
 * Returns 1 if the destination is permitted, 0 if it must be blocked.
2353
 *
2354
 * This is a best-effort guard performed at the integration boundary; a host
2355
 * that cannot be resolved is treated as not permitted. Note that the connect
2356
 * resolves the name again, so this does not by itself defeat a DNS-rebinding
2357
 * responder -- deployments that need a hard guarantee should install a custom
2358
 * OCSP IO callback with wolfSSL_CTX_SetOCSP_Cb.
2359
 *
2360
 * This screening is OPT-IN: it is compiled and active only when
2361
 * WOLFSSL_OCSP_SCREEN_RESPONDER is defined. It is off by default because many
2362
 * deployments legitimately run an OCSP responder on loopback or an internal
2363
 * network (the in-tree OCSP tests use http://127.0.0.1, for example), and an
2364
 * operator-configured override responder (wolfSSL_CTX_SetOCSP_OverrideURL) is
2365
 * delivered to this same default callback and would be screened identically. */
2366
int wolfIO_OcspDestAllowed(const char* host)
2367
{
2368
#ifdef HAVE_SOCKADDR
2369
    int blocked = 0;
2370
#if defined(HAVE_GETADDRINFO)
2371
    ADDRINFO  hints;
2372
    ADDRINFO* answer = NULL;
2373
    ADDRINFO* cur;
2374
2375
    if (host == NULL)
2376
        return 0;
2377
2378
    XMEMSET(&hints, 0, sizeof(hints));
2379
#ifdef WOLFSSL_IPV6
2380
    hints.ai_family = AF_UNSPEC;
2381
#else
2382
    hints.ai_family = AF_INET;
2383
#endif
2384
    hints.ai_socktype = SOCK_STREAM;
2385
    hints.ai_protocol = IPPROTO_TCP;
2386
2387
    if (getaddrinfo(host, NULL, &hints, &answer) != 0 || answer == NULL) {
2388
        /* cannot resolve -> cannot verify destination -> deny */
2389
        return 0;
2390
    }
2391
2392
    for (cur = answer; cur != NULL && !blocked; cur = cur->ai_next) {
2393
        if (cur->ai_family == AF_INET) {
2394
            SOCKADDR_IN* s = (SOCKADDR_IN*)cur->ai_addr;
2395
            blocked = wolfIO_OcspIPv4Blocked(
2396
                (const unsigned char*)&s->sin_addr.s_addr);
2397
        }
2398
    #ifdef WOLFSSL_IPV6
2399
        else if (cur->ai_family == AF_INET6) {
2400
            SOCKADDR_IN6* s = (SOCKADDR_IN6*)cur->ai_addr;
2401
            blocked = wolfIO_OcspIPv6Blocked(
2402
                (const unsigned char*)&s->sin6_addr);
2403
        }
2404
    #endif
2405
    }
2406
    freeaddrinfo(answer);
2407
#else /* !HAVE_GETADDRINFO: gethostbyname fallback */
2408
    /* gethostbyname() returns non-reentrant static storage; on multi-threaded
2409
     * glibc use gethostbyname_r() with a heap buffer, matching the resolver
2410
     * pattern in wolfIO_TcpConnect(). */
2411
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
2412
    !defined(SINGLE_THREADED)
2413
    #define WOLFSSL_OCSP_GHBN_R
2414
#endif
2415
#ifdef WOLFSSL_OCSP_GHBN_R
2416
    HOSTENT  entry_buf, *entry = NULL;
2417
    char*    ghbn_r_buf;
2418
    int      ghbn_r_errno;
2419
#else
2420
    HOSTENT* entry;
2421
#endif
2422
    int i;
2423
2424
    if (host == NULL)
2425
        return 0;
2426
2427
#ifdef WOLFSSL_OCSP_GHBN_R
2428
    /* 2048 is the same empirically-chosen buffer size used in
2429
     * wolfIO_TcpConnect(). */
2430
    ghbn_r_buf = (char*)XMALLOC(2048, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2431
    if (ghbn_r_buf != NULL) {
2432
        gethostbyname_r(host, &entry_buf, ghbn_r_buf, 2048, &entry,
2433
                        &ghbn_r_errno);
2434
    }
2435
#else
2436
    entry = gethostbyname(host);
2437
#endif
2438
    if (entry == NULL) {
2439
#ifdef WOLFSSL_OCSP_GHBN_R
2440
        XFREE(ghbn_r_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2441
#endif
2442
        return 0;
2443
    }
2444
2445
    /* gethostbyname()/gethostbyname_r() resolve only IPv4 (h_addrtype
2446
     * AF_INET); IPv6 would require gethostbyname2()/getipnodebyname(), which
2447
     * are not used here, so screen each returned address as IPv4. */
2448
    for (i = 0; entry->h_addr_list[i] != NULL && !blocked; i++) {
2449
        if (entry->h_addrtype == AF_INET) {
2450
            blocked = wolfIO_OcspIPv4Blocked(
2451
                (const unsigned char*)entry->h_addr_list[i]);
2452
        }
2453
    }
2454
#ifdef WOLFSSL_OCSP_GHBN_R
2455
    XFREE(ghbn_r_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2456
    #undef WOLFSSL_OCSP_GHBN_R
2457
#endif
2458
#endif /* HAVE_GETADDRINFO */
2459
2460
    return blocked ? 0 : 1;
2461
#else /* !HAVE_SOCKADDR: no address support to screen */
2462
    (void)host;
2463
    return 1;
2464
#endif /* HAVE_SOCKADDR */
2465
}
2466
2467
#endif /* WOLFSSL_OCSP_SCREEN_RESPONDER */
2468
2469
/* in default wolfSSL callback ctx is the heap pointer */
2470
int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
2471
                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
2472
{
2473
    SOCKET_T sfd = SOCKET_INVALID;
2474
    word16   port;
2475
    int      ret = -1;
2476
#ifdef WOLFSSL_SMALL_STACK
2477
    char*    path;
2478
    char*    domainName;
2479
#else
2480
    char     path[MAX_URL_ITEM_SIZE];
2481
    char     domainName[MAX_URL_ITEM_SIZE];
2482
#endif
2483
2484
#ifdef WOLFSSL_SMALL_STACK
2485
    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2486
    if (path == NULL)
2487
        return MEMORY_E;
2488
2489
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL,
2490
            DYNAMIC_TYPE_TMP_BUFFER);
2491
    if (domainName == NULL) {
2492
        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2493
        return MEMORY_E;
2494
    }
2495
#endif
2496
2497
    if (ocspReqBuf == NULL || ocspReqSz == 0) {
2498
        WOLFSSL_MSG("OCSP request is required for lookup");
2499
    }
2500
    else if (ocspRespBuf == NULL) {
2501
        WOLFSSL_MSG("Cannot save OCSP response");
2502
    }
2503
    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
2504
        WOLFSSL_MSG("Unable to decode OCSP URL");
2505
    }
2506
#ifdef WOLFSSL_OCSP_SCREEN_RESPONDER
2507
    /* Opt-in: reject responders that resolve to private/loopback/link-local
2508
     * ranges to keep a certificate-supplied AIA URL from forcing an internal
2509
     * request (SSRF, CWE-918). */
2510
    else if (!wolfIO_OcspDestAllowed(domainName)) {
2511
        WOLFSSL_MSG("OCSP responder destination not permitted");
2512
    }
2513
#endif
2514
    else {
2515
        /* Note, the library uses the EmbedOcspRespFree() callback to
2516
         * free this buffer. */
2517
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2518
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
2519
2520
        if (httpBuf == NULL) {
2521
            WOLFSSL_MSG("Unable to create OCSP response buffer");
2522
        }
2523
        else {
2524
            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
2525
                                                            httpBuf, httpBufSz);
2526
2527
            if (httpBufSz <= 0) {
2528
                WOLFSSL_MSG("Unable to build OCSP request");
2529
            }
2530
            else if ((ret = wolfIO_TcpConnect(&sfd, domainName, port,
2531
                                              io_timeout_sec)) != 0) {
2532
                WOLFSSL_MSG("OCSP Responder connection failed");
2533
            }
2534
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
2535
                                                                    httpBufSz) {
2536
                WOLFSSL_MSG("OCSP http request failed");
2537
            }
2538
            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
2539
                                                                    ocspReqSz) {
2540
                WOLFSSL_MSG("OCSP ocsp request failed");
2541
            }
2542
            else {
2543
                ret = wolfIO_HttpProcessResponseOcsp((int)sfd, ocspRespBuf, httpBuf,
2544
                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
2545
            }
2546
            if (sfd != SOCKET_INVALID)
2547
                CloseSocket(sfd);
2548
            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
2549
        }
2550
    }
2551
2552
    WC_FREE_VAR_EX(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2553
    WC_FREE_VAR_EX(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2554
2555
    return ret;
2556
}
2557
2558
/* in default callback ctx is heap hint */
2559
void EmbedOcspRespFree(void* ctx, byte *resp)
2560
{
2561
    XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
2562
2563
    (void)ctx;
2564
}
2565
#endif /* HAVE_OCSP */
2566
2567
2568
#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
2569
2570
int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
2571
    const char* domainName, byte* buf, int bufSize)
2572
{
2573
    const char *cacheCtl = "Cache-Control: no-cache";
2574
    return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "",
2575
                                   cacheCtl, buf, bufSize);
2576
}
2577
2578
int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
2579
    int httpBufSz)
2580
{
2581
    int ret;
2582
    byte *respBuf = NULL;
2583
2584
    const char* appStrList[] = {
2585
        "application/pkix-crl",
2586
        "application/x-pkcs7-crl",
2587
        NULL
2588
    };
2589
2590
2591
    ret = wolfIO_HttpProcessResponse(sfd, appStrList,
2592
        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
2593
    if (ret >= 0) {
2594
        ret = BufferLoadCRL(crl, respBuf, ret, WOLFSSL_FILETYPE_ASN1, 0);
2595
    }
2596
    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
2597
2598
    return ret;
2599
}
2600
2601
int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
2602
{
2603
    SOCKET_T sfd = SOCKET_INVALID;
2604
    word16   port;
2605
    int      ret = -1;
2606
    WC_DECLARE_VAR(domainName, char, MAX_URL_ITEM_SIZE, 0);
2607
2608
#ifdef WOLFSSL_SMALL_STACK
2609
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
2610
                                                       DYNAMIC_TYPE_TMP_BUFFER);
2611
    if (domainName == NULL) {
2612
        return MEMORY_E;
2613
    }
2614
#endif
2615
2616
    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
2617
        WOLFSSL_MSG("Unable to decode CRL URL");
2618
    }
2619
    else {
2620
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2621
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, crl->heap,
2622
                                                              DYNAMIC_TYPE_CRL);
2623
        if (httpBuf == NULL) {
2624
            WOLFSSL_MSG("Unable to create CRL response buffer");
2625
        }
2626
        else {
2627
            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
2628
                httpBuf, httpBufSz);
2629
2630
            if (httpBufSz <= 0) {
2631
                WOLFSSL_MSG("Unable to build CRL request");
2632
            }
2633
            else if ((ret = wolfIO_TcpConnect(&sfd, domainName, port,
2634
                                              io_timeout_sec)) != 0) {
2635
                WOLFSSL_MSG("CRL connection failed");
2636
            }
2637
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
2638
                                                                 != httpBufSz) {
2639
                WOLFSSL_MSG("CRL http get failed");
2640
            }
2641
            else {
2642
                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
2643
                                                      HTTP_SCRATCH_BUFFER_SIZE);
2644
            }
2645
            if (sfd != SOCKET_INVALID)
2646
                CloseSocket(sfd);
2647
            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
2648
        }
2649
    }
2650
2651
    WC_FREE_VAR_EX(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
2652
2653
    return ret;
2654
}
2655
#endif /* HAVE_CRL && HAVE_CRL_IO */
2656
2657
#endif /* HAVE_HTTP_CLIENT */
2658
2659
2660
2661
void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
2662
48
{
2663
48
    if (ctx) {
2664
48
        ctx->CBIORecv = CBIORecv;
2665
    #ifdef OPENSSL_EXTRA
2666
        ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
2667
    #endif
2668
48
    }
2669
48
}
2670
2671
2672
void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
2673
48
{
2674
48
    if (ctx) {
2675
48
        ctx->CBIOSend = CBIOSend;
2676
    #ifdef OPENSSL_EXTRA
2677
        ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
2678
    #endif
2679
48
    }
2680
48
}
2681
2682
2683
/* sets the IO callback to use for receives at WOLFSSL level */
2684
void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv)
2685
0
{
2686
0
    if (ssl) {
2687
0
        ssl->CBIORecv = CBIORecv;
2688
    #ifdef OPENSSL_EXTRA
2689
        ssl->cbioFlag |= WOLFSSL_CBIO_RECV;
2690
    #endif
2691
0
    }
2692
0
}
2693
2694
2695
/* sets the IO callback to use for sends at WOLFSSL level */
2696
void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
2697
0
{
2698
0
    if (ssl) {
2699
0
        ssl->CBIOSend = CBIOSend;
2700
    #ifdef OPENSSL_EXTRA
2701
        ssl->cbioFlag |= WOLFSSL_CBIO_SEND;
2702
    #endif
2703
0
    }
2704
0
}
2705
2706
void wolfSSL_SSLDisableRead(WOLFSSL *ssl)
2707
0
{
2708
0
    if (ssl) {
2709
0
        ssl->options.disableRead = 1;
2710
0
    }
2711
0
}
2712
2713
void wolfSSL_SSLEnableRead(WOLFSSL *ssl)
2714
0
{
2715
0
    if (ssl) {
2716
0
        ssl->options.disableRead = 0;
2717
0
    }
2718
0
}
2719
2720
2721
void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
2722
0
{
2723
0
    if (ssl)
2724
0
        ssl->IOCB_ReadCtx = rctx;
2725
0
}
2726
2727
2728
void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
2729
0
{
2730
0
    if (ssl)
2731
0
        ssl->IOCB_WriteCtx = wctx;
2732
0
}
2733
2734
2735
void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
2736
0
{
2737
0
    if (ssl)
2738
0
        return ssl->IOCB_ReadCtx;
2739
2740
0
    return NULL;
2741
0
}
2742
2743
2744
void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
2745
0
{
2746
0
    if (ssl)
2747
0
        return ssl->IOCB_WriteCtx;
2748
2749
0
    return NULL;
2750
0
}
2751
2752
2753
void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
2754
0
{
2755
0
    if (ssl)
2756
0
        ssl->rflags = flags;
2757
0
}
2758
2759
2760
void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
2761
0
{
2762
0
    if (ssl)
2763
0
        ssl->wflags = flags;
2764
0
}
2765
2766
2767
#ifdef WOLFSSL_DTLS
2768
2769
void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
2770
{
2771
    if (ctx)
2772
        ctx->CBIOCookie = cb;
2773
}
2774
2775
2776
void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
2777
{
2778
    if (ssl)
2779
        ssl->IOCB_CookieCtx = ctx;
2780
}
2781
2782
2783
void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
2784
{
2785
    if (ssl)
2786
        return ssl->IOCB_CookieCtx;
2787
2788
    return NULL;
2789
}
2790
#endif /* WOLFSSL_DTLS */
2791
2792
#ifdef WOLFSSL_SESSION_EXPORT
2793
2794
void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
2795
{
2796
    if (ctx)
2797
        ctx->CBGetPeer = cb;
2798
}
2799
2800
2801
void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
2802
{
2803
    if (ctx)
2804
        ctx->CBSetPeer = cb;
2805
}
2806
2807
#endif /* WOLFSSL_SESSION_EXPORT */
2808
2809
2810
#ifdef HAVE_NETX
2811
2812
/* Map a failing NetX status onto a wolfSSL CBIO error code.
2813
 * Transient conditions must not be reported as fatal, otherwise a non
2814
 * blocking (or short wait option) setup cannot retry the operation. */
2815
static int NetX_TranslateReturnCode(UINT status, int direction)
2816
{
2817
    int ret;
2818
2819
    switch (status) {
2820
        /* Receive queue empty, packet pool exhausted, peer receive window
2821
         * full or transmit queue at max depth. All clear on their own. */
2822
        case NX_NO_PACKET:
2823
        case NX_WINDOW_OVERFLOW:
2824
        case NX_TX_QUEUE_DEPTH:
2825
            WOLFSSL_MSG("\tWould block");
2826
            ret = (direction == SOCKET_SENDING) ? WOLFSSL_CBIO_ERR_WANT_WRITE
2827
                                                : WOLFSSL_CBIO_ERR_WANT_READ;
2828
            break;
2829
2830
        /* A suspended wait was aborted, treated like an interrupted call. */
2831
        case NX_WAIT_ABORTED:
2832
            WOLFSSL_MSG("\tSocket interrupted");
2833
            ret = WOLFSSL_CBIO_ERR_ISR;
2834
            break;
2835
2836
        /* NetX has no separate reset status, so a peer reset also lands
2837
         * here and is reported as a close. */
2838
        case NX_NOT_CONNECTED:
2839
            WOLFSSL_MSG("\tConnection closed");
2840
            ret = WOLFSSL_CBIO_ERR_CONN_CLOSE;
2841
            break;
2842
2843
        default:
2844
            WOLFSSL_MSG_EX("\tGeneral error: %u", (unsigned int)status);
2845
            ret = WOLFSSL_CBIO_ERR_GENERAL;
2846
            break;
2847
    }
2848
2849
    return ret;
2850
}
2851
2852
/* The NetX receive callback for TLS
2853
 *  return :  bytes read, or error
2854
 */
2855
int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2856
{
2857
    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
2858
    ULONG left;
2859
    ULONG total;
2860
    ULONG copied = 0;
2861
    UINT  status;
2862
2863
    (void)ssl;
2864
2865
    if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
2866
        WOLFSSL_MSG("NetX Recv NULL parameters");
2867
        return WOLFSSL_CBIO_ERR_GENERAL;
2868
    }
2869
2870
    if (nxCtx->nxPacket == NULL) {
2871
        status = nx_tcp_socket_receive(nxCtx->nxTcpSocket, &nxCtx->nxPacket,
2872
                                       nxCtx->nxWait);
2873
        if (status != NX_SUCCESS) {
2874
            WOLFSSL_MSG("NetX Recv receive error");
2875
            return NetX_TranslateReturnCode(status, SOCKET_RECEIVING);
2876
        }
2877
    }
2878
2879
    if (nxCtx->nxPacket) {
2880
        status = nx_packet_length_get(nxCtx->nxPacket, &total);
2881
        if (status != NX_SUCCESS) {
2882
            WOLFSSL_MSG("NetX Recv length get error");
2883
            return WOLFSSL_CBIO_ERR_GENERAL;
2884
        }
2885
2886
        left = total - nxCtx->nxOffset;
2887
        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
2888
                                               buf, sz, &copied);
2889
        if (status != NX_SUCCESS) {
2890
            WOLFSSL_MSG("NetX Recv data extract offset error");
2891
            return WOLFSSL_CBIO_ERR_GENERAL;
2892
        }
2893
2894
        nxCtx->nxOffset += copied;
2895
2896
        if (copied == left) {
2897
            WOLFSSL_MSG("NetX Recv Drained packet");
2898
            nx_packet_release(nxCtx->nxPacket);
2899
            nxCtx->nxPacket = NULL;
2900
            nxCtx->nxOffset = 0;
2901
        }
2902
    }
2903
2904
    return copied;
2905
}
2906
2907
2908
/* The NetX send callback for TLS
2909
 *  return : bytes sent, or error
2910
 */
2911
int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2912
{
2913
    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
2914
    NX_PACKET*      packet;
2915
    NX_PACKET_POOL* pool;   /* shorthand */
2916
    UINT            status;
2917
2918
    (void)ssl;
2919
2920
    if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
2921
        WOLFSSL_MSG("NetX Send NULL parameters");
2922
        return WOLFSSL_CBIO_ERR_GENERAL;
2923
    }
2924
2925
    pool = nxCtx->nxTcpSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
2926
    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
2927
                                nxCtx->nxWait);
2928
    if (status != NX_SUCCESS) {
2929
        WOLFSSL_MSG("NetX Send packet alloc error");
2930
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
2931
    }
2932
2933
    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
2934
    if (status != NX_SUCCESS) {
2935
        nx_packet_release(packet);
2936
        WOLFSSL_MSG("NetX Send data append error");
2937
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
2938
    }
2939
2940
    status = nx_tcp_socket_send(nxCtx->nxTcpSocket, packet, nxCtx->nxWait);
2941
    if (status != NX_SUCCESS) {
2942
        nx_packet_release(packet);
2943
        WOLFSSL_MSG("NetX Send socket send error");
2944
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
2945
    }
2946
2947
    return sz;
2948
}
2949
2950
/* like set_fd, but for default NetX context */
2951
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, ULONG waitoption)
2952
{
2953
    if (ssl) {
2954
        ssl->nxCtx.nxTcpSocket  = nxsocket;
2955
        ssl->nxCtx.nxWait       = waitoption;
2956
    }
2957
}
2958
2959
/* WOLFSSL_NETX_DUO: requires ThreadX NetX Duo (NXD_ADDRESS, nxd_udp_socket_send) */
2960
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
2961
static void NetX_ResetPacket(NetX_Ctx* nxCtx)
2962
{
2963
    if (nxCtx->nxPacket != NULL) {
2964
        nx_packet_release(nxCtx->nxPacket);
2965
        nxCtx->nxPacket = NULL;
2966
    }
2967
    nxCtx->nxOffset = 0;
2968
}
2969
2970
static int NetX_PeerAddrEqual(const NXD_ADDRESS* left, const NXD_ADDRESS* right)
2971
{
2972
    if (left->nxd_ip_version != right->nxd_ip_version)
2973
        return 0;
2974
2975
    /* NXD_ADDRESS only carries the union member for the families the NetX Duo
2976
     * build was configured with, so guard each access. NX_DISABLE_IPV4 and
2977
     * NX_DISABLE_IPV6 are set in nx_user.h, FEATURE_NX_IPV6 is derived from
2978
     * NX_DISABLE_IPV6 by nx_api.h. */
2979
#ifndef NX_DISABLE_IPV4
2980
    if (left->nxd_ip_version == NX_IP_VERSION_V4)
2981
        return left->nxd_ip_address.v4 == right->nxd_ip_address.v4;
2982
#endif
2983
#ifdef FEATURE_NX_IPV6
2984
    if (left->nxd_ip_version == NX_IP_VERSION_V6) {
2985
        return left->nxd_ip_address.v6[0] == right->nxd_ip_address.v6[0] &&
2986
               left->nxd_ip_address.v6[1] == right->nxd_ip_address.v6[1] &&
2987
               left->nxd_ip_address.v6[2] == right->nxd_ip_address.v6[2] &&
2988
               left->nxd_ip_address.v6[3] == right->nxd_ip_address.v6[3];
2989
    }
2990
#endif
2991
2992
    /* Unknown or unsupported address family, do not treat it as our peer. */
2993
    return 0;
2994
}
2995
2996
/* The NetX receive callback for DTLS
2997
 *  return :  bytes read, or error
2998
 */
2999
int NetX_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3000
{
3001
    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
3002
    NXD_ADDRESS srcIp;
3003
    ULONG left;
3004
    ULONG total;
3005
    ULONG copied = 0;
3006
    UINT  srcPort;
3007
    UINT  status;
3008
    ULONG waitOption;
3009
    int   dtls_timeout;
3010
    int   usingNonblock;
3011
    byte  doDtlsTimeout;
3012
    word32 invalidPeerPackets = 0;
3013
#if defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
3014
    const word32 maxInvalidPeerPackets = DTLS_RECEIVEFROM_MAX_INVALID_PEER;
3015
#else
3016
    const word32 maxInvalidPeerPackets = 10;
3017
#endif
3018
3019
    if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
3020
        WOLFSSL_MSG("NetX Recv NULL parameters");
3021
        return WOLFSSL_CBIO_ERR_GENERAL;
3022
    }
3023
3024
    if (sz < 0)
3025
        return WOLFSSL_CBIO_ERR_GENERAL;
3026
3027
    usingNonblock = wolfSSL_dtls_get_using_nonblock(ssl);
3028
3029
    /* Don't use ssl->options.handShakeDone since it is true even if
3030
     * we are in the process of renegotiation. */
3031
    doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
3032
#ifdef WOLFSSL_DTLS13
3033
    if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
3034
        doDtlsTimeout =
3035
            doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
3036
            (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
3037
    }
3038
#endif /* WOLFSSL_DTLS13 */
3039
3040
    do {
3041
        if (nxCtx->nxPacket == NULL) {
3042
            /* Compute wait ticks from the DTLS retransmit timeout while a
3043
             * handshake/RTX timer is active, otherwise honor nxWait. */
3044
            if (!usingNonblock) {
3045
                dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
3046
                if (!doDtlsTimeout)
3047
                    dtls_timeout = 0;
3048
#ifdef WOLFSSL_DTLS13
3049
                if (dtls_timeout > 0 && wolfSSL_dtls13_use_quick_timeout(ssl) &&
3050
                    IsAtLeastTLSv1_3(ssl->version)) {
3051
                    if (dtls_timeout > 4)
3052
                        dtls_timeout /= 4;
3053
                    else
3054
                        dtls_timeout = 1;
3055
                }
3056
#endif /* WOLFSSL_DTLS13 */
3057
                waitOption = (dtls_timeout > 0)
3058
                             ? (ULONG)dtls_timeout * NX_IP_PERIODIC_RATE
3059
                             : nxCtx->nxWait;
3060
            }
3061
            else {
3062
                waitOption = NX_NO_WAIT; /* non-blocking */
3063
            }
3064
3065
            status = nx_udp_socket_receive(nxCtx->nxUdpSocket, &nxCtx->nxPacket,
3066
                                           waitOption);
3067
            if (status != NX_SUCCESS) {
3068
                if (status == NX_NO_PACKET) {
3069
                    /* Normal receive timeout - allow DTLS to retransmit */
3070
                    WOLFSSL_MSG("NetX Recv timeout");
3071
                    return usingNonblock
3072
                           ? WOLFSSL_CBIO_ERR_WANT_READ
3073
                           : WOLFSSL_CBIO_ERR_TIMEOUT;
3074
                }
3075
                WOLFSSL_MSG("NetX Recv receive error");
3076
                return NetX_TranslateReturnCode(status, SOCKET_RECEIVING);
3077
            }
3078
3079
            status = nxd_udp_source_extract(nxCtx->nxPacket, &srcIp, &srcPort);
3080
            if (status != NX_SUCCESS) {
3081
                NetX_ResetPacket(nxCtx);
3082
                WOLFSSL_MSG("NetX Recv source extract error");
3083
                return WOLFSSL_CBIO_ERR_GENERAL;
3084
            }
3085
3086
            if (nxCtx->nxPort != 0 &&
3087
                (nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V4 ||
3088
                 nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V6)) {
3089
                if ((USHORT)srcPort != nxCtx->nxPort ||
3090
                    !NetX_PeerAddrEqual(&srcIp, &nxCtx->nxdIp)) {
3091
                    WOLFSSL_MSG("NetX Recv ignored packet from invalid peer");
3092
                    NetX_ResetPacket(nxCtx);
3093
                    /* Intentional: bound discard only during handshake/RTX
3094
                     * window (doDtlsTimeout). Post-handshake, spoofed-source
3095
                     * packets loop until a valid one arrives. This matches
3096
                     * the EmbedReceiveFrom behavior. */
3097
                    if (doDtlsTimeout) {
3098
                        invalidPeerPackets++;
3099
                        if (invalidPeerPackets > maxInvalidPeerPackets) {
3100
                            return usingNonblock
3101
                                   ? WOLFSSL_CBIO_ERR_WANT_READ
3102
                                   : WOLFSSL_CBIO_ERR_TIMEOUT;
3103
                        }
3104
                    }
3105
                    continue;
3106
                }
3107
            }
3108
            else {
3109
                /* No peer preset: accept first datagram and lock onto source. */
3110
                nxCtx->nxdIp = srcIp;
3111
                nxCtx->nxPort = (USHORT)srcPort;
3112
            }
3113
        }
3114
3115
        status = nx_packet_length_get(nxCtx->nxPacket, &total);
3116
        if (status != NX_SUCCESS) {
3117
            NetX_ResetPacket(nxCtx);
3118
            WOLFSSL_MSG("NetX Recv length get error");
3119
            return WOLFSSL_CBIO_ERR_GENERAL;
3120
        }
3121
3122
        if (total == 0) {
3123
            WOLFSSL_MSG("Ignoring 0-length datagram");
3124
            NetX_ResetPacket(nxCtx);
3125
            /* Intentional: same discard-bound semantics as invalid-peer
3126
             * handling above and EmbedReceiveFrom: only bounded during
3127
             * handshake, loops post-handshake until a valid datagram
3128
             * arrives. */
3129
            if (doDtlsTimeout) {
3130
                invalidPeerPackets++;
3131
                if (invalidPeerPackets > maxInvalidPeerPackets) {
3132
                    return usingNonblock
3133
                           ? WOLFSSL_CBIO_ERR_WANT_READ
3134
                           : WOLFSSL_CBIO_ERR_TIMEOUT;
3135
                }
3136
            }
3137
            continue;
3138
        }
3139
3140
        if (nxCtx->nxOffset > total) {
3141
            NetX_ResetPacket(nxCtx);
3142
            WOLFSSL_MSG("NetX Recv invalid packet offset");
3143
            return WOLFSSL_CBIO_ERR_GENERAL;
3144
        }
3145
3146
        left = total - nxCtx->nxOffset;
3147
        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
3148
                                               buf, sz, &copied);
3149
        if (status != NX_SUCCESS) {
3150
            NetX_ResetPacket(nxCtx);
3151
            WOLFSSL_MSG("NetX Recv data extract offset error");
3152
            return WOLFSSL_CBIO_ERR_GENERAL;
3153
        }
3154
3155
        /* DTLS datagram semantics: always release the full datagram after one
3156
         * read. If the caller's buffer (sz) is smaller than the datagram,
3157
         * the excess bytes are discarded here, matching EmbedReceiveFrom /
3158
         * recvfrom behavior. Partial-datagram retention would re-introduce
3159
         * TCP stream semantics and could mis-frame DTLS records. */
3160
        if (copied < left) {
3161
            WOLFSSL_MSG("NetX Recv datagram truncated, discarding remainder");
3162
        }
3163
        NetX_ResetPacket(nxCtx);
3164
3165
        return (int)copied;
3166
    } while (1);
3167
}
3168
3169
/* The NetX send callback for DTLS
3170
 *  return : bytes sent, or error
3171
 */
3172
int NetX_SendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
3173
{
3174
    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
3175
    NX_PACKET*      packet;
3176
    NX_PACKET_POOL* pool;   /* shorthand */
3177
    UINT            status;
3178
3179
    (void)ssl;
3180
3181
    if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
3182
        WOLFSSL_MSG("NetX Send NULL parameters");
3183
        return WOLFSSL_CBIO_ERR_GENERAL;
3184
    }
3185
3186
    if (sz < 0)
3187
        return WOLFSSL_CBIO_ERR_GENERAL;
3188
3189
    pool = nxCtx->nxUdpSocket->nx_udp_socket_ip_ptr->nx_ip_default_packet_pool;
3190
    status = nx_packet_allocate(pool, &packet, NX_UDP_PACKET,
3191
                                nxCtx->nxWait);
3192
    if (status != NX_SUCCESS) {
3193
        WOLFSSL_MSG("NetX Send packet alloc error");
3194
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
3195
    }
3196
3197
    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
3198
    if (status != NX_SUCCESS) {
3199
        nx_packet_release(packet);
3200
        WOLFSSL_MSG("NetX Send data append error");
3201
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
3202
    }
3203
3204
    /* nxd_udp_socket_send() takes the NXD_ADDRESS itself and dispatches on
3205
     * nxd_ip_version, so it serves IPv4 and IPv6 without reaching into the
3206
     * nxd_ip_address union, which is only partly populated when the NetX Duo
3207
     * build disables a family. */
3208
    status = nxd_udp_socket_send(nxCtx->nxUdpSocket, packet,
3209
                                 &nxCtx->nxdIp, (UINT)nxCtx->nxPort);
3210
    if (status != NX_SUCCESS) {
3211
        nx_packet_release(packet);
3212
        WOLFSSL_MSG("NetX Send socket send error");
3213
        return NetX_TranslateReturnCode(status, SOCKET_SENDING);
3214
    }
3215
3216
    return sz;
3217
}
3218
3219
/* like set_fd, but for default NetX Duo UDP context */
3220
void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
3221
                              NXD_ADDRESS nxdip, USHORT nxport,
3222
                              ULONG waitoption)
3223
{
3224
    if (ssl) {
3225
        ssl->nxCtx.nxUdpSocket = nxsocket;
3226
        ssl->nxCtx.nxdIp       = nxdip;
3227
        ssl->nxCtx.nxPort      = nxport;
3228
        ssl->nxCtx.nxWait      = waitoption;
3229
    }
3230
}
3231
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
3232
3233
#endif /* HAVE_NETX */
3234
3235
3236
#ifdef MICRIUM
3237
3238
/* Micrium uTCP/IP port, using the NetSock API
3239
 * TCP and UDP are currently supported with the callbacks below.
3240
 *
3241
 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
3242
 * and EmbedSetPeer() callbacks implemented.
3243
 *
3244
 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
3245
 * callback implemented.
3246
 *
3247
 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
3248
 * callback implemented.
3249
 */
3250
3251
/* The Micrium uTCP/IP send callback
3252
 * return : bytes sent, or error
3253
 */
3254
int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3255
{
3256
    NET_SOCK_ID sd = *(int*)ctx;
3257
    NET_SOCK_RTN_CODE ret;
3258
    NET_ERR err;
3259
3260
    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
3261
    if (ret < 0) {
3262
        WOLFSSL_MSG("Embed Send error");
3263
3264
        if (err == NET_ERR_TX) {
3265
            WOLFSSL_MSG("\tWould block");
3266
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
3267
3268
        } else {
3269
            WOLFSSL_MSG("\tGeneral error");
3270
            return WOLFSSL_CBIO_ERR_GENERAL;
3271
        }
3272
    }
3273
3274
    return ret;
3275
}
3276
3277
/* The Micrium uTCP/IP receive callback
3278
 *  return : nb bytes read, or error
3279
 */
3280
int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3281
{
3282
    NET_SOCK_ID sd = *(int*)ctx;
3283
    NET_SOCK_RTN_CODE ret;
3284
    NET_ERR err;
3285
3286
    #ifdef WOLFSSL_DTLS
3287
    {
3288
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
3289
        /* Don't use ssl->options.handShakeDone since it is true even if
3290
         * we are in the process of renegotiation */
3291
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
3292
        #ifdef WOLFSSL_DTLS13
3293
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
3294
            doDtlsTimeout =
3295
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
3296
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
3297
        }
3298
        #endif /* WOLFSSL_DTLS13 */
3299
3300
        if (!doDtlsTimeout)
3301
            dtls_timeout = 0;
3302
3303
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
3304
            /* needs timeout in milliseconds */
3305
            #ifdef WOLFSSL_DTLS13
3306
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
3307
                IsAtLeastTLSv1_3(ssl->version)) {
3308
                dtls_timeout = (1000 * dtls_timeout) / 4;
3309
            } else
3310
            #endif /* WOLFSSL_DTLS13 */
3311
                dtls_timeout = 1000 * dtls_timeout;
3312
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
3313
            if (err != NET_SOCK_ERR_NONE) {
3314
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
3315
            }
3316
        }
3317
    }
3318
    #endif /* WOLFSSL_DTLS */
3319
3320
    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
3321
    if (ret < 0) {
3322
        WOLFSSL_MSG("Embed Receive error");
3323
3324
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
3325
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
3326
            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
3327
                WOLFSSL_MSG("\tWould block");
3328
                return WOLFSSL_CBIO_ERR_WANT_READ;
3329
            }
3330
            else {
3331
                WOLFSSL_MSG("\tSocket timeout");
3332
                return WOLFSSL_CBIO_ERR_TIMEOUT;
3333
            }
3334
3335
        } else if (err == NET_SOCK_ERR_CLOSED) {
3336
            WOLFSSL_MSG("Embed receive connection closed");
3337
            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
3338
3339
        } else {
3340
            WOLFSSL_MSG("\tGeneral error");
3341
            return WOLFSSL_CBIO_ERR_GENERAL;
3342
        }
3343
    }
3344
3345
    return ret;
3346
}
3347
3348
/* The Micrium uTCP/IP receivefrom callback
3349
 *  return : nb bytes read, or error
3350
 */
3351
int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3352
{
3353
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
3354
    NET_SOCK_ID       sd = dtlsCtx->rfd;
3355
    NET_SOCK_ADDR     peer;
3356
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
3357
    NET_SOCK_RTN_CODE ret;
3358
    NET_ERR err;
3359
3360
    WOLFSSL_ENTER("MicriumReceiveFrom");
3361
3362
#ifdef WOLFSSL_DTLS
3363
    {
3364
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
3365
        /* Don't use ssl->options.handShakeDone since it is true even if
3366
         * we are in the process of renegotiation */
3367
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
3368
3369
        #ifdef WOLFSSL_DTLS13
3370
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
3371
            doDtlsTimeout =
3372
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
3373
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
3374
        }
3375
        #endif /* WOLFSSL_DTLS13 */
3376
3377
        if (!doDtlsTimeout)
3378
            dtls_timeout = 0;
3379
3380
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
3381
            /* needs timeout in milliseconds */
3382
            #ifdef WOLFSSL_DTLS13
3383
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
3384
                IsAtLeastTLSv1_3(ssl->version)) {
3385
                dtls_timeout = (1000 * dtls_timeout) / 4;
3386
            } else
3387
            #endif /* WOLFSSL_DTLS13 */
3388
                dtls_timeout = 1000 * dtls_timeout;
3389
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
3390
            if (err != NET_SOCK_ERR_NONE) {
3391
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
3392
            }
3393
        }
3394
    }
3395
#endif /* WOLFSSL_DTLS */
3396
3397
    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
3398
                             0, 0, 0, &err);
3399
    if (ret < 0) {
3400
        WOLFSSL_MSG("Embed Receive From error");
3401
3402
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
3403
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
3404
            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
3405
                WOLFSSL_MSG("\tWould block");
3406
                return WOLFSSL_CBIO_ERR_WANT_READ;
3407
            }
3408
            else {
3409
                WOLFSSL_MSG("\tSocket timeout");
3410
                return WOLFSSL_CBIO_ERR_TIMEOUT;
3411
            }
3412
        } else {
3413
            WOLFSSL_MSG("\tGeneral error");
3414
            return WOLFSSL_CBIO_ERR_GENERAL;
3415
        }
3416
    }
3417
    else {
3418
        if (dtlsCtx->peer.sz > 0) {
3419
            NET_SOCK_ADDR_LEN expectedPeerSz =
3420
                (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz;
3421
            if (dtlsCtx->peer.sa == NULL ||
3422
                peerSz != expectedPeerSz ||
3423
                XMEMCMP(&peer, dtlsCtx->peer.sa, expectedPeerSz) != 0) {
3424
                WOLFSSL_MSG("\tIgnored packet from invalid peer");
3425
                return WOLFSSL_CBIO_ERR_WANT_READ;
3426
            }
3427
        }
3428
    }
3429
3430
    return ret;
3431
}
3432
3433
/* The Micrium uTCP/IP sendto callback
3434
 *  return : nb bytes sent, or error
3435
 */
3436
int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
3437
{
3438
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
3439
    NET_SOCK_ID sd = dtlsCtx->wfd;
3440
    NET_SOCK_RTN_CODE ret;
3441
    NET_ERR err;
3442
3443
    WOLFSSL_ENTER("MicriumSendTo");
3444
3445
    ret = NetSock_TxDataTo(sd, buf, sz, ssl->wflags,
3446
                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
3447
                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
3448
                           &err);
3449
    if (err < 0) {
3450
        WOLFSSL_MSG("Embed Send To error");
3451
3452
        if (err == NET_ERR_TX) {
3453
            WOLFSSL_MSG("\tWould block");
3454
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
3455
3456
        } else {
3457
            WOLFSSL_MSG("\tGeneral error");
3458
            return WOLFSSL_CBIO_ERR_GENERAL;
3459
        }
3460
    }
3461
3462
    return ret;
3463
}
3464
3465
/* Micrium DTLS Generate Cookie callback
3466
 *  return : number of bytes copied into buf, or error
3467
 */
3468
#if defined(NO_SHA) && !defined(NO_SHA256)
3469
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3470
#elif !defined(NO_SHA)
3471
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3472
#else
3473
    #error Must enable either SHA-1 or SHA256 (or both) for Micrium.
3474
#endif
3475
int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
3476
{
3477
    NET_SOCK_ADDR peer;
3478
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
3479
    byte digest[MICRIUM_COOKIE_DIGEST_SIZE];
3480
    int  ret = 0;
3481
3482
    (void)ctx;
3483
3484
    XMEMSET(&peer, 0, sizeof(peer));
3485
    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
3486
                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
3487
        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
3488
        return GEN_COOKIE_E;
3489
    }
3490
3491
#if defined(NO_SHA) && !defined(NO_SHA256)
3492
    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
3493
#else
3494
    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
3495
#endif
3496
    if (ret != 0)
3497
        return ret;
3498
3499
    if (sz > MICRIUM_COOKIE_DIGEST_SIZE)
3500
        sz = MICRIUM_COOKIE_DIGEST_SIZE;
3501
    XMEMCPY(buf, digest, sz);
3502
3503
    return sz;
3504
}
3505
3506
#endif /* MICRIUM */
3507
3508
#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
3509
3510
#include <os/os_error.h>
3511
#include <os/os_mbuf.h>
3512
#include <os/os_mempool.h>
3513
3514
#define MB_NAME "wolfssl_mb"
3515
3516
typedef struct Mynewt_Ctx {
3517
        struct mn_socket *mnSocket;          /* send/recv socket handler */
3518
        struct mn_sockaddr_in mnSockAddrIn;  /* socket address */
3519
        struct os_mbuf *mnPacket;            /* incoming packet handle
3520
                                                for short reads */
3521
        int reading;                         /* reading flag */
3522
3523
        /* private */
3524
        void *mnMemBuffer;                   /* memory buffer for mempool */
3525
        struct os_mempool mnMempool;         /* mempool */
3526
        struct os_mbuf_pool mnMbufpool;      /* mbuf pool */
3527
} Mynewt_Ctx;
3528
3529
void mynewt_ctx_clear(void *ctx) {
3530
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3531
    if(!mynewt_ctx) return;
3532
3533
    if(mynewt_ctx->mnPacket) {
3534
        os_mbuf_free_chain(mynewt_ctx->mnPacket);
3535
        mynewt_ctx->mnPacket = NULL;
3536
    }
3537
    os_mempool_clear(&mynewt_ctx->mnMempool);
3538
    XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
3539
    XFREE(mynewt_ctx, 0, 0);
3540
}
3541
3542
/* return Mynewt_Ctx instance */
3543
void* mynewt_ctx_new() {
3544
    int rc = 0;
3545
    Mynewt_Ctx *mynewt_ctx;
3546
    int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
3547
    int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
3548
    int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
3549
3550
    mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
3551
                                       NULL, DYNAMIC_TYPE_TMP_BUFFER);
3552
    if(!mynewt_ctx) return NULL;
3553
3554
    XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
3555
    mynewt_ctx->mnMemBuffer = (void *)XMALLOC(mempool_bytes, 0, 0);
3556
    if(!mynewt_ctx->mnMemBuffer) {
3557
        mynewt_ctx_clear((void*)mynewt_ctx);
3558
        return NULL;
3559
    }
3560
3561
    rc = os_mempool_init(&mynewt_ctx->mnMempool,
3562
                         mem_buf_count, mem_buf_size,
3563
                         mynewt_ctx->mnMemBuffer, MB_NAME);
3564
    if(rc != 0) {
3565
        mynewt_ctx_clear((void*)mynewt_ctx);
3566
        return NULL;
3567
    }
3568
    rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
3569
                           mem_buf_count, mem_buf_size);
3570
    if(rc != 0) {
3571
        mynewt_ctx_clear((void*)mynewt_ctx);
3572
        return NULL;
3573
    }
3574
3575
    return mynewt_ctx;
3576
}
3577
3578
static void mynewt_sock_writable(void *arg, int err);
3579
static void mynewt_sock_readable(void *arg, int err);
3580
static const union mn_socket_cb mynewt_sock_cbs = {
3581
    .socket.writable = mynewt_sock_writable,
3582
    .socket.readable = mynewt_sock_readable,
3583
};
3584
static void mynewt_sock_writable(void *arg, int err)
3585
{
3586
    /* do nothing */
3587
}
3588
static void mynewt_sock_readable(void *arg, int err)
3589
{
3590
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
3591
    if (err && mynewt_ctx->reading) {
3592
        mynewt_ctx->reading = 0;
3593
    }
3594
}
3595
3596
/* The Mynewt receive callback
3597
 *  return :  bytes read, or error
3598
 */
3599
int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3600
{
3601
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3602
    int rc = 0;
3603
    struct mn_sockaddr_in from;
3604
    struct os_mbuf *m;
3605
    int read_sz = 0;
3606
    word16 total;
3607
3608
    if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
3609
        WOLFSSL_MSG("Mynewt Recv NULL parameters");
3610
        return WOLFSSL_CBIO_ERR_GENERAL;
3611
    }
3612
3613
    if(mynewt_ctx->mnPacket == NULL) {
3614
        mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
3615
        if(mynewt_ctx->mnPacket == NULL) {
3616
            return MEMORY_E;
3617
        }
3618
3619
        mynewt_ctx->reading = 1;
3620
        while(mynewt_ctx->reading && rc == 0) {
3621
            rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
3622
            if(rc == MN_ECONNABORTED) {
3623
                rc = 0;
3624
                mynewt_ctx->reading = 0;
3625
                break;
3626
            }
3627
            if (!(rc == 0 || rc == MN_EAGAIN)) {
3628
                WOLFSSL_MSG("Mynewt Recv receive error");
3629
                mynewt_ctx->reading = 0;
3630
                break;
3631
            }
3632
            if(rc == 0) {
3633
                int len = OS_MBUF_PKTLEN(m);
3634
                if(len == 0) {
3635
                    break;
3636
                }
3637
                rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
3638
                if(rc != 0) {
3639
                    WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
3640
                    break;
3641
                }
3642
                os_mbuf_free_chain(m);
3643
                m = NULL;
3644
            } else if(rc == MN_EAGAIN) {
3645
                /* continue to until reading all of packet data. */
3646
                rc = 0;
3647
                break;
3648
            }
3649
        }
3650
        if(rc != 0) {
3651
            mynewt_ctx->reading = 0;
3652
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
3653
            mynewt_ctx->mnPacket = NULL;
3654
            return rc;
3655
        }
3656
    }
3657
3658
    if(mynewt_ctx->mnPacket) {
3659
        total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
3660
        read_sz = (total >= sz)? sz : total;
3661
3662
        os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
3663
        os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
3664
3665
        if (read_sz == total) {
3666
            WOLFSSL_MSG("Mynewt Recv Drained packet");
3667
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
3668
            mynewt_ctx->mnPacket = NULL;
3669
        }
3670
    }
3671
3672
    return read_sz;
3673
}
3674
3675
/* The Mynewt send callback
3676
 *  return : bytes sent, or error
3677
 */
3678
int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
3679
{
3680
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3681
    int rc = 0;
3682
    struct os_mbuf *m;
3683
    int write_sz = 0;
3684
    m = os_msys_get_pkthdr(sz, 0);
3685
    if (!m) {
3686
        WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
3687
        return WOLFSSL_CBIO_ERR_GENERAL;
3688
    }
3689
    rc = os_mbuf_copyinto(m, 0, buf, sz);
3690
    if (rc != 0) {
3691
        WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
3692
        os_mbuf_free_chain(m);
3693
        return rc;
3694
    }
3695
    rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
3696
    if(rc != 0) {
3697
        WOLFSSL_MSG("Mynewt Send mn_sendto error");
3698
        os_mbuf_free_chain(m);
3699
        return rc;
3700
    }
3701
    write_sz = sz;
3702
    return write_sz;
3703
}
3704
3705
/* like set_fd, but for default NetX context */
3706
void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
3707
{
3708
    if (ssl && ssl->mnCtx) {
3709
        Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
3710
        mynewt_ctx->mnSocket = mnSocket;
3711
        XMEMCPY(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
3712
        mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
3713
    }
3714
}
3715
3716
#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
3717
3718
#ifdef WOLFSSL_UIP
3719
#include <uip.h>
3720
#include <stdio.h>
3721
3722
/* uIP TCP/IP port, using the native tcp/udp socket api.
3723
 * TCP and UDP are currently supported with the callbacks below.
3724
 *
3725
 */
3726
/* The uIP tcp send callback
3727
 * return : bytes sent, or error
3728
 */
3729
int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3730
{
3731
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3732
    int total_written = 0;
3733
    (void)ssl;
3734
    do {
3735
        int ret;
3736
        unsigned int bytes_left = sz - total_written;
3737
        unsigned int max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
3738
        if (bytes_left > max_sendlen) {
3739
            fprintf(stderr, "uIPSend: Send limited by buffer\r\n");
3740
            bytes_left = max_sendlen;
3741
        }
3742
        if (bytes_left == 0) {
3743
            fprintf(stderr, "uIPSend: Buffer full!\r\n");
3744
            break;
3745
        }
3746
        ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
3747
        if (ret <= 0)
3748
            break;
3749
        total_written += ret;
3750
    } while(total_written < sz);
3751
    if (total_written == 0)
3752
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3753
    return total_written;
3754
}
3755
3756
int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3757
{
3758
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3759
    int ret = 0;
3760
    (void)ssl;
3761
    ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
3762
    if (ret == 0)
3763
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3764
    return ret;
3765
}
3766
3767
/* The uIP uTCP/IP receive callback
3768
 *  return : nb bytes read, or error
3769
 */
3770
int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3771
{
3772
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3773
    if (!ctx || !ctx->ssl_rx_databuf)
3774
        return WOLFSSL_FATAL_ERROR;
3775
    (void)ssl;
3776
    if (ctx->ssl_rb_len > 0) {
3777
        if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
3778
            sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
3779
        XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
3780
        ctx->ssl_rb_off += sz;
3781
        if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
3782
            ctx->ssl_rb_len = 0;
3783
            ctx->ssl_rb_off = 0;
3784
        }
3785
        return sz;
3786
    } else {
3787
        return WOLFSSL_CBIO_ERR_WANT_READ;
3788
    }
3789
}
3790
3791
/* uIP DTLS Generate Cookie callback
3792
 *  return : number of bytes copied into buf, or error
3793
 */
3794
#if defined(NO_SHA) && !defined(NO_SHA256)
3795
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3796
#elif !defined(NO_SHA)
3797
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3798
#else
3799
    #error Must enable either SHA-1 or SHA256 (or both) for uIP.
3800
#endif
3801
int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3802
{
3803
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3804
    byte token[32];
3805
    byte digest[UIP_COOKIE_DIGEST_SIZE];
3806
    int  ret = 0;
3807
    XMEMSET(token, 0, sizeof(token));
3808
    XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
3809
    XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
3810
#if defined(NO_SHA) && !defined(NO_SHA256)
3811
    ret = wc_Sha256Hash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3812
#else
3813
    ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3814
#endif
3815
    if (ret != 0)
3816
        return ret;
3817
    if (sz > UIP_COOKIE_DIGEST_SIZE)
3818
        sz = UIP_COOKIE_DIGEST_SIZE;
3819
    XMEMCPY(buf, digest, sz);
3820
    return sz;
3821
}
3822
3823
#endif /* WOLFSSL_UIP */
3824
3825
#ifdef WOLFSSL_GNRC
3826
3827
#include <net/sock.h>
3828
#include <net/sock/tcp.h>
3829
#include <stdio.h>
3830
3831
/* GNRC TCP/IP port, using the native tcp/udp socket api.
3832
 * TCP and UDP are currently supported with the callbacks below.
3833
 *
3834
 */
3835
/* The GNRC tcp send callback
3836
 * return : bytes sent, or error
3837
 */
3838
3839
int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3840
{
3841
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3842
    int ret = 0;
3843
    (void)ssl;
3844
    if (!ctx)
3845
        return WOLFSSL_CBIO_ERR_GENERAL;
3846
    ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr);
3847
    if (ret == 0)
3848
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3849
    return ret;
3850
}
3851
3852
/* The GNRC TCP/IP receive callback
3853
 *  return : nb bytes read, or error
3854
 */
3855
int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3856
{
3857
    sock_udp_ep_t ep;
3858
    int ret;
3859
    word32 timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000;
3860
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3861
    if (!ctx)
3862
        return WOLFSSL_CBIO_ERR_GENERAL;
3863
    (void)ssl;
3864
    if (wolfSSL_get_using_nonblock(ctx->ssl)) {
3865
        timeout = 0;
3866
    }
3867
    ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep);
3868
    if (ret > 0) {
3869
        if (ctx->peer_addr.port == 0)
3870
            XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t));
3871
    }
3872
    if (ret == -ETIMEDOUT) {
3873
        return WOLFSSL_CBIO_ERR_WANT_READ;
3874
    }
3875
    return ret;
3876
}
3877
3878
/* GNRC DTLS Generate Cookie callback
3879
 *  return : number of bytes copied into buf, or error
3880
 */
3881
#define GNRC_MAX_TOKEN_SIZE (32)
3882
#if defined(NO_SHA) && !defined(NO_SHA256)
3883
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3884
#elif !defined(NO_SHA)
3885
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3886
#else
3887
    #error Must enable either SHA-1 or SHA256 (or both) for GNRC.
3888
#endif
3889
int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3890
{
3891
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3892
    if (!ctx)
3893
        return WOLFSSL_CBIO_ERR_GENERAL;
3894
    byte token[GNRC_MAX_TOKEN_SIZE];
3895
    byte digest[GNRC_COOKIE_DIGEST_SIZE];
3896
    int  ret = 0;
3897
    size_t token_size = sizeof(sock_udp_ep_t);
3898
    (void)ssl;
3899
    if (token_size > GNRC_MAX_TOKEN_SIZE)
3900
        token_size = GNRC_MAX_TOKEN_SIZE;
3901
    XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE);
3902
    XMEMCPY(token, &ctx->peer_addr, token_size);
3903
#if defined(NO_SHA) && !defined(NO_SHA256)
3904
    ret = wc_Sha256Hash(token, token_size, digest);
3905
#else
3906
    ret = wc_ShaHash(token, token_size, digest);
3907
#endif
3908
    if (ret != 0)
3909
        return ret;
3910
    if (sz > GNRC_COOKIE_DIGEST_SIZE)
3911
        sz = GNRC_COOKIE_DIGEST_SIZE;
3912
    XMEMCPY(buf, digest, sz);
3913
    return sz;
3914
}
3915
3916
#endif /* WOLFSSL_GNRC */
3917
3918
#ifdef WOLFSSL_LWIP_NATIVE
3919
int LwIPNativeSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3920
{
3921
    err_t ret;
3922
    WOLFSSL_LWIP_NATIVE_STATE* nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3923
3924
    if (sz < 0 || sz > (int)WOLFSSL_MAX_16BIT) {
3925
        return BAD_FUNC_ARG;
3926
    }
3927
3928
    ret = tcp_write(nlwip->pcb, buf, (u16_t)sz, TCP_WRITE_FLAG_COPY);
3929
    if (ret != ERR_OK) {
3930
        sz = WOLFSSL_FATAL_ERROR;
3931
    }
3932
3933
    return sz;
3934
}
3935
3936
3937
int LwIPNativeReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3938
{
3939
    struct pbuf *current, *head;
3940
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3941
    int ret = 0;
3942
3943
    if (ctx == NULL) {
3944
        return WOLFSSL_CBIO_ERR_GENERAL;
3945
    }
3946
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3947
3948
    current = nlwip->pbuf;
3949
    if (current == NULL || sz > current->tot_len) {
3950
        WOLFSSL_MSG("LwIP native pbuf list is null or not enough data, want read");
3951
        ret = WOLFSSL_CBIO_ERR_WANT_READ;
3952
    }
3953
    else {
3954
        int read = 0; /* total amount read */
3955
        head = nlwip->pbuf; /* save pointer to current head */
3956
3957
        /* loop through buffers reading data */
3958
        while (current != NULL) {
3959
            int len; /* current amount to be read */
3960
3961
            len = (current->len - nlwip->pulled < sz) ?
3962
                                            (current->len - nlwip->pulled) : sz;
3963
3964
            if (read + len > sz) {
3965
                /* should never be hit but have sanity check before use */
3966
                return WOLFSSL_CBIO_ERR_GENERAL;
3967
            }
3968
3969
            /* check if is a partial read from before */
3970
            XMEMCPY(&buf[read],
3971
                   (const char *)&(((char *)(current->payload))[nlwip->pulled]),
3972
3973
                    len);
3974
            nlwip->pulled = nlwip->pulled + len;
3975
            if (nlwip->pulled >= current->len) {
3976
                WOLFSSL_MSG("Native LwIP read full pbuf");
3977
                nlwip->pbuf = current->next;
3978
                current = nlwip->pbuf;
3979
                nlwip->pulled = 0;
3980
            }
3981
            read = read + len;
3982
            ret  = read;
3983
3984
            /* read enough break out */
3985
            if (read >= sz) {
3986
                /* if more pbuf's are left in the chain then increment the
3987
                 * ref count for next in chain and free all from beginning till
3988
                 * next */
3989
                if (current != NULL) {
3990
                    pbuf_ref(current);
3991
                }
3992
3993
                /* ack and start free'ing from the current head of the chain */
3994
                pbuf_free(head);
3995
                break;
3996
            }
3997
        }
3998
    }
3999
    WOLFSSL_LEAVE("LwIPNativeReceive", ret);
4000
    return ret;
4001
}
4002
4003
4004
static err_t LwIPNativeReceiveCB(void* cb, struct tcp_pcb* pcb,
4005
                                struct pbuf* pbuf, err_t err)
4006
{
4007
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
4008
4009
    if (cb == NULL || pcb == NULL) {
4010
        WOLFSSL_MSG("Expected callback was null, abort");
4011
        return ERR_ABRT;
4012
    }
4013
4014
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
4015
    if (pbuf == NULL && err == ERR_OK) {
4016
        return ERR_OK;
4017
    }
4018
4019
    if (nlwip->pbuf == NULL) {
4020
        nlwip->pbuf = pbuf;
4021
    }
4022
    else {
4023
        if (nlwip->pbuf != pbuf) {
4024
            tcp_recved(nlwip->pcb, pbuf->tot_len);
4025
            pbuf_cat(nlwip->pbuf, pbuf); /* add chain to head */
4026
        }
4027
    }
4028
4029
    if (nlwip->recv_fn) {
4030
        return nlwip->recv_fn(nlwip->arg, pcb, pbuf, err);
4031
    }
4032
4033
    WOLFSSL_LEAVE("LwIPNativeReceiveCB", nlwip->pbuf->tot_len);
4034
    return ERR_OK;
4035
}
4036
4037
4038
static err_t LwIPNativeSentCB(void* cb, struct tcp_pcb* pcb, u16_t len)
4039
{
4040
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
4041
4042
    if (cb == NULL || pcb == NULL) {
4043
        WOLFSSL_MSG("Expected callback was null, abort");
4044
        return ERR_ABRT;
4045
    }
4046
4047
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
4048
    if (nlwip->sent_fn) {
4049
        return nlwip->sent_fn(nlwip->arg, pcb, len);
4050
    }
4051
    return ERR_OK;
4052
}
4053
4054
4055
int wolfSSL_SetIO_LwIP(WOLFSSL* ssl, void* pcb,
4056
                          tcp_recv_fn recv_fn, tcp_sent_fn sent_fn, void *arg)
4057
{
4058
    if (ssl == NULL || pcb == NULL)
4059
        return BAD_FUNC_ARG;
4060
4061
    ssl->lwipCtx.pcb = (struct tcp_pcb *)pcb;
4062
    ssl->lwipCtx.recv_fn = recv_fn; /*  recv user callback */
4063
    ssl->lwipCtx.sent_fn = sent_fn; /*  sent user callback */
4064
    ssl->lwipCtx.arg  = arg;
4065
    ssl->lwipCtx.pbuf = 0;
4066
    ssl->lwipCtx.pulled = 0;
4067
    ssl->lwipCtx.wait   = 0;
4068
4069
    /* wolfSSL_LwIP_recv/sent_cb invokes recv/sent user callback in them. */
4070
    tcp_recv(pcb, LwIPNativeReceiveCB);
4071
    tcp_sent(pcb, LwIPNativeSentCB);
4072
    tcp_arg (pcb, (void *)&ssl->lwipCtx);
4073
    wolfSSL_SetIOReadCtx(ssl, &ssl->lwipCtx);
4074
    wolfSSL_SetIOWriteCtx(ssl, &ssl->lwipCtx);
4075
4076
    return ERR_OK;
4077
}
4078
#endif /* WOLFSSL_LWIP_NATIVE */
4079
4080
#ifdef WOLFSSL_ISOTP
4081
static int isotp_send_single_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
4082
        word16 length)
4083
{
4084
    /* Length will be at most 7 bytes to get here. Packet is length and type
4085
     * for the first byte, then up to 7 bytes of data */
4086
    ctx->frame.data[0] = ((byte)length) | (ISOTP_FRAME_TYPE_SINGLE << 4);
4087
    XMEMCPY(&ctx->frame.data[1], buf, length);
4088
    ctx->frame.length = length + 1;
4089
    return ctx->send_fn(&ctx->frame, ctx->arg);
4090
}
4091
4092
static int isotp_send_flow_control(struct isotp_wolfssl_ctx *ctx,
4093
        byte overflow)
4094
{
4095
    int ret;
4096
    /* Overflow is set it if we have been asked to receive more data than the
4097
     * user allocated a buffer for */
4098
    if (overflow) {
4099
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_ABORT |
4100
            (ISOTP_FRAME_TYPE_CONTROL << 4);
4101
    } else {
4102
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_CTS |
4103
            (ISOTP_FRAME_TYPE_CONTROL << 4);
4104
    }
4105
    /* Set the number of frames between flow control to infinite */
4106
    ctx->frame.data[1] = ISOTP_FLOW_CONTROL_FRAMES;
4107
    /* User specified frame delay */
4108
    ctx->frame.data[2] = ctx->receive_delay;
4109
    ctx->frame.length = ISOTP_FLOW_CONTROL_PACKET_SIZE;
4110
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
4111
    return ret;
4112
}
4113
4114
static int isotp_receive_flow_control(struct isotp_wolfssl_ctx *ctx)
4115
{
4116
    int ret;
4117
    enum isotp_frame_type type;
4118
    enum isotp_flow_control flow_control;
4119
    ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT);
4120
    if (ret == 0) {
4121
        return WOLFSSL_CBIO_ERR_TIMEOUT;
4122
    } else if (ret < 0) {
4123
        WOLFSSL_MSG("ISO-TP error receiving flow control packet");
4124
        return WOLFSSL_CBIO_ERR_GENERAL;
4125
    }
4126
    /* Flow control is the frame type and flow response for the first byte,
4127
     * number of frames until the next flow control packet for the second
4128
     * byte, time between frames for the third byte */
4129
    type = ctx->frame.data[0] >> 4;
4130
4131
    if (type != ISOTP_FRAME_TYPE_CONTROL) {
4132
        WOLFSSL_MSG("ISO-TP frames out of sequence");
4133
        return WOLFSSL_CBIO_ERR_GENERAL;
4134
    }
4135
4136
    flow_control = ctx->frame.data[0] & 0xf;
4137
4138
    ctx->flow_counter = 0;
4139
    ctx->flow_packets = ctx->frame.data[1];
4140
    ctx->frame_delay = ctx->frame.data[2];
4141
4142
    return flow_control;
4143
}
4144
4145
static int isotp_send_consecutive_frame(struct isotp_wolfssl_ctx *ctx)
4146
{
4147
    /* Sequence is 0 - 15 and then starts again, the first frame has an
4148
     * implied sequence of '0' */
4149
    ctx->sequence += 1;
4150
    if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
4151
        ctx->sequence = 0;
4152
    }
4153
    ctx->flow_counter++;
4154
    /* First byte it type and sequence number, up to 7 bytes of data */
4155
    ctx->frame.data[0] = ctx->sequence | (ISOTP_FRAME_TYPE_CONSECUTIVE << 4);
4156
    if (ctx->buf_length > ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE) {
4157
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr,
4158
                ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE);
4159
        ctx->buf_ptr += ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
4160
        ctx->buf_length -= ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
4161
        ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
4162
    } else {
4163
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr, ctx->buf_length);
4164
        ctx->frame.length = ctx->buf_length + 1;
4165
        ctx->buf_length = 0;
4166
    }
4167
    return ctx->send_fn(&ctx->frame, ctx->arg);
4168
4169
}
4170
4171
static int isotp_send_first_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
4172
        word16 length)
4173
{
4174
    int ret;
4175
    ctx->sequence = 0;
4176
    /* Set to 1 to trigger a flow control straight away, the flow control
4177
     * packet will set these properly */
4178
    ctx->flow_packets = ctx->flow_counter = 1;
4179
    /* First frame has 1 nibble for type, 3 nibbles for length followed by
4180
     * 6 bytes for data*/
4181
    ctx->frame.data[0] = (length >> 8) | (ISOTP_FRAME_TYPE_FIRST << 4);
4182
    ctx->frame.data[1] = length & 0xff;
4183
    XMEMCPY(&ctx->frame.data[2], buf, ISOTP_FIRST_FRAME_DATA_SIZE);
4184
    ctx->buf_ptr = buf + ISOTP_FIRST_FRAME_DATA_SIZE;
4185
    ctx->buf_length = length - ISOTP_FIRST_FRAME_DATA_SIZE;
4186
    ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
4187
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
4188
    if (ret <= 0) {
4189
        WOLFSSL_MSG("ISO-TP error sending first frame");
4190
        return WOLFSSL_CBIO_ERR_GENERAL;
4191
    }
4192
    while(ctx->buf_length) {
4193
        /* The receiver can set how often to get a flow control packet. If it
4194
         * is time, then get the packet. Note that this will always happen
4195
         * after the first packet */
4196
        if ((ctx->flow_packets > 0) &&
4197
                (ctx->flow_counter == ctx->flow_packets)) {
4198
            ret = isotp_receive_flow_control(ctx);
4199
        }
4200
        /* Frame delay <= 0x7f is in ms, 0xfX is X * 100 us */
4201
        if (ctx->frame_delay) {
4202
            if (ctx->frame_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
4203
                ctx->delay_fn(ctx->frame_delay * 1000);
4204
            } else {
4205
                ctx->delay_fn((ctx->frame_delay & 0xf) * 100);
4206
            }
4207
        }
4208
        switch (ret) {
4209
            /* Clear to send */
4210
            case ISOTP_FLOW_CONTROL_CTS:
4211
                if (isotp_send_consecutive_frame(ctx) < 0) {
4212
                    WOLFSSL_MSG("ISO-TP error sending consecutive frame");
4213
                    return WOLFSSL_CBIO_ERR_GENERAL;
4214
                }
4215
                break;
4216
            /* Receiver says "WAIT", so we wait for another flow control
4217
             * packet, or abort if we have waited too long */
4218
            case ISOTP_FLOW_CONTROL_WAIT:
4219
                ctx->wait_counter += 1;
4220
                if (ctx->wait_counter > ISOTP_DEFAULT_WAIT_COUNT) {
4221
                    WOLFSSL_MSG("ISO-TP receiver told us to wait too many"
4222
                            " times");
4223
                    return WOLFSSL_CBIO_ERR_WANT_WRITE;
4224
                }
4225
                break;
4226
            /* Receiver is not ready to receive packet, so abort */
4227
            case ISOTP_FLOW_CONTROL_ABORT:
4228
                WOLFSSL_MSG("ISO-TP receiver aborted transmission");
4229
                return WOLFSSL_CBIO_ERR_WANT_WRITE;
4230
            default:
4231
                WOLFSSL_MSG("ISO-TP got unexpected flow control packet");
4232
                return WOLFSSL_CBIO_ERR_GENERAL;
4233
        }
4234
    }
4235
    return 0;
4236
}
4237
4238
int ISOTP_Send(WOLFSSL* ssl, char* buf, int sz, void* ctx)
4239
{
4240
    int ret;
4241
    struct isotp_wolfssl_ctx *isotp_ctx;
4242
    (void) ssl;
4243
4244
    if (!ctx) {
4245
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
4246
        return WOLFSSL_CBIO_ERR_GENERAL;
4247
    }
4248
    isotp_ctx = (struct isotp_wolfssl_ctx*) ctx;
4249
4250
    /* ISO-TP cannot send more than 4095 bytes, this limits the packet size
4251
     * and wolfSSL will try again with the remaining data */
4252
    if (sz > ISOTP_MAX_DATA_SIZE) {
4253
        sz = ISOTP_MAX_DATA_SIZE;
4254
    }
4255
    /* Can't send whilst we are receiving */
4256
    if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
4257
        return WOLFSSL_ERROR_WANT_WRITE;
4258
    }
4259
    isotp_ctx->state = ISOTP_CONN_STATE_SENDING;
4260
4261
    /* Assuming normal addressing */
4262
    if (sz <= ISOTP_SINGLE_FRAME_DATA_SIZE) {
4263
        ret = isotp_send_single_frame(isotp_ctx, buf, (word16)sz);
4264
    } else {
4265
        ret = isotp_send_first_frame(isotp_ctx, buf, (word16)sz);
4266
    }
4267
    isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4268
4269
    if (ret == 0) {
4270
        return sz;
4271
    }
4272
    return ret;
4273
}
4274
4275
static int isotp_receive_single_frame(struct isotp_wolfssl_ctx *ctx)
4276
{
4277
    byte data_size;
4278
4279
    /* 1 nibble for data size which will be 1 - 7 in a regular 8 byte CAN
4280
     * packet */
4281
    data_size = (byte)ctx->frame.data[0] & 0xf;
4282
    if (data_size > ISOTP_SINGLE_FRAME_DATA_SIZE) {
4283
        WOLFSSL_MSG("Data size is too large for ISO-TP single frame");
4284
        return WOLFSSL_CBIO_ERR_GENERAL;
4285
    }
4286
    if (ctx->receive_buffer_size < (int)data_size) {
4287
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
4288
        return BUFFER_E;
4289
    }
4290
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[1], data_size);
4291
    return data_size;
4292
}
4293
4294
static int isotp_receive_multi_frame(struct isotp_wolfssl_ctx *ctx)
4295
{
4296
    int ret;
4297
    word16 data_size;
4298
    byte delay = 0;
4299
4300
    /* Increase receive timeout for enforced ms delay */
4301
    if (ctx->receive_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
4302
        delay = ctx->receive_delay;
4303
    }
4304
    /* Still processing first frame.
4305
     * Full data size is lower nibble of first byte for the most significant
4306
     * followed by the second byte for the rest. Last 6 bytes are data */
4307
    data_size = ((ctx->frame.data[0] & 0xf) << 8) + ctx->frame.data[1];
4308
    if ((ctx->frame.length != ISOTP_CAN_BUS_PAYLOAD_SIZE) ||
4309
            (data_size <= ISOTP_SINGLE_FRAME_DATA_SIZE)) {
4310
        WOLFSSL_MSG("ISO-TP first frame is malformed");
4311
        return WOLFSSL_CBIO_ERR_GENERAL;
4312
    }
4313
    /* Need to send a flow control packet to either cancel or continue
4314
     * transmission of data */
4315
    if (ctx->receive_buffer_size < data_size) {
4316
        isotp_send_flow_control(ctx, TRUE);
4317
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
4318
        return BUFFER_E;
4319
    }
4320
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[2], ISOTP_FIRST_FRAME_DATA_SIZE);
4321
    isotp_send_flow_control(ctx, FALSE);
4322
4323
    ctx->buf_length = ISOTP_FIRST_FRAME_DATA_SIZE;
4324
    ctx->buf_ptr = ctx->receive_buffer + ISOTP_FIRST_FRAME_DATA_SIZE;
4325
    data_size -= ISOTP_FIRST_FRAME_DATA_SIZE;
4326
    ctx->sequence = 1;
4327
4328
    while(data_size) {
4329
        enum isotp_frame_type type;
4330
        byte sequence;
4331
        byte frame_len;
4332
        ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT +
4333
                (delay / 1000));
4334
        if (ret == 0) {
4335
            return WOLFSSL_CBIO_ERR_TIMEOUT;
4336
        } else if (ret < 0) {
4337
            WOLFSSL_MSG("ISO-TP error receiving consecutive frame");
4338
            return WOLFSSL_CBIO_ERR_GENERAL;
4339
        }
4340
        type = ctx->frame.data[0] >> 4;
4341
        /* Consecutive frames have sequence number as lower nibble */
4342
        sequence = ctx->frame.data[0] & 0xf;
4343
        if (type != ISOTP_FRAME_TYPE_CONSECUTIVE) {
4344
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4345
            return WOLFSSL_CBIO_ERR_GENERAL;
4346
        }
4347
        if (sequence != ctx->sequence) {
4348
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4349
            return WOLFSSL_CBIO_ERR_GENERAL;
4350
        }
4351
        /* A consecutive frame carries the sequence byte and at least one byte
4352
         * of data */
4353
        if ((ctx->frame.length < 2) ||
4354
                (ctx->frame.length > ISOTP_CAN_BUS_PAYLOAD_SIZE)) {
4355
            WOLFSSL_MSG("ISO-TP consecutive frame is malformed");
4356
            return WOLFSSL_CBIO_ERR_GENERAL;
4357
        }
4358
        /* Last 7 bytes or whatever we got after the first byte is data, the
4359
         * final frame can be padded beyond the data we are still owed */
4360
        frame_len = ctx->frame.length - 1;
4361
        if (frame_len > data_size) {
4362
            frame_len = (byte)data_size;
4363
        }
4364
        XMEMCPY(ctx->buf_ptr, &ctx->frame.data[1], frame_len);
4365
        ctx->buf_ptr += frame_len;
4366
        ctx->buf_length += frame_len;
4367
        data_size -= frame_len;
4368
4369
        /* Sequence is 0 - 15 (first 0 is implied for first packet */
4370
        ctx->sequence++;
4371
        if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
4372
            ctx->sequence = 0;
4373
        }
4374
    }
4375
    return ctx->buf_length;
4376
4377
}
4378
4379
/* The wolfSSL receive callback, needs to buffer because we need to grab all
4380
 * incoming data, even if wolfSSL doesn't want it all yet */
4381
int ISOTP_Receive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
4382
{
4383
    enum isotp_frame_type type;
4384
    int ret;
4385
    struct isotp_wolfssl_ctx *isotp_ctx;
4386
    (void) ssl;
4387
4388
    if (!ctx) {
4389
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
4390
        return WOLFSSL_CBIO_ERR_TIMEOUT;
4391
    }
4392
    isotp_ctx = (struct isotp_wolfssl_ctx*)ctx;
4393
4394
    /* Is buffer empty? If so, fill it */
4395
    if (!isotp_ctx->receive_buffer_len) {
4396
        /* Can't send whilst we are receiving */
4397
        if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
4398
            return WOLFSSL_ERROR_WANT_READ;
4399
        }
4400
        isotp_ctx->state = ISOTP_CONN_STATE_RECEIVING;
4401
        /* Each poll waits ISOTP_DEFAULT_TIMEOUT ms, but nothing bounds
4402
         * the wait for a message to start, so keep polling. */
4403
        do {
4404
            ret = isotp_ctx->recv_fn(&isotp_ctx->frame, isotp_ctx->arg,
4405
                    ISOTP_DEFAULT_TIMEOUT);
4406
        } while (ret == 0);
4407
        if (ret < 0) {
4408
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4409
            WOLFSSL_MSG("ISO-TP receive error");
4410
            return WOLFSSL_CBIO_ERR_GENERAL;
4411
        }
4412
4413
        type = (enum isotp_frame_type) isotp_ctx->frame.data[0] >> 4;
4414
4415
        if (type == ISOTP_FRAME_TYPE_SINGLE) {
4416
            isotp_ctx->receive_buffer_len =
4417
                isotp_receive_single_frame(isotp_ctx);
4418
        } else if (type == ISOTP_FRAME_TYPE_FIRST) {
4419
            isotp_ctx->receive_buffer_len =
4420
                isotp_receive_multi_frame(isotp_ctx);
4421
        } else {
4422
            /* Should never get here */
4423
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4424
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4425
            return WOLFSSL_CBIO_ERR_GENERAL;
4426
        }
4427
        if (isotp_ctx->receive_buffer_len <= 1) {
4428
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4429
            return isotp_ctx->receive_buffer_len;
4430
        } else {
4431
            isotp_ctx->receive_buffer_ptr = isotp_ctx->receive_buffer;
4432
        }
4433
        isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4434
    }
4435
4436
    /* Return from the buffer */
4437
    if (isotp_ctx->receive_buffer_len >= sz) {
4438
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr, sz);
4439
        isotp_ctx->receive_buffer_ptr+= sz;
4440
        isotp_ctx->receive_buffer_len-= sz;
4441
        return sz;
4442
    } else {
4443
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr,
4444
                isotp_ctx->receive_buffer_len);
4445
        sz = isotp_ctx->receive_buffer_len;
4446
        isotp_ctx->receive_buffer_len = 0;
4447
        return sz;
4448
    }
4449
}
4450
4451
int wolfSSL_SetIO_ISOTP(WOLFSSL *ssl, isotp_wolfssl_ctx *ctx,
4452
        can_recv_fn recv_fn, can_send_fn send_fn, can_delay_fn delay_fn,
4453
        word32 receive_delay, char *receive_buffer, int receive_buffer_size,
4454
        void *arg)
4455
{
4456
    if (!ctx || !recv_fn || !send_fn || !delay_fn || !receive_buffer) {
4457
        WOLFSSL_MSG("ISO-TP has missing required parameter");
4458
        return WOLFSSL_CBIO_ERR_GENERAL;
4459
    }
4460
    ctx->recv_fn = recv_fn;
4461
    ctx->send_fn = send_fn;
4462
    ctx->arg = arg;
4463
    ctx->delay_fn = delay_fn;
4464
    ctx->frame_delay = 0;
4465
    ctx->receive_buffer = receive_buffer;
4466
    ctx->receive_buffer_size = receive_buffer_size;
4467
    ctx->receive_buffer_len = 0;
4468
    ctx->state = ISOTP_CONN_STATE_IDLE;
4469
4470
    wolfSSL_SetIOReadCtx(ssl, ctx);
4471
    wolfSSL_SetIOWriteCtx(ssl, ctx);
4472
4473
    /* Delay of 100 - 900us is 0xfX where X is value / 100. Delay of
4474
     * >= 1000 is divided by 1000. > 127ms is invalid */
4475
    if (receive_delay < 1000) {
4476
        ctx->receive_delay = 0xf0 + (receive_delay / 100);
4477
    } else if (receive_delay <= ISOTP_MAX_MS_FRAME_DELAY * 1000) {
4478
        ctx->receive_delay = receive_delay / 1000;
4479
    } else {
4480
        WOLFSSL_MSG("ISO-TP delay parameter out of bounds");
4481
        return WOLFSSL_CBIO_ERR_GENERAL;
4482
    }
4483
    return 0;
4484
}
4485
#endif /* WOLFSSL_ISOTP */
4486
#endif /* WOLFCRYPT_ONLY */