Coverage Report

Created: 2026-07-16 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/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 (getsockopt(sfd, SOL_SOCKET, SO_TYPE, (XSOCKOPT_TYPE_OPTVAL_TYPE)&type,
656
            &length) == 0 && type != SOCK_DGRAM) {
657
        return 0;
658
    }
659
    else {
660
        return 1;
661
    }
662
}
663
664
void wolfSSL_SetRecvFrom(WOLFSSL* ssl, WolfSSLRecvFrom recvFrom)
665
{
666
    if (ssl != NULL)
667
        ssl->buffers.dtlsCtx.recvfrom = recvFrom;
668
}
669
670
void wolfSSL_SetSendTo(WOLFSSL* ssl, WolfSSLSento sendTo)
671
{
672
    if (ssl != NULL)
673
        ssl->buffers.dtlsCtx.sendto = sendTo;
674
}
675
676
/* The receive embedded callback
677
 *  return : nb bytes read, or error
678
 */
679
int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
680
{
681
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
682
    int recvd;
683
    int sd = dtlsCtx->rfd;
684
    int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
685
    byte doDtlsTimeout;
686
    SOCKADDR_S lclPeer;
687
    SOCKADDR_S* peer;
688
    XSOCKLENT peerSz = 0;
689
#ifndef NO_ASN_TIME
690
    word32 start = 0;
691
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
692
    word32 invalidPeerPackets = 0;
693
#endif
694
    int newPeer = 0;
695
    int ret = 0;
696
697
    WOLFSSL_ENTER("EmbedReceiveFrom");
698
    (void)ret; /* possibly unused */
699
700
    if (sz < 0)
701
        return WOLFSSL_CBIO_ERR_GENERAL;
702
703
    XMEMSET(&lclPeer, 0, sizeof(lclPeer));
704
705
#ifdef WOLFSSL_RW_THREADED
706
    if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
707
        return WOLFSSL_CBIO_ERR_GENERAL;
708
#endif
709
710
    if (dtlsCtx->connected) {
711
        peer = NULL;
712
    }
713
    else if (dtlsCtx->userSet) {
714
#ifndef WOLFSSL_IPV6
715
        if (PeerIsIpv6((SOCKADDR_S*)dtlsCtx->peer.sa, dtlsCtx->peer.sz)) {
716
            WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
717
            ret = WOLFSSL_CBIO_ERR_GENERAL;
718
        }
719
#endif
720
        peer = &lclPeer;
721
        peerSz = sizeof(lclPeer);
722
    }
723
    else {
724
        /* Store the peer address. It is used to calculate the DTLS cookie. */
725
        newPeer = dtlsCtx->peer.sa == NULL || !ssl->options.dtlsStateful;
726
        peer = &lclPeer;
727
        peerSz = sizeof(lclPeer);
728
    }
729
730
#ifdef WOLFSSL_RW_THREADED
731
    /* We make a copy above to avoid holding the lock for the entire function */
732
    if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
733
        return WOLFSSL_CBIO_ERR_GENERAL;
734
#endif
735
736
    if (ret != 0)
737
        return ret;
738
739
    /* Don't use ssl->options.handShakeDone since it is true even if
740
     * we are in the process of renegotiation */
741
    doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
742
743
#ifdef WOLFSSL_DTLS13
744
    if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
745
        doDtlsTimeout = doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL;
746
#ifdef WOLFSSL_RW_THREADED
747
        ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
748
        if (ret != 0)
749
            return ret;
750
#endif
751
        doDtlsTimeout = doDtlsTimeout ||
752
            (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
753
#ifdef WOLFSSL_RW_THREADED
754
        wc_UnLockMutex(&ssl->dtls13Rtx.mutex);
755
#endif
756
    }
757
#endif /* WOLFSSL_DTLS13 */
758
759
    do {
760
761
        if (!doDtlsTimeout) {
762
            dtls_timeout = 0;
763
        }
764
        else {
765
#ifndef NO_ASN_TIME
766
            if (start == 0) {
767
                start = LowResTimer();
768
            }
769
            else {
770
                dtls_timeout -= (int) (LowResTimer() - start);
771
                start = LowResTimer();
772
                if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
773
                    return WOLFSSL_CBIO_ERR_TIMEOUT;
774
            }
775
#endif
776
        }
777
778
        if (!wolfSSL_get_using_nonblock(ssl)) {
779
        #ifdef USE_WINDOWS_API
780
            DWORD timeout = dtls_timeout * 1000;
781
            #ifdef WOLFSSL_DTLS13
782
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
783
                IsAtLeastTLSv1_3(ssl->version))
784
                timeout /= 4;
785
            #endif /* WOLFSSL_DTLS13 */
786
        #else
787
            struct timeval timeout;
788
            XMEMSET(&timeout, 0, sizeof(timeout));
789
            #ifdef WOLFSSL_DTLS13
790
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
791
                IsAtLeastTLSv1_3(ssl->version)) {
792
                if (dtls_timeout >= 4)
793
                    timeout.tv_sec = dtls_timeout / 4;
794
                else
795
                    timeout.tv_usec = dtls_timeout * 1000000 / 4;
796
            }
797
            else
798
            #endif /* WOLFSSL_DTLS13 */
799
                timeout.tv_sec = dtls_timeout;
800
        #endif /* USE_WINDOWS_API */
801
            if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
802
                    sizeof(timeout)) != 0) {
803
                WOLFSSL_MSG("setsockopt rcvtimeo failed");
804
            }
805
        }
806
#ifndef NO_ASN_TIME
807
        else if (IsSCR(ssl)) {
808
            if (ssl->dtls_start_timeout &&
809
                LowResTimer() - ssl->dtls_start_timeout >
810
                    (word32)dtls_timeout) {
811
                ssl->dtls_start_timeout = 0;
812
                return WOLFSSL_CBIO_ERR_TIMEOUT;
813
            }
814
            else if (!ssl->dtls_start_timeout) {
815
                ssl->dtls_start_timeout = LowResTimer();
816
            }
817
        }
818
#endif /* !NO_ASN_TIME */
819
820
        {
821
            XSOCKLENT inPeerSz = peerSz;
822
            if (dtlsCtx->recvfrom == NULL) {
823
                recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz,
824
                        ssl->rflags, (SOCKADDR*)peer,
825
                        peer != NULL ? &inPeerSz : NULL);
826
            }
827
            else {
828
                recvd = (int)dtlsCtx->recvfrom(sd, buf, (size_t) sz,
829
                        ssl->rflags, (SOCKADDR*) peer,
830
                        peer != NULL ? &inPeerSz : NULL);
831
            }
832
            /* Truncate peerSz. From the RECV(2) man page
833
             * The returned address is truncated if the buffer provided is too
834
             * small; in this case, addrlen will return a value greater than was
835
             * supplied to the call.
836
             */
837
            peerSz = MIN(peerSz, inPeerSz);
838
        }
839
840
        recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
841
842
        if (recvd < 0) {
843
            WOLFSSL_MSG("Embed Receive From error");
844
            if (recvd == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) &&
845
                !wolfSSL_dtls_get_using_nonblock(ssl)) {
846
                recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
847
            }
848
            return recvd;
849
        }
850
        else if (recvd == 0) {
851
            if (!dtlsCtx->rfdIsDGram) {
852
                /* Closed TCP connection */
853
                recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
854
            }
855
            else {
856
                WOLFSSL_MSG("Ignoring 0-length datagram");
857
                continue;
858
            }
859
            return recvd;
860
        }
861
        else if (dtlsCtx->connected) {
862
            /* Nothing to do */
863
        }
864
        else if (dtlsCtx->userSet) {
865
            /* Check we received the packet from the correct peer */
866
            int ignore = 0;
867
#ifdef WOLFSSL_RW_THREADED
868
            if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
869
                return WOLFSSL_CBIO_ERR_GENERAL;
870
#endif
871
            if (dtlsCtx->peer.sz > 0 &&
872
                (peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
873
                    !sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
874
                        dtlsCtx->peer.sz))) {
875
                WOLFSSL_MSG("    Ignored packet from invalid peer");
876
                ignore = 1;
877
            }
878
#ifdef WOLFSSL_RW_THREADED
879
            if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
880
                return WOLFSSL_CBIO_ERR_GENERAL;
881
#endif
882
            if (ignore) {
883
#if defined(NO_ASN_TIME) &&                                                    \
884
    !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
885
                if (doDtlsTimeout) {
886
                    invalidPeerPackets++;
887
                    if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
888
                        return wolfSSL_dtls_get_using_nonblock(ssl)
889
                                   ? WOLFSSL_CBIO_ERR_WANT_READ
890
                                   : WOLFSSL_CBIO_ERR_TIMEOUT;
891
                }
892
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
893
                continue;
894
            }
895
        }
896
        else {
897
            if (newPeer) {
898
                /* Store size of saved address. Locking handled internally. */
899
                if (wolfSSL_dtls_set_peer(ssl, peer, peerSz) != WOLFSSL_SUCCESS)
900
                    return WOLFSSL_CBIO_ERR_GENERAL;
901
                dtlsCtx->userSet = 0;
902
            }
903
#ifndef WOLFSSL_PEER_ADDRESS_CHANGES
904
            else {
905
                ret = 0;
906
    #ifdef WOLFSSL_RW_THREADED
907
                if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
908
                    return WOLFSSL_CBIO_ERR_GENERAL;
909
    #endif /* WOLFSSL_RW_THREADED */
910
                if (!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
911
                                    dtlsCtx->peer.sz)) {
912
                    ret = WOLFSSL_CBIO_ERR_GENERAL;
913
                }
914
    #ifdef WOLFSSL_RW_THREADED
915
                if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
916
                    return WOLFSSL_CBIO_ERR_GENERAL;
917
    #endif /* WOLFSSL_RW_THREADED */
918
                if (ret != 0)
919
                    return ret;
920
            }
921
#endif /* !WOLFSSL_PEER_ADDRESS_CHANGES */
922
        }
923
#ifndef NO_ASN_TIME
924
        ssl->dtls_start_timeout = 0;
925
#endif /* !NO_ASN_TIME */
926
        break;
927
    } while (1);
928
929
    return recvd;
930
}
931
932
933
/* The send embedded callback
934
 *  return : nb bytes sent, or error
935
 */
936
int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
937
{
938
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
939
    int sd = dtlsCtx->wfd;
940
    int sent;
941
    const SOCKADDR_S* peer = NULL;
942
    XSOCKLENT peerSz = 0;
943
944
    WOLFSSL_ENTER("EmbedSendTo");
945
946
    if (sz < 0)
947
        return WOLFSSL_CBIO_ERR_GENERAL;
948
949
    if (!dtlsCtx->wfdIsDGram) {
950
        /* Probably a TCP socket. peer and peerSz MUST be NULL and 0 */
951
    }
952
    else if (!dtlsCtx->connected) {
953
        peer   = (const SOCKADDR_S*)dtlsCtx->peer.sa;
954
        peerSz = dtlsCtx->peer.sz;
955
#ifndef WOLFSSL_IPV6
956
        if (PeerIsIpv6(peer, peerSz)) {
957
            WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
958
            return NOT_COMPILED_IN;
959
        }
960
#endif
961
    }
962
963
    if (dtlsCtx->sendto == NULL) {
964
        sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags,
965
                (const SOCKADDR*)peer, peerSz);
966
    }
967
    else {
968
        sent = (int)dtlsCtx->sendto(sd, buf, (size_t)sz, ssl->wflags,
969
                (const SOCKADDR*)peer, peerSz);
970
    }
971
972
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
973
974
    if (sent < 0) {
975
        WOLFSSL_MSG("Embed Send To error");
976
    }
977
978
    return sent;
979
}
980
981
982
#ifdef WOLFSSL_MULTICAST
983
984
/* The alternate receive embedded callback for Multicast
985
 *  return : nb bytes read, or error
986
 */
987
int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
988
{
989
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
990
    int recvd;
991
    int sd = dtlsCtx->rfd;
992
993
    WOLFSSL_ENTER("EmbedReceiveFromMcast");
994
995
    if (sz < 0)
996
        return WOLFSSL_CBIO_ERR_GENERAL;
997
998
    recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, NULL, NULL);
999
1000
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1001
1002
    if (recvd < 0) {
1003
        WOLFSSL_MSG("Embed Receive From error");
1004
        if (recvd == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ) &&
1005
            !wolfSSL_dtls_get_using_nonblock(ssl)) {
1006
            recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
1007
        }
1008
    }
1009
1010
    return recvd;
1011
}
1012
#endif /* WOLFSSL_MULTICAST */
1013
1014
1015
/* The DTLS Generate Cookie callback
1016
 *  return : number of bytes copied into buf, or error
1017
 */
1018
int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
1019
{
1020
    int sd = ssl->wfd;
1021
    SOCKADDR_S peer;
1022
    XSOCKLENT peerSz = sizeof(peer);
1023
    byte digest[WC_SHA256_DIGEST_SIZE];
1024
    int  ret = 0;
1025
1026
    (void)ctx;
1027
1028
    if (sz < 0)
1029
        return BAD_FUNC_ARG;
1030
1031
    XMEMSET(&peer, 0, sizeof(peer));
1032
    if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
1033
        WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
1034
        return GEN_COOKIE_E;
1035
    }
1036
1037
    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
1038
    if (ret != 0)
1039
        return ret;
1040
1041
    if (sz > WC_SHA256_DIGEST_SIZE)
1042
        sz = WC_SHA256_DIGEST_SIZE;
1043
    XMEMCPY(buf, digest, (size_t)sz);
1044
1045
    return sz;
1046
}
1047
#endif /* WOLFSSL_DTLS */
1048
1049
#ifdef WOLFSSL_SESSION_EXPORT
1050
1051
#ifdef WOLFSSL_DTLS
1052
    static int EmbedGetPeerDTLS(WOLFSSL* ssl, char* ip, int* ipSz,
1053
                                                 unsigned short* port, int* fam)
1054
    {
1055
        SOCKADDR_S peer;
1056
        word32     peerSz;
1057
        int        ret;
1058
1059
        /* get peer information stored in ssl struct */
1060
        peerSz = sizeof(SOCKADDR_S);
1061
        if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
1062
                                                               != WOLFSSL_SUCCESS) {
1063
            return ret;
1064
        }
1065
1066
        /* extract family, ip, and port */
1067
        *fam = ((SOCKADDR_S*)&peer)->ss_family;
1068
        switch (*fam) {
1069
            case WOLFSSL_IP4:
1070
                if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
1071
                                                           ip, *ipSz) == NULL) {
1072
                    WOLFSSL_MSG("XINET_NTOP error");
1073
                    return SOCKET_ERROR_E;
1074
                }
1075
                *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
1076
                break;
1077
1078
            case WOLFSSL_IP6:
1079
            #ifdef WOLFSSL_IPV6
1080
                if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
1081
                                                           ip, *ipSz) == NULL) {
1082
                    WOLFSSL_MSG("XINET_NTOP error");
1083
                    return SOCKET_ERROR_E;
1084
                }
1085
                *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
1086
            #endif /* WOLFSSL_IPV6 */
1087
                break;
1088
1089
            default:
1090
                WOLFSSL_MSG("Unknown family type");
1091
                return SOCKET_ERROR_E;
1092
        }
1093
        ip[*ipSz - 1] = '\0'; /* make sure has terminator */
1094
        *ipSz = (word16)XSTRLEN(ip);
1095
1096
        return WOLFSSL_SUCCESS;
1097
    }
1098
1099
    static int EmbedSetPeerDTLS(WOLFSSL* ssl, char* ip, int ipSz,
1100
                                                   unsigned short port, int fam)
1101
    {
1102
        int    ret;
1103
        SOCKADDR_S addr;
1104
1105
        /* sanity checks on arguments */
1106
        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
1107
            return BAD_FUNC_ARG;
1108
        }
1109
1110
        addr.ss_family = fam;
1111
        switch (addr.ss_family) {
1112
            case WOLFSSL_IP4:
1113
                if (XINET_PTON(addr.ss_family, ip,
1114
                                     &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
1115
                    WOLFSSL_MSG("XINET_PTON error");
1116
                    return SOCKET_ERROR_E;
1117
                }
1118
                ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
1119
1120
                /* peer sa is free'd in wolfSSL_ResourceFree */
1121
                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
1122
                                          sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
1123
                    WOLFSSL_MSG("Import DTLS peer info error");
1124
                    return ret;
1125
                }
1126
                break;
1127
1128
            case WOLFSSL_IP6:
1129
            #ifdef WOLFSSL_IPV6
1130
                if (XINET_PTON(addr.ss_family, ip,
1131
                                   &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
1132
                    WOLFSSL_MSG("XINET_PTON error");
1133
                    return SOCKET_ERROR_E;
1134
                }
1135
                ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
1136
1137
                /* peer sa is free'd in wolfSSL_ResourceFree */
1138
                if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
1139
                                         sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
1140
                    WOLFSSL_MSG("Import DTLS peer info error");
1141
                    return ret;
1142
                }
1143
            #endif /* WOLFSSL_IPV6 */
1144
                break;
1145
1146
            default:
1147
                WOLFSSL_MSG("Unknown address family");
1148
                return BUFFER_E;
1149
        }
1150
1151
        return WOLFSSL_SUCCESS;
1152
    }
1153
#endif /* WOLFSSL_DTLS */
1154
1155
    /* get the peer information in human readable form (ip, port, family)
1156
     * default function assumes BSD sockets
1157
     * can be overridden with wolfSSL_CTX_SetIOGetPeer
1158
     */
1159
    int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
1160
                                                 unsigned short* port, int* fam)
1161
    {
1162
        if (ssl == NULL || ip == NULL || ipSz == NULL ||
1163
                                                  port == NULL || fam == NULL) {
1164
            return BAD_FUNC_ARG;
1165
        }
1166
1167
        if (ssl->options.dtls) {
1168
        #ifdef WOLFSSL_DTLS
1169
            return EmbedGetPeerDTLS(ssl, ip, ipSz, port, fam);
1170
        #else
1171
            return NOT_COMPILED_IN;
1172
        #endif
1173
        }
1174
        else {
1175
            *port = wolfSSL_get_fd(ssl);
1176
            ip[0] = '\0';
1177
            *ipSz = 0;
1178
            *fam  = 0;
1179
            return WOLFSSL_SUCCESS;
1180
        }
1181
    }
1182
1183
    /* set the peer information in human readable form (ip, port, family)
1184
     * default function assumes BSD sockets
1185
     * can be overridden with wolfSSL_CTX_SetIOSetPeer
1186
     */
1187
    int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
1188
                                                   unsigned short port, int fam)
1189
    {
1190
        /* sanity checks on arguments */
1191
        if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
1192
            return BAD_FUNC_ARG;
1193
        }
1194
1195
        if (ssl->options.dtls) {
1196
        #ifdef WOLFSSL_DTLS
1197
            return EmbedSetPeerDTLS(ssl, ip, ipSz, port, fam);
1198
        #else
1199
            return NOT_COMPILED_IN;
1200
        #endif
1201
        }
1202
        else {
1203
            wolfSSL_set_fd(ssl, port);
1204
            (void)fam;
1205
            return WOLFSSL_SUCCESS;
1206
        }
1207
    }
1208
#endif /* WOLFSSL_SESSION_EXPORT */
1209
1210
#ifdef WOLFSSL_LINUXKM
1211
static int linuxkm_send(struct socket *socket, void *buf, int size,
1212
    unsigned int flags)
1213
{
1214
    size_t len;
1215
    int ret;
1216
    struct kvec vec;
1217
    struct msghdr msg = { .msg_flags = flags };
1218
1219
    if (size < 0)
1220
        return -EINVAL;
1221
    if (size == 0)
1222
        return 0;
1223
1224
    len = (size_t)size;
1225
    vec.iov_base = buf;
1226
    vec.iov_len  = len;
1227
1228
    ret = kernel_sendmsg(socket, &msg, &vec, 1, len);
1229
    return ret;
1230
}
1231
1232
static int linuxkm_recv(struct socket *socket, void *buf, int size,
1233
    unsigned int flags)
1234
{
1235
    size_t len;
1236
    int ret;
1237
    struct kvec vec;
1238
    struct msghdr msg = { .msg_flags = flags };
1239
1240
    if (size < 0)
1241
        return -EINVAL;
1242
    if (size == 0)
1243
        return 0;
1244
1245
    len = (size_t)size;
1246
    vec.iov_base = buf;
1247
    vec.iov_len  = len;
1248
1249
    ret = kernel_recvmsg(socket, &msg, &vec, 1, len, msg.msg_flags);
1250
    return ret;
1251
}
1252
#endif /* WOLFSSL_LINUXKM */
1253
1254
1255
int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
1256
0
{
1257
0
    int recvd;
1258
1259
0
    if (sz < 0)
1260
0
        return WOLFSSL_CBIO_ERR_GENERAL;
1261
1262
0
    recvd = (int)RECV_FUNCTION(sd, buf, (size_t)sz, rdFlags);
1263
0
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1264
1265
0
    return recvd;
1266
0
}
1267
1268
int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
1269
0
{
1270
0
    int sent;
1271
1272
0
    if (sz < 0)
1273
0
        return WOLFSSL_CBIO_ERR_GENERAL;
1274
1275
0
    sent = (int)SEND_FUNCTION(sd, buf, (size_t)sz, wrFlags);
1276
0
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
1277
1278
0
    return sent;
1279
0
}
1280
1281
#if defined(WOLFSSL_HAVE_BIO_ADDR) && defined(WOLFSSL_DTLS) && defined(OPENSSL_EXTRA)
1282
1283
int wolfIO_RecvFrom(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int rdFlags)
1284
{
1285
    int recvd;
1286
    socklen_t addr_len = (socklen_t)sizeof(*addr);
1287
1288
    if (sz < 0)
1289
        return WOLFSSL_CBIO_ERR_GENERAL;
1290
1291
    recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, rdFlags,
1292
                                            addr ? &addr->sa : NULL,
1293
                                            addr ? &addr_len : 0);
1294
    recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
1295
1296
    return recvd;
1297
}
1298
1299
int wolfIO_SendTo(SOCKET_T sd, WOLFSSL_BIO_ADDR *addr, char *buf, int sz, int wrFlags)
1300
{
1301
    int sent;
1302
    socklen_t addr_len = addr ? wolfSSL_BIO_ADDR_size(addr) : 0;
1303
1304
    if (sz < 0)
1305
        return WOLFSSL_CBIO_ERR_GENERAL;
1306
1307
    sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, wrFlags,
1308
                                         addr ? &addr->sa : NULL,
1309
                                         addr_len);
1310
    sent = TranslateIoReturnCode(sent, sd, SOCKET_SENDING);
1311
1312
    return sent;
1313
}
1314
1315
#endif /* WOLFSSL_HAVE_BIO_ADDR && WOLFSSL_DTLS && OPENSSL_EXTRA */
1316
1317
#endif /* USE_WOLFSSL_IO */
1318
1319
1320
#ifdef HAVE_HTTP_CLIENT
1321
1322
#ifndef HAVE_IO_TIMEOUT
1323
    #define io_timeout_sec 0
1324
#else
1325
1326
    #ifndef DEFAULT_TIMEOUT_SEC
1327
        #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
1328
    #endif
1329
1330
    static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
1331
1332
    void wolfIO_SetTimeout(int to_sec)
1333
    {
1334
        io_timeout_sec = to_sec;
1335
    }
1336
1337
    int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
1338
    {
1339
        int ret = 0;
1340
1341
    #ifdef USE_WINDOWS_API
1342
        unsigned long blocking = non_blocking;
1343
        ret = ioctlsocket(sockfd, FIONBIO, &blocking);
1344
        if (ret == SOCKET_ERROR)
1345
            ret = WOLFSSL_FATAL_ERROR;
1346
    #elif defined(__WATCOMC__) && defined(__OS2__)
1347
        if (ioctl(sockfd, FIONBIO, &non_blocking) == -1)
1348
            ret = WOLFSSL_FATAL_ERROR;
1349
    #else
1350
        ret = fcntl(sockfd, F_GETFL, 0);
1351
        if (ret >= 0) {
1352
            if (non_blocking)
1353
                ret |= O_NONBLOCK;
1354
            else
1355
                ret &= ~O_NONBLOCK;
1356
            ret = fcntl(sockfd, F_SETFL, ret);
1357
        }
1358
    #endif
1359
        if (ret < 0) {
1360
            WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
1361
        }
1362
1363
        return ret;
1364
    }
1365
1366
    int wolfIO_Select(SOCKET_T sockfd, int to_sec)
1367
    {
1368
        fd_set rfds, wfds;
1369
        int nfds = 0;
1370
        struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
1371
        int ret;
1372
1373
    #ifndef USE_WINDOWS_API
1374
        nfds = (int)sockfd + 1;
1375
1376
        if ((sockfd < 0) || (sockfd >= FD_SETSIZE)) {
1377
            WOLFSSL_MSG("socket fd out of FDSET range");
1378
            return WOLFSSL_FATAL_ERROR;
1379
        }
1380
    #endif
1381
1382
        FD_ZERO(&rfds);
1383
        FD_SET(sockfd, &rfds);
1384
        wfds = rfds;
1385
1386
        ret = select(nfds, &rfds, &wfds, NULL, &timeout);
1387
        if (ret == 0) {
1388
    #ifdef DEBUG_HTTP
1389
            fprintf(stderr, "Timeout: %d\n", ret);
1390
    #endif
1391
            return HTTP_TIMEOUT;
1392
        }
1393
        else if (ret > 0) {
1394
            if (FD_ISSET(sockfd, &wfds)) {
1395
                if (!FD_ISSET(sockfd, &rfds)) {
1396
                    return 0;
1397
                }
1398
            }
1399
        }
1400
1401
        WOLFSSL_MSG("Select error");
1402
        return SOCKET_ERROR_E;
1403
    }
1404
#endif /* HAVE_IO_TIMEOUT */
1405
1406
static word32 wolfIO_Word16ToString(char* d, word16 number)
1407
{
1408
    word32 i = 0;
1409
    word16 order = 10000;
1410
    word16 digit;
1411
1412
    if (d == NULL)
1413
        return i;
1414
1415
    if (number == 0)
1416
        d[i++] = '0';
1417
    else {
1418
        while (order) {
1419
            digit = number / order;
1420
            if (i > 0 || digit != 0)
1421
                d[i++] = (char)digit + '0';
1422
            if (digit != 0)
1423
                number = (word16) (number % (digit * order));
1424
1425
            order = (order > 1) ? order / 10 : 0;
1426
        }
1427
    }
1428
    d[i] = 0; /* null terminate */
1429
1430
    return i;
1431
}
1432
1433
int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
1434
{
1435
#ifdef HAVE_SOCKADDR
1436
    int ret = 0;
1437
    SOCKADDR_S addr;
1438
    socklen_t sockaddr_len;
1439
#if defined(HAVE_GETADDRINFO)
1440
    /* use getaddrinfo */
1441
    ADDRINFO hints;
1442
    ADDRINFO* answer = NULL;
1443
    char strPort[6];
1444
#else
1445
    /* use gethostbyname */
1446
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1447
    !defined(SINGLE_THREADED)
1448
    HOSTENT entry_buf, *entry = NULL;
1449
    char *ghbn_r_buf = NULL;
1450
    int ghbn_r_errno;
1451
#else
1452
    HOSTENT *entry;
1453
#endif
1454
#ifdef WOLFSSL_IPV6
1455
    SOCKADDR_IN6 *sin;
1456
#else
1457
    SOCKADDR_IN *sin;
1458
#endif /* WOLFSSL_IPV6 */
1459
#endif /* HAVE_GETADDRINFO */
1460
1461
    if (sockfd == NULL || ip == NULL) {
1462
        return WOLFSSL_FATAL_ERROR;
1463
    }
1464
1465
#if !defined(HAVE_GETADDRINFO)
1466
#ifdef WOLFSSL_IPV6
1467
    sockaddr_len = sizeof(SOCKADDR_IN6);
1468
#else
1469
    sockaddr_len = sizeof(SOCKADDR_IN);
1470
#endif /* WOLFSSL_IPV6 */
1471
#endif /* !HAVE_GETADDRINFO */
1472
    XMEMSET(&addr, 0, sizeof(addr));
1473
1474
#ifdef WOLFIO_DEBUG
1475
    printf("TCP Connect: %s:%d\n", ip, port);
1476
#endif
1477
1478
    /* use gethostbyname for c99 */
1479
#if defined(HAVE_GETADDRINFO)
1480
    XMEMSET(&hints, 0, sizeof(hints));
1481
#ifdef WOLFSSL_IPV6
1482
    hints.ai_family = AF_UNSPEC; /* detect IPv4 or IPv6 */
1483
#else
1484
    hints.ai_family = AF_INET;   /* detect only IPv4 */
1485
#endif
1486
    hints.ai_socktype = SOCK_STREAM;
1487
    hints.ai_protocol = IPPROTO_TCP;
1488
1489
    if (wolfIO_Word16ToString(strPort, port) == 0) {
1490
        WOLFSSL_MSG("invalid port number for responder");
1491
        return WOLFSSL_FATAL_ERROR;
1492
    }
1493
1494
    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
1495
        WOLFSSL_MSG("no addr info for responder");
1496
        return WOLFSSL_FATAL_ERROR;
1497
    }
1498
1499
    sockaddr_len = answer->ai_addrlen;
1500
    XMEMCPY(&addr, answer->ai_addr, (size_t)sockaddr_len);
1501
    freeaddrinfo(answer);
1502
#else
1503
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1504
    !defined(SINGLE_THREADED)
1505
    /* 2048 is a magic number that empirically works.  the header and
1506
     * documentation provide no guidance on appropriate buffer size other than
1507
     * "if buf is too small, the functions will return ERANGE, and the call
1508
     * should be retried with a larger buffer."
1509
     */
1510
    ghbn_r_buf = (char *)XMALLOC(2048, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1511
    if (ghbn_r_buf != NULL) {
1512
        gethostbyname_r(ip, &entry_buf, ghbn_r_buf, 2048, &entry, &ghbn_r_errno);
1513
    }
1514
#else
1515
    entry = gethostbyname(ip);
1516
#endif
1517
1518
    if (entry) {
1519
    #ifdef WOLFSSL_IPV6
1520
        sin = (SOCKADDR_IN6 *)&addr;
1521
        sin->sin6_family = AF_INET6;
1522
        sin->sin6_port = XHTONS(port);
1523
        XMEMCPY(&sin->sin6_addr, entry->h_addr_list[0], entry->h_length);
1524
    #else
1525
        sin = (SOCKADDR_IN *)&addr;
1526
        sin->sin_family = AF_INET;
1527
        sin->sin_port = XHTONS(port);
1528
        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
1529
                (size_t)entry->h_length);
1530
    #endif
1531
    }
1532
1533
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1534
    !defined(SINGLE_THREADED)
1535
    XFREE(ghbn_r_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1536
#endif
1537
1538
    if (entry == NULL) {
1539
        WOLFSSL_MSG("no addr info for responder");
1540
        return WOLFSSL_FATAL_ERROR;
1541
    }
1542
#endif
1543
1544
    *sockfd = (SOCKET_T)wc_socket_cloexec(addr.ss_family, SOCK_STREAM, 0);
1545
#ifdef USE_WINDOWS_API
1546
    if (*sockfd == SOCKET_INVALID)
1547
#else
1548
    if (*sockfd <= SOCKET_INVALID)
1549
#endif
1550
    {
1551
        WOLFSSL_MSG("bad socket fd, out of fds?");
1552
        *sockfd = SOCKET_INVALID;
1553
        return WOLFSSL_FATAL_ERROR;
1554
    }
1555
1556
#ifdef HAVE_IO_TIMEOUT
1557
    /* if timeout value provided then set socket non-blocking */
1558
    if (to_sec > 0) {
1559
        wolfIO_SetBlockingMode(*sockfd, 1);
1560
    }
1561
#else
1562
    (void)to_sec;
1563
#endif /* HAVE_IO_TIMEOUT */
1564
1565
    ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
1566
#ifdef HAVE_IO_TIMEOUT
1567
    if ((ret != 0) && (to_sec > 0)) {
1568
#ifdef USE_WINDOWS_API
1569
        if ((ret == SOCKET_ERROR) &&
1570
            (wolfSSL_LastError(ret, *sockfd) == SOCKET_EWOULDBLOCK))
1571
#else
1572
        if (errno == EINPROGRESS)
1573
#endif
1574
        {
1575
            /* wait for connect to complete */
1576
            ret = wolfIO_Select(*sockfd, to_sec);
1577
1578
            /* restore blocking mode */
1579
            wolfIO_SetBlockingMode(*sockfd, 0);
1580
        }
1581
    }
1582
#endif /* HAVE_IO_TIMEOUT */
1583
    if (ret != 0) {
1584
        WOLFSSL_MSG("Responder tcp connect failed");
1585
        CloseSocket(*sockfd);
1586
        *sockfd = SOCKET_INVALID;
1587
        return WOLFSSL_FATAL_ERROR;
1588
    }
1589
    return ret;
1590
#else
1591
    (void)sockfd;
1592
    (void)ip;
1593
    (void)port;
1594
    (void)to_sec;
1595
    return WOLFSSL_FATAL_ERROR;
1596
#endif /* HAVE_SOCKADDR */
1597
}
1598
1599
int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
1600
{
1601
#ifdef HAVE_SOCKADDR
1602
    int ret = 0;
1603
    SOCKADDR_S addr;
1604
#ifdef WOLFSSL_IPV6
1605
    socklen_t sockaddr_len = sizeof(SOCKADDR_IN6);
1606
    SOCKADDR_IN6 *sin = (SOCKADDR_IN6 *)&addr;
1607
#else
1608
    socklen_t sockaddr_len = sizeof(SOCKADDR_IN);
1609
    SOCKADDR_IN *sin = (SOCKADDR_IN *)&addr;
1610
#endif
1611
1612
    if (sockfd == NULL || port < 1) {
1613
        return WOLFSSL_FATAL_ERROR;
1614
    }
1615
1616
    XMEMSET(&addr, 0, sizeof(addr));
1617
1618
#ifdef WOLFSSL_IPV6
1619
    sin->sin6_family = AF_INET6;
1620
    sin->sin6_addr = in6addr_any;
1621
    sin->sin6_port = XHTONS(port);
1622
    *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET6, SOCK_STREAM, 0);
1623
#else
1624
    sin->sin_family = AF_INET;
1625
    sin->sin_addr.s_addr = INADDR_ANY;
1626
    sin->sin_port = XHTONS(port);
1627
    *sockfd = (SOCKET_T)wc_socket_cloexec(AF_INET, SOCK_STREAM, 0);
1628
#endif
1629
1630
#ifdef USE_WINDOWS_API
1631
    if (*sockfd == SOCKET_INVALID)
1632
#else
1633
    if (*sockfd <= SOCKET_INVALID)
1634
#endif
1635
    {
1636
        WOLFSSL_MSG("socket failed");
1637
        *sockfd = SOCKET_INVALID;
1638
        return WOLFSSL_FATAL_ERROR;
1639
    }
1640
1641
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
1642
                   && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
1643
    {
1644
        int optval  = 1;
1645
        XSOCKLENT optlen = sizeof(optval);
1646
        ret = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
1647
    }
1648
#endif
1649
1650
    if (ret == 0)
1651
        ret = bind(*sockfd, (SOCKADDR *)sin, sockaddr_len);
1652
    if (ret == 0)
1653
        ret = listen(*sockfd, SOMAXCONN);
1654
1655
    if (ret != 0) {
1656
        WOLFSSL_MSG("wolfIO_TcpBind failed");
1657
        CloseSocket(*sockfd);
1658
        *sockfd = SOCKET_INVALID;
1659
        ret = WOLFSSL_FATAL_ERROR;
1660
    }
1661
1662
    return ret;
1663
#else
1664
    (void)sockfd;
1665
    (void)port;
1666
    return WOLFSSL_FATAL_ERROR;
1667
#endif /* HAVE_SOCKADDR */
1668
}
1669
1670
#ifdef HAVE_SOCKADDR
1671
int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
1672
{
1673
    return (int)wc_accept_cloexec((int)sockfd, peer_addr, peer_len);
1674
}
1675
#endif /* HAVE_SOCKADDR */
1676
1677
#ifndef HTTP_SCRATCH_BUFFER_SIZE
1678
    #define HTTP_SCRATCH_BUFFER_SIZE 512
1679
#endif
1680
#ifndef MAX_URL_ITEM_SIZE
1681
    #define MAX_URL_ITEM_SIZE   80
1682
#endif
1683
1684
int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
1685
    word16* outPort)
1686
{
1687
    int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
1688
1689
    if (url == NULL || urlSz == 0) {
1690
        if (outName)
1691
            *outName = 0;
1692
        if (outPath)
1693
            *outPath = 0;
1694
        if (outPort)
1695
            *outPort = 0;
1696
    }
1697
    else {
1698
        int i, cur;
1699
1700
        /* need to break the url down into scheme, address, and port */
1701
        /*     "http://example.com:8080/" */
1702
        /*     "http://[::1]:443/"        */
1703
        if (XSTRNCMP(url, "http://", 7) == 0) {
1704
            cur = 7;
1705
        } else cur = 0;
1706
1707
        i = 0;
1708
        if (url[cur] == '[') {
1709
            cur++;
1710
            /* copy until ']' */
1711
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1712
                    url[cur] != ']') {
1713
                if (url[cur] == '\r' || url[cur] == '\n')
1714
                    return WOLFSSL_FATAL_ERROR;
1715
                if (outName)
1716
                    outName[i] = url[cur];
1717
                i++; cur++;
1718
            }
1719
            /* A bracketed IPv6 literal must be terminated by ']'. The loop
1720
             * above can also stop on end-of-buffer, NUL, or the length cap,
1721
             * none of which represent a well-formed host. Reject those cases
1722
             * rather than accepting the unterminated tail as the hostname. */
1723
            if (cur >= urlSz || url[cur] != ']')
1724
                return WOLFSSL_FATAL_ERROR;
1725
            cur++; /* skip ']' */
1726
        }
1727
        else {
1728
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1729
                    url[cur] != ':' && url[cur] != '/') {
1730
                if (url[cur] == '\r' || url[cur] == '\n')
1731
                    return WOLFSSL_FATAL_ERROR;
1732
                if (outName)
1733
                    outName[i] = url[cur];
1734
                i++; cur++;
1735
            }
1736
        }
1737
        if (outName)
1738
            outName[i] = 0;
1739
        /* Need to pick out the path after the domain name */
1740
1741
        if (cur < urlSz && url[cur] == ':') {
1742
            char port[5];
1743
            int j;
1744
            word32 bigPort = 0;
1745
            i = 0;
1746
            cur++;
1747
1748
            XMEMSET(port, 0, sizeof(port));
1749
1750
            while (i < 5 && cur < urlSz && url[cur] != 0 && url[cur] != '/') {
1751
                port[i] = url[cur];
1752
                i++; cur++;
1753
            }
1754
1755
            /* A valid port is at most 5 digits; if more characters remain
1756
             * before the path/terminator the port field is malformed (e.g.
1757
             * a 6-digit port) and must be rejected rather than parsed from a
1758
             * truncated digit string. */
1759
            if (cur < urlSz && url[cur] != 0 && url[cur] != '/')
1760
                return WOLFSSL_FATAL_ERROR;
1761
1762
            for (j = 0; j < i; j++) {
1763
                if (port[j] < '0' || port[j] > '9') return WOLFSSL_FATAL_ERROR;
1764
                bigPort = (bigPort * 10) + (word32)(port[j] - '0');
1765
            }
1766
            /* Reject out-of-range ports rather than silently truncating to
1767
             * word16, which would otherwise wrap (e.g. 65536 -> 0) and
1768
             * connect to an unintended port. */
1769
            if (bigPort > WOLFSSL_MAX_16BIT)
1770
                return WOLFSSL_FATAL_ERROR;
1771
            if (outPort)
1772
                *outPort = (word16)bigPort;
1773
        }
1774
        else if (outPort)
1775
            *outPort = 80;
1776
1777
1778
        if (cur < urlSz && url[cur] == '/') {
1779
            i = 0;
1780
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) {
1781
                if (url[cur] == '\r' || url[cur] == '\n')
1782
                    return WOLFSSL_FATAL_ERROR;
1783
                if (outPath)
1784
                    outPath[i] = url[cur];
1785
                i++; cur++;
1786
            }
1787
            if (outPath)
1788
                outPath[i] = 0;
1789
        }
1790
        else if (outPath) {
1791
            outPath[0] = '/';
1792
            outPath[1] = 0;
1793
        }
1794
1795
        result = 0;
1796
    }
1797
1798
    return result;
1799
}
1800
1801
#ifndef WOLFIO_HTTP_MAX_BODY
1802
/* Upper bound on an HTTP body that will be buffered in memory. */
1803
#define WOLFIO_HTTP_MAX_BODY (32 * 1024 * 1024)
1804
#endif
1805
1806
static int wolfIO_HttpProcessResponseBuf(WolfSSLGenericIORecvCb ioCb,
1807
    void* ioCbCtx, byte **recvBuf, int* recvBufSz, int chunkSz, char* start,
1808
    int len, int dynType, void* heap)
1809
{
1810
    byte* newRecvBuf = NULL;
1811
    int newRecvSz;
1812
    int pos = 0;
1813
1814
    WOLFSSL_MSG("Processing HTTP response");
1815
#ifdef WOLFIO_DEBUG
1816
    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
1817
#endif
1818
1819
    (void)heap;
1820
    (void)dynType;
1821
1822
    if (chunkSz < 0 || len < 0) {
1823
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size");
1824
        return MEMORY_E;
1825
    }
1826
1827
    if (chunkSz > WOLFIO_HTTP_MAX_BODY) {
1828
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf chunk too large");
1829
        return BUFFER_ERROR;
1830
    }
1831
1832
    if (*recvBufSz < 0 || *recvBufSz > WOLFIO_HTTP_MAX_BODY - chunkSz) {
1833
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf aggregate body too large");
1834
        return BUFFER_ERROR;
1835
    }
1836
1837
    if (len > chunkSz) {
1838
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf len exceeds chunk size");
1839
        return WOLFSSL_FATAL_ERROR;
1840
    }
1841
1842
    newRecvSz = *recvBufSz + chunkSz;
1843
1844
    if (newRecvSz <= 0) {
1845
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow");
1846
        return MEMORY_E;
1847
    }
1848
1849
    newRecvBuf = (byte*)XMALLOC((size_t)newRecvSz, heap, dynType);
1850
    if (newRecvBuf == NULL) {
1851
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
1852
        return MEMORY_E;
1853
    }
1854
1855
    /* if buffer already exists, then we are growing it */
1856
    if (*recvBuf) {
1857
        XMEMCPY(&newRecvBuf[pos], *recvBuf, (size_t) *recvBufSz);
1858
        XFREE(*recvBuf, heap, dynType);
1859
        pos += *recvBufSz;
1860
        *recvBuf = NULL;
1861
    }
1862
1863
    /* copy the remainder of the httpBuf into the respBuf */
1864
    if (len != 0) {
1865
        if (pos + len <= newRecvSz) {
1866
            XMEMCPY(&newRecvBuf[pos], start, (size_t)len);
1867
            pos += len;
1868
        }
1869
        else {
1870
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size");
1871
            XFREE(newRecvBuf, heap, dynType);
1872
            return WOLFSSL_FATAL_ERROR;
1873
        }
1874
    }
1875
1876
    /* receive the remainder of chunk */
1877
    while (len < chunkSz) {
1878
        int rxSz = ioCb((char*)&newRecvBuf[pos], chunkSz-len, ioCbCtx);
1879
        if (rxSz > 0) {
1880
            len += rxSz;
1881
            pos += rxSz;
1882
        }
1883
        else {
1884
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
1885
            XFREE(newRecvBuf, heap, dynType);
1886
            return WOLFSSL_FATAL_ERROR;
1887
        }
1888
    }
1889
1890
    *recvBuf = newRecvBuf;
1891
    *recvBufSz = newRecvSz;
1892
1893
    return 0;
1894
}
1895
1896
int wolfIO_HttpProcessResponseGenericIO(WolfSSLGenericIORecvCb ioCb,
1897
    void* ioCbCtx, const char** appStrList, unsigned char** respBuf,
1898
    unsigned char* httpBuf, int httpBufSz, int dynType, void* heap)
1899
{
1900
    static const char HTTP_PROTO[] = "HTTP/1.";
1901
    static const char HTTP_STATUS_200[] = "200";
1902
    int result = 0;
1903
    int len = 0;
1904
    char *start, *end;
1905
    int respBufSz = 0;
1906
    int isChunked = 0, chunkSz = 0;
1907
    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
1908
                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
1909
                     phr_http_end
1910
    } state = phr_init;
1911
1912
    WOLFSSL_ENTER("wolfIO_HttpProcessResponse");
1913
1914
    *respBuf = NULL;
1915
    start = end = NULL;
1916
    do {
1917
        if (state == phr_get_chunk_data) {
1918
            /* get chunk of data */
1919
            result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
1920
                &respBufSz, chunkSz, start, len, dynType, heap);
1921
1922
            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
1923
            end = NULL;
1924
            len = 0;
1925
        }
1926
1927
        /* read data if no \r\n or first time */
1928
        if ((start == NULL) || (end == NULL)) {
1929
            if (httpBufSz < len + 1) {
1930
                return BUFFER_ERROR; /* can't happen, but Coverity thinks it
1931
                                      * can.
1932
                                      */
1933
            }
1934
            result = ioCb((char*)httpBuf+len, httpBufSz-len-1, ioCbCtx);
1935
            if (result > 0) {
1936
                len += result;
1937
                start = (char*)httpBuf;
1938
                start[len] = 0;
1939
            }
1940
            else {
1941
                if (result == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
1942
                    return OCSP_WANT_READ;
1943
                }
1944
1945
                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
1946
                return HTTP_RECV_ERR;
1947
            }
1948
        }
1949
        end = XSTRSTR(start, "\r\n"); /* locate end */
1950
1951
        /* handle incomplete rx */
1952
        if (end == NULL) {
1953
            if (len != 0)
1954
                XMEMMOVE(httpBuf, start, (size_t)len);
1955
            start = end = NULL;
1956
        }
1957
        /* when start is "\r\n" */
1958
        else if (end == start) {
1959
            /* if waiting for end or need chunk len */
1960
            if (state == phr_wait_end || state == phr_get_chunk_len) {
1961
                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
1962
                len -= 2; start += 2; /* skip \r\n */
1963
             }
1964
             else {
1965
                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
1966
                return HTTP_HEADER_ERR;
1967
             }
1968
        }
1969
        else {
1970
            *end = 0; /* null terminate */
1971
            len -= (int)(end - start) + 2;
1972
                /* adjust len to remove the first line including the /r/n */
1973
1974
        #ifdef WOLFIO_DEBUG
1975
            printf("HTTP Resp: %s\n", start);
1976
        #endif
1977
1978
            switch (state) {
1979
                case phr_init:
1980
                    /* length of "HTTP/1.x 200" == 12*/
1981
                    if (XSTRLEN(start) < 12) {
1982
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1983
                            "too short.");
1984
                        return HTTP_HEADER_ERR;
1985
                    }
1986
                    if (XSTRNCASECMP(start, HTTP_PROTO,
1987
                                     sizeof(HTTP_PROTO) - 1) != 0) {
1988
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1989
                            "doesn't start with HTTP/1.");
1990
                        return HTTP_PROTO_ERR;
1991
                    }
1992
                    /* +2 for HTTP minor version and space between version and
1993
                     * status code. */
1994
                    start += sizeof(HTTP_PROTO) - 1 + 2 ;
1995
                    if (XSTRNCASECMP(start, HTTP_STATUS_200,
1996
                                     sizeof(HTTP_STATUS_200) - 1) != 0) {
1997
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1998
                            "doesn't have status code 200.");
1999
                        return HTTP_STATUS_ERR;
2000
                    }
2001
                    state = phr_http_start;
2002
                    break;
2003
                case phr_http_start:
2004
                case phr_have_length:
2005
                case phr_have_type:
2006
                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
2007
                        int i;
2008
2009
                        start += 13;
2010
                        while (*start == ' ') start++;
2011
2012
                        /* try and match against appStrList */
2013
                        i = 0;
2014
                        while (appStrList[i] != NULL) {
2015
                            if (XSTRNCASECMP(start, appStrList[i],
2016
                                                XSTRLEN(appStrList[i])) == 0) {
2017
                                break;
2018
                            }
2019
                            i++;
2020
                        }
2021
                        if (appStrList[i] == NULL) {
2022
                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
2023
                            return HTTP_APPSTR_ERR;
2024
                        }
2025
                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
2026
                    }
2027
                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
2028
                        start += 15;
2029
                        while (*start == ' ') start++;
2030
                        chunkSz = XATOI(start);
2031
                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
2032
                    }
2033
                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
2034
                        start += 18;
2035
                        while (*start == ' ') start++;
2036
                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
2037
                            isChunked = 1;
2038
                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
2039
                        }
2040
                    }
2041
                    break;
2042
                case phr_get_chunk_len:
2043
                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
2044
                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
2045
                    break;
2046
                case phr_get_chunk_data:
2047
                    /* processing for chunk data done above, since \r\n isn't required */
2048
                case phr_wait_end:
2049
                case phr_http_end:
2050
                    /* do nothing */
2051
                    break;
2052
            } /* switch (state) */
2053
2054
            /* skip to end plus \r\n */
2055
            start = end + 2;
2056
        }
2057
    } while (state != phr_http_end);
2058
2059
    if (!isChunked) {
2060
        result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
2061
                &respBufSz, chunkSz, start, len, dynType, heap);
2062
    }
2063
2064
    if (result >= 0) {
2065
        result = respBufSz;
2066
    }
2067
    else {
2068
        WOLFSSL_ERROR(result);
2069
    }
2070
2071
    return result;
2072
}
2073
2074
static int httpResponseIoCb(char* buf, int sz, void* ctx)
2075
{
2076
    /* Double cast to silence the compiler int/pointer width msg */
2077
    return wolfIO_Recv((SOCKET_T)(uintptr_t)ctx, buf, sz, 0);
2078
}
2079
2080
int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
2081
    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
2082
{
2083
    return wolfIO_HttpProcessResponseGenericIO(httpResponseIoCb,
2084
            /* Double cast to silence the compiler int/pointer width msg */
2085
            (void*)(uintptr_t)sfd, appStrList, respBuf, httpBuf, httpBufSz,
2086
            dynType, heap);
2087
}
2088
2089
int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
2090
                               const char *path, int pathLen, int reqSz, const char *contentType,
2091
                               byte *buf, int bufSize)
2092
{
2093
    return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize);
2094
}
2095
2096
/* Returns 1 if the buffer contains a CR or LF byte, 0 otherwise. Used to
2097
 * reject attacker-controlled URL components that would allow HTTP header
2098
 * injection or request splitting. */
2099
static int wolfIO_UrlHasCrlf(const char* in, int inSz)
2100
{
2101
    int i = 0;
2102
    if (in == NULL)
2103
        return 0;
2104
    for (i = 0; i < inSz; i++) {
2105
        if (in[i] == '\r' || in[i] == '\n')
2106
            return 1;
2107
    }
2108
    return 0;
2109
}
2110
2111
int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
2112
                                const char *path, int pathLen, int reqSz, const char *contentType,
2113
                                const char *exHdrs, byte *buf, int bufSize)
2114
    {
2115
    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen;
2116
    char reqSzStr[6];
2117
    char* req = (char*)buf;
2118
    const char* blankStr = " ";
2119
    const char* http11Str = " HTTP/1.1";
2120
    const char* hostStr = "\r\nHost: ";
2121
    const char* contentLenStr = "\r\nContent-Length: ";
2122
    const char* contentTypeStr = "\r\nContent-Type: ";
2123
    const char* singleCrLfStr = "\r\n";
2124
    const char* doubleCrLfStr = "\r\n\r\n";
2125
    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
2126
        contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen;
2127
2128
    /* reject NULL pointers and invalid lengths before any deref or length
2129
     * math: the XSTRLEN/copy calls below assume non-NULL inputs */
2130
    if (reqType == NULL || domainName == NULL || path == NULL ||
2131
            contentType == NULL || pathLen < 0 || bufSize <= 0)
2132
        return 0;
2133
2134
    reqTypeLen = (word32)XSTRLEN(reqType);
2135
    domainNameLen = (word32)XSTRLEN(domainName);
2136
    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
2137
    contentTypeLen = (word32)XSTRLEN(contentType);
2138
2139
    /* reject CR/LF in the path or host to prevent HTTP header injection or
2140
     * request splitting from attacker-controlled URL components */
2141
    if (wolfIO_UrlHasCrlf(path, pathLen) ||
2142
            wolfIO_UrlHasCrlf(domainName, (int)domainNameLen)) {
2143
        return 0;
2144
    }
2145
2146
    blankStrLen = (word32)XSTRLEN(blankStr);
2147
    http11StrLen = (word32)XSTRLEN(http11Str);
2148
    hostStrLen = (word32)XSTRLEN(hostStr);
2149
    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
2150
    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
2151
2152
    if(exHdrs){
2153
        singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr);
2154
        exHdrsLen = (word32)XSTRLEN(exHdrs);
2155
    } else {
2156
        singleCrLfStrLen = 0;
2157
        exHdrsLen = 0;
2158
    }
2159
2160
    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
2161
2162
    /* determine max length and check it */
2163
    maxLen =
2164
        reqTypeLen +
2165
        blankStrLen +
2166
        (word32)pathLen +
2167
        http11StrLen +
2168
        hostStrLen +
2169
        domainNameLen +
2170
        contentLenStrLen +
2171
        reqSzStrLen +
2172
        contentTypeStrLen +
2173
        contentTypeLen +
2174
        singleCrLfStrLen +
2175
        exHdrsLen +
2176
        doubleCrLfStrLen +
2177
        (word32)1 /* null term */;
2178
    if (maxLen > (word32)bufSize)
2179
        return 0;
2180
2181
    XSTRNCPY((char*)buf, reqType, (size_t)bufSize);
2182
    buf += reqTypeLen; bufSize -= (int)reqTypeLen;
2183
    XSTRNCPY((char*)buf, blankStr, (size_t)bufSize);
2184
    buf += blankStrLen; bufSize -= (int)blankStrLen;
2185
    /* path may not be NUL terminated (CRL raw-URL case passes a pointer into
2186
     * the certificate with only pathLen valid bytes), so bound the copy to
2187
     * pathLen rather than scanning for a NUL */
2188
    XMEMCPY((char*)buf, path, (size_t)pathLen);
2189
    buf += pathLen; bufSize -= (int)pathLen;
2190
    XSTRNCPY((char*)buf, http11Str, (size_t)bufSize);
2191
    buf += http11StrLen; bufSize -= (int)http11StrLen;
2192
    if (domainNameLen > 0) {
2193
        XSTRNCPY((char*)buf, hostStr, (size_t)bufSize);
2194
        buf += hostStrLen; bufSize -= (int)hostStrLen;
2195
        XSTRNCPY((char*)buf, domainName, (size_t)bufSize);
2196
        buf += domainNameLen; bufSize -= (int)domainNameLen;
2197
    }
2198
    if (reqSz > 0 && reqSzStrLen > 0) {
2199
        XSTRNCPY((char*)buf, contentLenStr, (size_t)bufSize);
2200
        buf += contentLenStrLen; bufSize -= (int)contentLenStrLen;
2201
        XSTRNCPY((char*)buf, reqSzStr, (size_t)bufSize);
2202
        buf += reqSzStrLen; bufSize -= (int)reqSzStrLen;
2203
    }
2204
    if (contentTypeLen > 0) {
2205
        XSTRNCPY((char*)buf, contentTypeStr, (size_t)bufSize);
2206
        buf += contentTypeStrLen; bufSize -= (int)contentTypeStrLen;
2207
        XSTRNCPY((char*)buf, contentType, (size_t)bufSize);
2208
        buf += contentTypeLen; bufSize -= (int)contentTypeLen;
2209
    }
2210
    if (exHdrsLen > 0)
2211
    {
2212
        XSTRNCPY((char *)buf, singleCrLfStr, (size_t)bufSize);
2213
        buf += singleCrLfStrLen;
2214
        bufSize -= (int)singleCrLfStrLen;
2215
        XSTRNCPY((char *)buf, exHdrs, (size_t)bufSize);
2216
        buf += exHdrsLen;
2217
        bufSize -= (int)exHdrsLen;
2218
    }
2219
    XSTRNCPY((char*)buf, doubleCrLfStr, (size_t)bufSize);
2220
    buf += doubleCrLfStrLen;
2221
2222
#ifdef WOLFIO_DEBUG
2223
    printf("HTTP %s: %s", reqType, req);
2224
#endif
2225
2226
    /* calculate actual length based on original and new pointer */
2227
    return (int)((char*)buf - req);
2228
}
2229
2230
2231
#ifdef HAVE_OCSP
2232
2233
int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
2234
                                    int ocspReqSz, byte* buf, int bufSize)
2235
{
2236
    const char *cacheCtl = "Cache-Control: no-cache";
2237
    return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path),
2238
        ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize);
2239
}
2240
2241
static const char* ocspAppStrList[] = {
2242
    "application/ocsp-response",
2243
    NULL
2244
};
2245
2246
int wolfIO_HttpProcessResponseOcspGenericIO(
2247
    WolfSSLGenericIORecvCb ioCb, void* ioCbCtx, unsigned char** respBuf,
2248
    unsigned char* httpBuf, int httpBufSz, void* heap)
2249
{
2250
    return wolfIO_HttpProcessResponseGenericIO(ioCb, ioCbCtx,
2251
          ocspAppStrList, respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2252
}
2253
2254
/* return: >0 OCSP Response Size
2255
 *         -1 error */
2256
int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
2257
                                       byte* httpBuf, int httpBufSz, void* heap)
2258
{
2259
    return wolfIO_HttpProcessResponse(sfd, ocspAppStrList,
2260
        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2261
}
2262
2263
/* in default wolfSSL callback ctx is the heap pointer */
2264
int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
2265
                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
2266
{
2267
    SOCKET_T sfd = SOCKET_INVALID;
2268
    word16   port;
2269
    int      ret = -1;
2270
#ifdef WOLFSSL_SMALL_STACK
2271
    char*    path;
2272
    char*    domainName;
2273
#else
2274
    char     path[MAX_URL_ITEM_SIZE];
2275
    char     domainName[MAX_URL_ITEM_SIZE];
2276
#endif
2277
2278
#ifdef WOLFSSL_SMALL_STACK
2279
    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2280
    if (path == NULL)
2281
        return MEMORY_E;
2282
2283
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL,
2284
            DYNAMIC_TYPE_TMP_BUFFER);
2285
    if (domainName == NULL) {
2286
        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2287
        return MEMORY_E;
2288
    }
2289
#endif
2290
2291
    if (ocspReqBuf == NULL || ocspReqSz == 0) {
2292
        WOLFSSL_MSG("OCSP request is required for lookup");
2293
    }
2294
    else if (ocspRespBuf == NULL) {
2295
        WOLFSSL_MSG("Cannot save OCSP response");
2296
    }
2297
    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
2298
        WOLFSSL_MSG("Unable to decode OCSP URL");
2299
    }
2300
    else {
2301
        /* Note, the library uses the EmbedOcspRespFree() callback to
2302
         * free this buffer. */
2303
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2304
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
2305
2306
        if (httpBuf == NULL) {
2307
            WOLFSSL_MSG("Unable to create OCSP response buffer");
2308
        }
2309
        else {
2310
            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
2311
                                                            httpBuf, httpBufSz);
2312
2313
            if (httpBufSz <= 0) {
2314
                WOLFSSL_MSG("Unable to build OCSP request");
2315
            }
2316
            else if ((ret = wolfIO_TcpConnect(&sfd, domainName, port,
2317
                                              io_timeout_sec)) != 0) {
2318
                WOLFSSL_MSG("OCSP Responder connection failed");
2319
            }
2320
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
2321
                                                                    httpBufSz) {
2322
                WOLFSSL_MSG("OCSP http request failed");
2323
            }
2324
            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
2325
                                                                    ocspReqSz) {
2326
                WOLFSSL_MSG("OCSP ocsp request failed");
2327
            }
2328
            else {
2329
                ret = wolfIO_HttpProcessResponseOcsp((int)sfd, ocspRespBuf, httpBuf,
2330
                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
2331
            }
2332
            if (sfd != SOCKET_INVALID)
2333
                CloseSocket(sfd);
2334
            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
2335
        }
2336
    }
2337
2338
    WC_FREE_VAR_EX(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2339
    WC_FREE_VAR_EX(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2340
2341
    return ret;
2342
}
2343
2344
/* in default callback ctx is heap hint */
2345
void EmbedOcspRespFree(void* ctx, byte *resp)
2346
{
2347
    XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
2348
2349
    (void)ctx;
2350
}
2351
#endif /* HAVE_OCSP */
2352
2353
2354
#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
2355
2356
int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
2357
    const char* domainName, byte* buf, int bufSize)
2358
{
2359
    const char *cacheCtl = "Cache-Control: no-cache";
2360
    return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "",
2361
                                   cacheCtl, buf, bufSize);
2362
}
2363
2364
int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
2365
    int httpBufSz)
2366
{
2367
    int ret;
2368
    byte *respBuf = NULL;
2369
2370
    const char* appStrList[] = {
2371
        "application/pkix-crl",
2372
        "application/x-pkcs7-crl",
2373
        NULL
2374
    };
2375
2376
2377
    ret = wolfIO_HttpProcessResponse(sfd, appStrList,
2378
        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
2379
    if (ret >= 0) {
2380
        ret = BufferLoadCRL(crl, respBuf, ret, WOLFSSL_FILETYPE_ASN1, 0);
2381
    }
2382
    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
2383
2384
    return ret;
2385
}
2386
2387
int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
2388
{
2389
    SOCKET_T sfd = SOCKET_INVALID;
2390
    word16   port;
2391
    int      ret = -1;
2392
    WC_DECLARE_VAR(domainName, char, MAX_URL_ITEM_SIZE, 0);
2393
2394
#ifdef WOLFSSL_SMALL_STACK
2395
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
2396
                                                       DYNAMIC_TYPE_TMP_BUFFER);
2397
    if (domainName == NULL) {
2398
        return MEMORY_E;
2399
    }
2400
#endif
2401
2402
    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
2403
        WOLFSSL_MSG("Unable to decode CRL URL");
2404
    }
2405
    else {
2406
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2407
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, crl->heap,
2408
                                                              DYNAMIC_TYPE_CRL);
2409
        if (httpBuf == NULL) {
2410
            WOLFSSL_MSG("Unable to create CRL response buffer");
2411
        }
2412
        else {
2413
            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
2414
                httpBuf, httpBufSz);
2415
2416
            if (httpBufSz <= 0) {
2417
                WOLFSSL_MSG("Unable to build CRL request");
2418
            }
2419
            else if ((ret = wolfIO_TcpConnect(&sfd, domainName, port,
2420
                                              io_timeout_sec)) != 0) {
2421
                WOLFSSL_MSG("CRL connection failed");
2422
            }
2423
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
2424
                                                                 != httpBufSz) {
2425
                WOLFSSL_MSG("CRL http get failed");
2426
            }
2427
            else {
2428
                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
2429
                                                      HTTP_SCRATCH_BUFFER_SIZE);
2430
            }
2431
            if (sfd != SOCKET_INVALID)
2432
                CloseSocket(sfd);
2433
            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
2434
        }
2435
    }
2436
2437
    WC_FREE_VAR_EX(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
2438
2439
    return ret;
2440
}
2441
#endif /* HAVE_CRL && HAVE_CRL_IO */
2442
2443
#endif /* HAVE_HTTP_CLIENT */
2444
2445
2446
2447
void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
2448
0
{
2449
0
    if (ctx) {
2450
0
        ctx->CBIORecv = CBIORecv;
2451
    #ifdef OPENSSL_EXTRA
2452
        ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
2453
    #endif
2454
0
    }
2455
0
}
2456
2457
2458
void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
2459
0
{
2460
0
    if (ctx) {
2461
0
        ctx->CBIOSend = CBIOSend;
2462
    #ifdef OPENSSL_EXTRA
2463
        ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
2464
    #endif
2465
0
    }
2466
0
}
2467
2468
2469
/* sets the IO callback to use for receives at WOLFSSL level */
2470
void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv)
2471
0
{
2472
0
    if (ssl) {
2473
0
        ssl->CBIORecv = CBIORecv;
2474
    #ifdef OPENSSL_EXTRA
2475
        ssl->cbioFlag |= WOLFSSL_CBIO_RECV;
2476
    #endif
2477
0
    }
2478
0
}
2479
2480
2481
/* sets the IO callback to use for sends at WOLFSSL level */
2482
void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
2483
0
{
2484
0
    if (ssl) {
2485
0
        ssl->CBIOSend = CBIOSend;
2486
    #ifdef OPENSSL_EXTRA
2487
        ssl->cbioFlag |= WOLFSSL_CBIO_SEND;
2488
    #endif
2489
0
    }
2490
0
}
2491
2492
void wolfSSL_SSLDisableRead(WOLFSSL *ssl)
2493
0
{
2494
0
    if (ssl) {
2495
0
        ssl->options.disableRead = 1;
2496
0
    }
2497
0
}
2498
2499
void wolfSSL_SSLEnableRead(WOLFSSL *ssl)
2500
0
{
2501
0
    if (ssl) {
2502
0
        ssl->options.disableRead = 0;
2503
0
    }
2504
0
}
2505
2506
2507
void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
2508
0
{
2509
0
    if (ssl)
2510
0
        ssl->IOCB_ReadCtx = rctx;
2511
0
}
2512
2513
2514
void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
2515
0
{
2516
0
    if (ssl)
2517
0
        ssl->IOCB_WriteCtx = wctx;
2518
0
}
2519
2520
2521
void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
2522
0
{
2523
0
    if (ssl)
2524
0
        return ssl->IOCB_ReadCtx;
2525
2526
0
    return NULL;
2527
0
}
2528
2529
2530
void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
2531
0
{
2532
0
    if (ssl)
2533
0
        return ssl->IOCB_WriteCtx;
2534
2535
0
    return NULL;
2536
0
}
2537
2538
2539
void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
2540
0
{
2541
0
    if (ssl)
2542
0
        ssl->rflags = flags;
2543
0
}
2544
2545
2546
void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
2547
0
{
2548
0
    if (ssl)
2549
0
        ssl->wflags = flags;
2550
0
}
2551
2552
2553
#ifdef WOLFSSL_DTLS
2554
2555
void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
2556
{
2557
    if (ctx)
2558
        ctx->CBIOCookie = cb;
2559
}
2560
2561
2562
void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
2563
{
2564
    if (ssl)
2565
        ssl->IOCB_CookieCtx = ctx;
2566
}
2567
2568
2569
void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
2570
{
2571
    if (ssl)
2572
        return ssl->IOCB_CookieCtx;
2573
2574
    return NULL;
2575
}
2576
#endif /* WOLFSSL_DTLS */
2577
2578
#ifdef WOLFSSL_SESSION_EXPORT
2579
2580
void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
2581
{
2582
    if (ctx)
2583
        ctx->CBGetPeer = cb;
2584
}
2585
2586
2587
void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
2588
{
2589
    if (ctx)
2590
        ctx->CBSetPeer = cb;
2591
}
2592
2593
#endif /* WOLFSSL_SESSION_EXPORT */
2594
2595
2596
#ifdef HAVE_NETX
2597
2598
/* The NetX receive callback for TLS
2599
 *  return :  bytes read, or error
2600
 */
2601
int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2602
{
2603
    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
2604
    ULONG left;
2605
    ULONG total;
2606
    ULONG copied = 0;
2607
    UINT  status;
2608
2609
    (void)ssl;
2610
2611
    if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
2612
        WOLFSSL_MSG("NetX Recv NULL parameters");
2613
        return WOLFSSL_CBIO_ERR_GENERAL;
2614
    }
2615
2616
    if (nxCtx->nxPacket == NULL) {
2617
        status = nx_tcp_socket_receive(nxCtx->nxTcpSocket, &nxCtx->nxPacket,
2618
                                       nxCtx->nxWait);
2619
        if (status != NX_SUCCESS) {
2620
            WOLFSSL_MSG("NetX Recv receive error");
2621
            return WOLFSSL_CBIO_ERR_GENERAL;
2622
        }
2623
    }
2624
2625
    if (nxCtx->nxPacket) {
2626
        status = nx_packet_length_get(nxCtx->nxPacket, &total);
2627
        if (status != NX_SUCCESS) {
2628
            WOLFSSL_MSG("NetX Recv length get error");
2629
            return WOLFSSL_CBIO_ERR_GENERAL;
2630
        }
2631
2632
        left = total - nxCtx->nxOffset;
2633
        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
2634
                                               buf, sz, &copied);
2635
        if (status != NX_SUCCESS) {
2636
            WOLFSSL_MSG("NetX Recv data extract offset error");
2637
            return WOLFSSL_CBIO_ERR_GENERAL;
2638
        }
2639
2640
        nxCtx->nxOffset += copied;
2641
2642
        if (copied == left) {
2643
            WOLFSSL_MSG("NetX Recv Drained packet");
2644
            nx_packet_release(nxCtx->nxPacket);
2645
            nxCtx->nxPacket = NULL;
2646
            nxCtx->nxOffset = 0;
2647
        }
2648
    }
2649
2650
    return copied;
2651
}
2652
2653
2654
/* The NetX send callback for TLS
2655
 *  return : bytes sent, or error
2656
 */
2657
int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2658
{
2659
    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
2660
    NX_PACKET*      packet;
2661
    NX_PACKET_POOL* pool;   /* shorthand */
2662
    UINT            status;
2663
2664
    (void)ssl;
2665
2666
    if (nxCtx == NULL || nxCtx->nxTcpSocket == NULL) {
2667
        WOLFSSL_MSG("NetX Send NULL parameters");
2668
        return WOLFSSL_CBIO_ERR_GENERAL;
2669
    }
2670
2671
    pool = nxCtx->nxTcpSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
2672
    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
2673
                                nxCtx->nxWait);
2674
    if (status != NX_SUCCESS) {
2675
        WOLFSSL_MSG("NetX Send packet alloc error");
2676
        return WOLFSSL_CBIO_ERR_GENERAL;
2677
    }
2678
2679
    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
2680
    if (status != NX_SUCCESS) {
2681
        nx_packet_release(packet);
2682
        WOLFSSL_MSG("NetX Send data append error");
2683
        return WOLFSSL_CBIO_ERR_GENERAL;
2684
    }
2685
2686
    status = nx_tcp_socket_send(nxCtx->nxTcpSocket, packet, nxCtx->nxWait);
2687
    if (status != NX_SUCCESS) {
2688
        nx_packet_release(packet);
2689
        WOLFSSL_MSG("NetX Send socket send error");
2690
        return WOLFSSL_CBIO_ERR_GENERAL;
2691
    }
2692
2693
    return sz;
2694
}
2695
2696
/* like set_fd, but for default NetX context */
2697
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, ULONG waitoption)
2698
{
2699
    if (ssl) {
2700
        ssl->nxCtx.nxTcpSocket  = nxsocket;
2701
        ssl->nxCtx.nxWait       = waitoption;
2702
    }
2703
}
2704
2705
/* WOLFSSL_NETX_DUO: requires ThreadX NetX Duo (NXD_ADDRESS, nxd_udp_socket_send) */
2706
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_NETX_DUO)
2707
static void NetX_ResetPacket(NetX_Ctx* nxCtx)
2708
{
2709
    if (nxCtx->nxPacket != NULL) {
2710
        nx_packet_release(nxCtx->nxPacket);
2711
        nxCtx->nxPacket = NULL;
2712
    }
2713
    nxCtx->nxOffset = 0;
2714
}
2715
2716
static int NetX_PeerAddrEqual(const NXD_ADDRESS* left, const NXD_ADDRESS* right)
2717
{
2718
    if (left->nxd_ip_version != right->nxd_ip_version)
2719
        return 0;
2720
2721
    if (left->nxd_ip_version == NX_IP_VERSION_V4)
2722
        return left->nxd_ip_address.v4 == right->nxd_ip_address.v4;
2723
2724
    return left->nxd_ip_address.v6[0] == right->nxd_ip_address.v6[0] &&
2725
           left->nxd_ip_address.v6[1] == right->nxd_ip_address.v6[1] &&
2726
           left->nxd_ip_address.v6[2] == right->nxd_ip_address.v6[2] &&
2727
           left->nxd_ip_address.v6[3] == right->nxd_ip_address.v6[3];
2728
}
2729
2730
/* The NetX receive callback for DTLS
2731
 *  return :  bytes read, or error
2732
 */
2733
int NetX_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2734
{
2735
    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
2736
    NXD_ADDRESS srcIp;
2737
    ULONG left;
2738
    ULONG total;
2739
    ULONG copied = 0;
2740
    UINT  srcPort;
2741
    UINT  status;
2742
    ULONG waitOption;
2743
    int   dtls_timeout;
2744
    int   usingNonblock;
2745
    byte  doDtlsTimeout;
2746
    word32 invalidPeerPackets = 0;
2747
#if defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
2748
    const word32 maxInvalidPeerPackets = DTLS_RECEIVEFROM_MAX_INVALID_PEER;
2749
#else
2750
    const word32 maxInvalidPeerPackets = 10;
2751
#endif
2752
2753
    if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
2754
        WOLFSSL_MSG("NetX Recv NULL parameters");
2755
        return WOLFSSL_CBIO_ERR_GENERAL;
2756
    }
2757
2758
    if (sz < 0)
2759
        return WOLFSSL_CBIO_ERR_GENERAL;
2760
2761
    usingNonblock = wolfSSL_dtls_get_using_nonblock(ssl);
2762
2763
    /* Don't use ssl->options.handShakeDone since it is true even if
2764
     * we are in the process of renegotiation. */
2765
    doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
2766
#ifdef WOLFSSL_DTLS13
2767
    if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
2768
        doDtlsTimeout =
2769
            doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
2770
            (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
2771
    }
2772
#endif /* WOLFSSL_DTLS13 */
2773
2774
    do {
2775
        if (nxCtx->nxPacket == NULL) {
2776
            /* Compute wait ticks from the DTLS retransmit timeout while a
2777
             * handshake/RTX timer is active, otherwise honor nxWait. */
2778
            if (!usingNonblock) {
2779
                dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
2780
                if (!doDtlsTimeout)
2781
                    dtls_timeout = 0;
2782
#ifdef WOLFSSL_DTLS13
2783
                if (dtls_timeout > 0 && wolfSSL_dtls13_use_quick_timeout(ssl) &&
2784
                    IsAtLeastTLSv1_3(ssl->version)) {
2785
                    if (dtls_timeout > 4)
2786
                        dtls_timeout /= 4;
2787
                    else
2788
                        dtls_timeout = 1;
2789
                }
2790
#endif /* WOLFSSL_DTLS13 */
2791
                waitOption = (dtls_timeout > 0)
2792
                             ? (ULONG)dtls_timeout * NX_IP_PERIODIC_RATE
2793
                             : nxCtx->nxWait;
2794
            }
2795
            else {
2796
                waitOption = NX_NO_WAIT; /* non-blocking */
2797
            }
2798
2799
            status = nx_udp_socket_receive(nxCtx->nxUdpSocket, &nxCtx->nxPacket,
2800
                                           waitOption);
2801
            if (status != NX_SUCCESS) {
2802
                if (status == NX_NO_PACKET) {
2803
                    /* Normal receive timeout - allow DTLS to retransmit */
2804
                    WOLFSSL_MSG("NetX Recv timeout");
2805
                    return usingNonblock
2806
                           ? WOLFSSL_CBIO_ERR_WANT_READ
2807
                           : WOLFSSL_CBIO_ERR_TIMEOUT;
2808
                }
2809
                WOLFSSL_MSG("NetX Recv receive error");
2810
                return WOLFSSL_CBIO_ERR_GENERAL;
2811
            }
2812
2813
            status = nxd_udp_source_extract(nxCtx->nxPacket, &srcIp, &srcPort);
2814
            if (status != NX_SUCCESS) {
2815
                NetX_ResetPacket(nxCtx);
2816
                WOLFSSL_MSG("NetX Recv source extract error");
2817
                return WOLFSSL_CBIO_ERR_GENERAL;
2818
            }
2819
2820
            if (nxCtx->nxPort != 0 &&
2821
                (nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V4 ||
2822
                 nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V6)) {
2823
                if ((USHORT)srcPort != nxCtx->nxPort ||
2824
                    !NetX_PeerAddrEqual(&srcIp, &nxCtx->nxdIp)) {
2825
                    WOLFSSL_MSG("NetX Recv ignored packet from invalid peer");
2826
                    NetX_ResetPacket(nxCtx);
2827
                    /* Intentional: bound discard only during handshake/RTX
2828
                     * window (doDtlsTimeout). Post-handshake, spoofed-source
2829
                     * packets loop until a valid one arrives. This matches
2830
                     * the EmbedReceiveFrom behavior. */
2831
                    if (doDtlsTimeout) {
2832
                        invalidPeerPackets++;
2833
                        if (invalidPeerPackets > maxInvalidPeerPackets) {
2834
                            return usingNonblock
2835
                                   ? WOLFSSL_CBIO_ERR_WANT_READ
2836
                                   : WOLFSSL_CBIO_ERR_TIMEOUT;
2837
                        }
2838
                    }
2839
                    continue;
2840
                }
2841
            }
2842
            else {
2843
                /* No peer preset: accept first datagram and lock onto source. */
2844
                nxCtx->nxdIp = srcIp;
2845
                nxCtx->nxPort = (USHORT)srcPort;
2846
            }
2847
        }
2848
2849
        status = nx_packet_length_get(nxCtx->nxPacket, &total);
2850
        if (status != NX_SUCCESS) {
2851
            NetX_ResetPacket(nxCtx);
2852
            WOLFSSL_MSG("NetX Recv length get error");
2853
            return WOLFSSL_CBIO_ERR_GENERAL;
2854
        }
2855
2856
        if (total == 0) {
2857
            WOLFSSL_MSG("Ignoring 0-length datagram");
2858
            NetX_ResetPacket(nxCtx);
2859
            /* Intentional: same discard-bound semantics as invalid-peer
2860
             * handling above and EmbedReceiveFrom: only bounded during
2861
             * handshake, loops post-handshake until a valid datagram
2862
             * arrives. */
2863
            if (doDtlsTimeout) {
2864
                invalidPeerPackets++;
2865
                if (invalidPeerPackets > maxInvalidPeerPackets) {
2866
                    return usingNonblock
2867
                           ? WOLFSSL_CBIO_ERR_WANT_READ
2868
                           : WOLFSSL_CBIO_ERR_TIMEOUT;
2869
                }
2870
            }
2871
            continue;
2872
        }
2873
2874
        if (nxCtx->nxOffset > total) {
2875
            NetX_ResetPacket(nxCtx);
2876
            WOLFSSL_MSG("NetX Recv invalid packet offset");
2877
            return WOLFSSL_CBIO_ERR_GENERAL;
2878
        }
2879
2880
        left = total - nxCtx->nxOffset;
2881
        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
2882
                                               buf, sz, &copied);
2883
        if (status != NX_SUCCESS) {
2884
            NetX_ResetPacket(nxCtx);
2885
            WOLFSSL_MSG("NetX Recv data extract offset error");
2886
            return WOLFSSL_CBIO_ERR_GENERAL;
2887
        }
2888
2889
        /* DTLS datagram semantics: always release the full datagram after one
2890
         * read. If the caller's buffer (sz) is smaller than the datagram,
2891
         * the excess bytes are discarded here, matching EmbedReceiveFrom /
2892
         * recvfrom behavior. Partial-datagram retention would re-introduce
2893
         * TCP stream semantics and could mis-frame DTLS records. */
2894
        if (copied < left) {
2895
            WOLFSSL_MSG("NetX Recv datagram truncated, discarding remainder");
2896
        }
2897
        NetX_ResetPacket(nxCtx);
2898
2899
        return (int)copied;
2900
    } while (1);
2901
}
2902
2903
/* The NetX send callback for DTLS
2904
 *  return : bytes sent, or error
2905
 */
2906
int NetX_SendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2907
{
2908
    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
2909
    NX_PACKET*      packet;
2910
    NX_PACKET_POOL* pool;   /* shorthand */
2911
    UINT            status;
2912
2913
    (void)ssl;
2914
2915
    if (nxCtx == NULL || nxCtx->nxUdpSocket == NULL) {
2916
        WOLFSSL_MSG("NetX Send NULL parameters");
2917
        return WOLFSSL_CBIO_ERR_GENERAL;
2918
    }
2919
2920
    if (sz < 0)
2921
        return WOLFSSL_CBIO_ERR_GENERAL;
2922
2923
    pool = nxCtx->nxUdpSocket->nx_udp_socket_ip_ptr->nx_ip_default_packet_pool;
2924
    status = nx_packet_allocate(pool, &packet, NX_UDP_PACKET,
2925
                                nxCtx->nxWait);
2926
    if (status != NX_SUCCESS) {
2927
        WOLFSSL_MSG("NetX Send packet alloc error");
2928
        return WOLFSSL_CBIO_ERR_GENERAL;
2929
    }
2930
2931
    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
2932
    if (status != NX_SUCCESS) {
2933
        nx_packet_release(packet);
2934
        WOLFSSL_MSG("NetX Send data append error");
2935
        return WOLFSSL_CBIO_ERR_GENERAL;
2936
    }
2937
2938
    if (nxCtx->nxdIp.nxd_ip_version == NX_IP_VERSION_V4) {
2939
        status = nx_udp_socket_send(nxCtx->nxUdpSocket, packet,
2940
                                    nxCtx->nxdIp.nxd_ip_address.v4,
2941
                                    (UINT)nxCtx->nxPort);
2942
    }
2943
    else {
2944
        status = nxd_udp_socket_send(nxCtx->nxUdpSocket, packet,
2945
                                     &nxCtx->nxdIp, (UINT)nxCtx->nxPort);
2946
    }
2947
    if (status != NX_SUCCESS) {
2948
        nx_packet_release(packet);
2949
        WOLFSSL_MSG("NetX Send socket send error");
2950
        return WOLFSSL_CBIO_ERR_GENERAL;
2951
    }
2952
2953
    return sz;
2954
}
2955
2956
/* like set_fd, but for default NetX Duo UDP context */
2957
void wolfSSL_SetIO_NetX_Dtls(WOLFSSL* ssl, NX_UDP_SOCKET* nxsocket,
2958
                              NXD_ADDRESS nxdip, USHORT nxport,
2959
                              ULONG waitoption)
2960
{
2961
    if (ssl) {
2962
        ssl->nxCtx.nxUdpSocket = nxsocket;
2963
        ssl->nxCtx.nxdIp       = nxdip;
2964
        ssl->nxCtx.nxPort      = nxport;
2965
        ssl->nxCtx.nxWait      = waitoption;
2966
    }
2967
}
2968
#endif /* WOLFSSL_DTLS && WOLFSSL_NETX_DUO */
2969
2970
#endif /* HAVE_NETX */
2971
2972
2973
#ifdef MICRIUM
2974
2975
/* Micrium uTCP/IP port, using the NetSock API
2976
 * TCP and UDP are currently supported with the callbacks below.
2977
 *
2978
 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
2979
 * and EmbedSetPeer() callbacks implemented.
2980
 *
2981
 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
2982
 * callback implemented.
2983
 *
2984
 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
2985
 * callback implemented.
2986
 */
2987
2988
/* The Micrium uTCP/IP send callback
2989
 * return : bytes sent, or error
2990
 */
2991
int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2992
{
2993
    NET_SOCK_ID sd = *(int*)ctx;
2994
    NET_SOCK_RTN_CODE ret;
2995
    NET_ERR err;
2996
2997
    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
2998
    if (ret < 0) {
2999
        WOLFSSL_MSG("Embed Send error");
3000
3001
        if (err == NET_ERR_TX) {
3002
            WOLFSSL_MSG("\tWould block");
3003
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
3004
3005
        } else {
3006
            WOLFSSL_MSG("\tGeneral error");
3007
            return WOLFSSL_CBIO_ERR_GENERAL;
3008
        }
3009
    }
3010
3011
    return ret;
3012
}
3013
3014
/* The Micrium uTCP/IP receive callback
3015
 *  return : nb bytes read, or error
3016
 */
3017
int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3018
{
3019
    NET_SOCK_ID sd = *(int*)ctx;
3020
    NET_SOCK_RTN_CODE ret;
3021
    NET_ERR err;
3022
3023
    #ifdef WOLFSSL_DTLS
3024
    {
3025
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
3026
        /* Don't use ssl->options.handShakeDone since it is true even if
3027
         * we are in the process of renegotiation */
3028
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
3029
        #ifdef WOLFSSL_DTLS13
3030
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
3031
            doDtlsTimeout =
3032
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
3033
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
3034
        }
3035
        #endif /* WOLFSSL_DTLS13 */
3036
3037
        if (!doDtlsTimeout)
3038
            dtls_timeout = 0;
3039
3040
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
3041
            /* needs timeout in milliseconds */
3042
            #ifdef WOLFSSL_DTLS13
3043
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
3044
                IsAtLeastTLSv1_3(ssl->version)) {
3045
                dtls_timeout = (1000 * dtls_timeout) / 4;
3046
            } else
3047
            #endif /* WOLFSSL_DTLS13 */
3048
                dtls_timeout = 1000 * dtls_timeout;
3049
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
3050
            if (err != NET_SOCK_ERR_NONE) {
3051
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
3052
            }
3053
        }
3054
    }
3055
    #endif /* WOLFSSL_DTLS */
3056
3057
    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
3058
    if (ret < 0) {
3059
        WOLFSSL_MSG("Embed Receive error");
3060
3061
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
3062
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
3063
            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
3064
                WOLFSSL_MSG("\tWould block");
3065
                return WOLFSSL_CBIO_ERR_WANT_READ;
3066
            }
3067
            else {
3068
                WOLFSSL_MSG("\tSocket timeout");
3069
                return WOLFSSL_CBIO_ERR_TIMEOUT;
3070
            }
3071
3072
        } else if (err == NET_SOCK_ERR_CLOSED) {
3073
            WOLFSSL_MSG("Embed receive connection closed");
3074
            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
3075
3076
        } else {
3077
            WOLFSSL_MSG("\tGeneral error");
3078
            return WOLFSSL_CBIO_ERR_GENERAL;
3079
        }
3080
    }
3081
3082
    return ret;
3083
}
3084
3085
/* The Micrium uTCP/IP receivefrom callback
3086
 *  return : nb bytes read, or error
3087
 */
3088
int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3089
{
3090
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
3091
    NET_SOCK_ID       sd = dtlsCtx->rfd;
3092
    NET_SOCK_ADDR     peer;
3093
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
3094
    NET_SOCK_RTN_CODE ret;
3095
    NET_ERR err;
3096
3097
    WOLFSSL_ENTER("MicriumReceiveFrom");
3098
3099
#ifdef WOLFSSL_DTLS
3100
    {
3101
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
3102
        /* Don't use ssl->options.handShakeDone since it is true even if
3103
         * we are in the process of renegotiation */
3104
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
3105
3106
        #ifdef WOLFSSL_DTLS13
3107
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
3108
            doDtlsTimeout =
3109
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
3110
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
3111
        }
3112
        #endif /* WOLFSSL_DTLS13 */
3113
3114
        if (!doDtlsTimeout)
3115
            dtls_timeout = 0;
3116
3117
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
3118
            /* needs timeout in milliseconds */
3119
            #ifdef WOLFSSL_DTLS13
3120
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
3121
                IsAtLeastTLSv1_3(ssl->version)) {
3122
                dtls_timeout = (1000 * dtls_timeout) / 4;
3123
            } else
3124
            #endif /* WOLFSSL_DTLS13 */
3125
                dtls_timeout = 1000 * dtls_timeout;
3126
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
3127
            if (err != NET_SOCK_ERR_NONE) {
3128
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
3129
            }
3130
        }
3131
    }
3132
#endif /* WOLFSSL_DTLS */
3133
3134
    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
3135
                             0, 0, 0, &err);
3136
    if (ret < 0) {
3137
        WOLFSSL_MSG("Embed Receive From error");
3138
3139
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
3140
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
3141
            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
3142
                WOLFSSL_MSG("\tWould block");
3143
                return WOLFSSL_CBIO_ERR_WANT_READ;
3144
            }
3145
            else {
3146
                WOLFSSL_MSG("\tSocket timeout");
3147
                return WOLFSSL_CBIO_ERR_TIMEOUT;
3148
            }
3149
        } else {
3150
            WOLFSSL_MSG("\tGeneral error");
3151
            return WOLFSSL_CBIO_ERR_GENERAL;
3152
        }
3153
    }
3154
    else {
3155
        if (dtlsCtx->peer.sz > 0) {
3156
            NET_SOCK_ADDR_LEN expectedPeerSz =
3157
                (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz;
3158
            if (dtlsCtx->peer.sa == NULL ||
3159
                peerSz != expectedPeerSz ||
3160
                XMEMCMP(&peer, dtlsCtx->peer.sa, expectedPeerSz) != 0) {
3161
                WOLFSSL_MSG("\tIgnored packet from invalid peer");
3162
                return WOLFSSL_CBIO_ERR_WANT_READ;
3163
            }
3164
        }
3165
    }
3166
3167
    return ret;
3168
}
3169
3170
/* The Micrium uTCP/IP sendto callback
3171
 *  return : nb bytes sent, or error
3172
 */
3173
int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
3174
{
3175
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
3176
    NET_SOCK_ID sd = dtlsCtx->wfd;
3177
    NET_SOCK_RTN_CODE ret;
3178
    NET_ERR err;
3179
3180
    WOLFSSL_ENTER("MicriumSendTo");
3181
3182
    ret = NetSock_TxDataTo(sd, buf, sz, ssl->wflags,
3183
                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
3184
                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
3185
                           &err);
3186
    if (err < 0) {
3187
        WOLFSSL_MSG("Embed Send To error");
3188
3189
        if (err == NET_ERR_TX) {
3190
            WOLFSSL_MSG("\tWould block");
3191
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
3192
3193
        } else {
3194
            WOLFSSL_MSG("\tGeneral error");
3195
            return WOLFSSL_CBIO_ERR_GENERAL;
3196
        }
3197
    }
3198
3199
    return ret;
3200
}
3201
3202
/* Micrium DTLS Generate Cookie callback
3203
 *  return : number of bytes copied into buf, or error
3204
 */
3205
#if defined(NO_SHA) && !defined(NO_SHA256)
3206
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3207
#elif !defined(NO_SHA)
3208
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3209
#else
3210
    #error Must enable either SHA-1 or SHA256 (or both) for Micrium.
3211
#endif
3212
int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
3213
{
3214
    NET_SOCK_ADDR peer;
3215
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
3216
    byte digest[MICRIUM_COOKIE_DIGEST_SIZE];
3217
    int  ret = 0;
3218
3219
    (void)ctx;
3220
3221
    XMEMSET(&peer, 0, sizeof(peer));
3222
    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
3223
                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
3224
        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
3225
        return GEN_COOKIE_E;
3226
    }
3227
3228
#if defined(NO_SHA) && !defined(NO_SHA256)
3229
    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
3230
#else
3231
    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
3232
#endif
3233
    if (ret != 0)
3234
        return ret;
3235
3236
    if (sz > MICRIUM_COOKIE_DIGEST_SIZE)
3237
        sz = MICRIUM_COOKIE_DIGEST_SIZE;
3238
    XMEMCPY(buf, digest, sz);
3239
3240
    return sz;
3241
}
3242
3243
#endif /* MICRIUM */
3244
3245
#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
3246
3247
#include <os/os_error.h>
3248
#include <os/os_mbuf.h>
3249
#include <os/os_mempool.h>
3250
3251
#define MB_NAME "wolfssl_mb"
3252
3253
typedef struct Mynewt_Ctx {
3254
        struct mn_socket *mnSocket;          /* send/recv socket handler */
3255
        struct mn_sockaddr_in mnSockAddrIn;  /* socket address */
3256
        struct os_mbuf *mnPacket;            /* incoming packet handle
3257
                                                for short reads */
3258
        int reading;                         /* reading flag */
3259
3260
        /* private */
3261
        void *mnMemBuffer;                   /* memory buffer for mempool */
3262
        struct os_mempool mnMempool;         /* mempool */
3263
        struct os_mbuf_pool mnMbufpool;      /* mbuf pool */
3264
} Mynewt_Ctx;
3265
3266
void mynewt_ctx_clear(void *ctx) {
3267
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3268
    if(!mynewt_ctx) return;
3269
3270
    if(mynewt_ctx->mnPacket) {
3271
        os_mbuf_free_chain(mynewt_ctx->mnPacket);
3272
        mynewt_ctx->mnPacket = NULL;
3273
    }
3274
    os_mempool_clear(&mynewt_ctx->mnMempool);
3275
    XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
3276
    XFREE(mynewt_ctx, 0, 0);
3277
}
3278
3279
/* return Mynewt_Ctx instance */
3280
void* mynewt_ctx_new() {
3281
    int rc = 0;
3282
    Mynewt_Ctx *mynewt_ctx;
3283
    int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
3284
    int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
3285
    int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
3286
3287
    mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
3288
                                       NULL, DYNAMIC_TYPE_TMP_BUFFER);
3289
    if(!mynewt_ctx) return NULL;
3290
3291
    XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
3292
    mynewt_ctx->mnMemBuffer = (void *)XMALLOC(mempool_bytes, 0, 0);
3293
    if(!mynewt_ctx->mnMemBuffer) {
3294
        mynewt_ctx_clear((void*)mynewt_ctx);
3295
        return NULL;
3296
    }
3297
3298
    rc = os_mempool_init(&mynewt_ctx->mnMempool,
3299
                         mem_buf_count, mem_buf_size,
3300
                         mynewt_ctx->mnMemBuffer, MB_NAME);
3301
    if(rc != 0) {
3302
        mynewt_ctx_clear((void*)mynewt_ctx);
3303
        return NULL;
3304
    }
3305
    rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
3306
                           mem_buf_count, mem_buf_size);
3307
    if(rc != 0) {
3308
        mynewt_ctx_clear((void*)mynewt_ctx);
3309
        return NULL;
3310
    }
3311
3312
    return mynewt_ctx;
3313
}
3314
3315
static void mynewt_sock_writable(void *arg, int err);
3316
static void mynewt_sock_readable(void *arg, int err);
3317
static const union mn_socket_cb mynewt_sock_cbs = {
3318
    .socket.writable = mynewt_sock_writable,
3319
    .socket.readable = mynewt_sock_readable,
3320
};
3321
static void mynewt_sock_writable(void *arg, int err)
3322
{
3323
    /* do nothing */
3324
}
3325
static void mynewt_sock_readable(void *arg, int err)
3326
{
3327
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
3328
    if (err && mynewt_ctx->reading) {
3329
        mynewt_ctx->reading = 0;
3330
    }
3331
}
3332
3333
/* The Mynewt receive callback
3334
 *  return :  bytes read, or error
3335
 */
3336
int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
3337
{
3338
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3339
    int rc = 0;
3340
    struct mn_sockaddr_in from;
3341
    struct os_mbuf *m;
3342
    int read_sz = 0;
3343
    word16 total;
3344
3345
    if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
3346
        WOLFSSL_MSG("Mynewt Recv NULL parameters");
3347
        return WOLFSSL_CBIO_ERR_GENERAL;
3348
    }
3349
3350
    if(mynewt_ctx->mnPacket == NULL) {
3351
        mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
3352
        if(mynewt_ctx->mnPacket == NULL) {
3353
            return MEMORY_E;
3354
        }
3355
3356
        mynewt_ctx->reading = 1;
3357
        while(mynewt_ctx->reading && rc == 0) {
3358
            rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
3359
            if(rc == MN_ECONNABORTED) {
3360
                rc = 0;
3361
                mynewt_ctx->reading = 0;
3362
                break;
3363
            }
3364
            if (!(rc == 0 || rc == MN_EAGAIN)) {
3365
                WOLFSSL_MSG("Mynewt Recv receive error");
3366
                mynewt_ctx->reading = 0;
3367
                break;
3368
            }
3369
            if(rc == 0) {
3370
                int len = OS_MBUF_PKTLEN(m);
3371
                if(len == 0) {
3372
                    break;
3373
                }
3374
                rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
3375
                if(rc != 0) {
3376
                    WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
3377
                    break;
3378
                }
3379
                os_mbuf_free_chain(m);
3380
                m = NULL;
3381
            } else if(rc == MN_EAGAIN) {
3382
                /* continue to until reading all of packet data. */
3383
                rc = 0;
3384
                break;
3385
            }
3386
        }
3387
        if(rc != 0) {
3388
            mynewt_ctx->reading = 0;
3389
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
3390
            mynewt_ctx->mnPacket = NULL;
3391
            return rc;
3392
        }
3393
    }
3394
3395
    if(mynewt_ctx->mnPacket) {
3396
        total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
3397
        read_sz = (total >= sz)? sz : total;
3398
3399
        os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
3400
        os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
3401
3402
        if (read_sz == total) {
3403
            WOLFSSL_MSG("Mynewt Recv Drained packet");
3404
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
3405
            mynewt_ctx->mnPacket = NULL;
3406
        }
3407
    }
3408
3409
    return read_sz;
3410
}
3411
3412
/* The Mynewt send callback
3413
 *  return : bytes sent, or error
3414
 */
3415
int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
3416
{
3417
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
3418
    int rc = 0;
3419
    struct os_mbuf *m;
3420
    int write_sz = 0;
3421
    m = os_msys_get_pkthdr(sz, 0);
3422
    if (!m) {
3423
        WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
3424
        return WOLFSSL_CBIO_ERR_GENERAL;
3425
    }
3426
    rc = os_mbuf_copyinto(m, 0, buf, sz);
3427
    if (rc != 0) {
3428
        WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
3429
        os_mbuf_free_chain(m);
3430
        return rc;
3431
    }
3432
    rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
3433
    if(rc != 0) {
3434
        WOLFSSL_MSG("Mynewt Send mn_sendto error");
3435
        os_mbuf_free_chain(m);
3436
        return rc;
3437
    }
3438
    write_sz = sz;
3439
    return write_sz;
3440
}
3441
3442
/* like set_fd, but for default NetX context */
3443
void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
3444
{
3445
    if (ssl && ssl->mnCtx) {
3446
        Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
3447
        mynewt_ctx->mnSocket = mnSocket;
3448
        XMEMCPY(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
3449
        mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
3450
    }
3451
}
3452
3453
#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
3454
3455
#ifdef WOLFSSL_UIP
3456
#include <uip.h>
3457
#include <stdio.h>
3458
3459
/* uIP TCP/IP port, using the native tcp/udp socket api.
3460
 * TCP and UDP are currently supported with the callbacks below.
3461
 *
3462
 */
3463
/* The uIP tcp send callback
3464
 * return : bytes sent, or error
3465
 */
3466
int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3467
{
3468
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3469
    int total_written = 0;
3470
    (void)ssl;
3471
    do {
3472
        int ret;
3473
        unsigned int bytes_left = sz - total_written;
3474
        unsigned int max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
3475
        if (bytes_left > max_sendlen) {
3476
            fprintf(stderr, "uIPSend: Send limited by buffer\r\n");
3477
            bytes_left = max_sendlen;
3478
        }
3479
        if (bytes_left == 0) {
3480
            fprintf(stderr, "uIPSend: Buffer full!\r\n");
3481
            break;
3482
        }
3483
        ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
3484
        if (ret <= 0)
3485
            break;
3486
        total_written += ret;
3487
    } while(total_written < sz);
3488
    if (total_written == 0)
3489
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3490
    return total_written;
3491
}
3492
3493
int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3494
{
3495
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3496
    int ret = 0;
3497
    (void)ssl;
3498
    ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
3499
    if (ret == 0)
3500
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3501
    return ret;
3502
}
3503
3504
/* The uIP uTCP/IP receive callback
3505
 *  return : nb bytes read, or error
3506
 */
3507
int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3508
{
3509
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3510
    if (!ctx || !ctx->ssl_rx_databuf)
3511
        return WOLFSSL_FATAL_ERROR;
3512
    (void)ssl;
3513
    if (ctx->ssl_rb_len > 0) {
3514
        if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
3515
            sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
3516
        XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
3517
        ctx->ssl_rb_off += sz;
3518
        if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
3519
            ctx->ssl_rb_len = 0;
3520
            ctx->ssl_rb_off = 0;
3521
        }
3522
        return sz;
3523
    } else {
3524
        return WOLFSSL_CBIO_ERR_WANT_READ;
3525
    }
3526
}
3527
3528
/* uIP DTLS Generate Cookie callback
3529
 *  return : number of bytes copied into buf, or error
3530
 */
3531
#if defined(NO_SHA) && !defined(NO_SHA256)
3532
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3533
#elif !defined(NO_SHA)
3534
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3535
#else
3536
    #error Must enable either SHA-1 or SHA256 (or both) for uIP.
3537
#endif
3538
int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3539
{
3540
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3541
    byte token[32];
3542
    byte digest[UIP_COOKIE_DIGEST_SIZE];
3543
    int  ret = 0;
3544
    XMEMSET(token, 0, sizeof(token));
3545
    XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
3546
    XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
3547
#if defined(NO_SHA) && !defined(NO_SHA256)
3548
    ret = wc_Sha256Hash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3549
#else
3550
    ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3551
#endif
3552
    if (ret != 0)
3553
        return ret;
3554
    if (sz > UIP_COOKIE_DIGEST_SIZE)
3555
        sz = UIP_COOKIE_DIGEST_SIZE;
3556
    XMEMCPY(buf, digest, sz);
3557
    return sz;
3558
}
3559
3560
#endif /* WOLFSSL_UIP */
3561
3562
#ifdef WOLFSSL_GNRC
3563
3564
#include <net/sock.h>
3565
#include <net/sock/tcp.h>
3566
#include <stdio.h>
3567
3568
/* GNRC TCP/IP port, using the native tcp/udp socket api.
3569
 * TCP and UDP are currently supported with the callbacks below.
3570
 *
3571
 */
3572
/* The GNRC tcp send callback
3573
 * return : bytes sent, or error
3574
 */
3575
3576
int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3577
{
3578
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3579
    int ret = 0;
3580
    (void)ssl;
3581
    if (!ctx)
3582
        return WOLFSSL_CBIO_ERR_GENERAL;
3583
    ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr);
3584
    if (ret == 0)
3585
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3586
    return ret;
3587
}
3588
3589
/* The GNRC TCP/IP receive callback
3590
 *  return : nb bytes read, or error
3591
 */
3592
int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3593
{
3594
    sock_udp_ep_t ep;
3595
    int ret;
3596
    word32 timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000;
3597
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3598
    if (!ctx)
3599
        return WOLFSSL_CBIO_ERR_GENERAL;
3600
    (void)ssl;
3601
    if (wolfSSL_get_using_nonblock(ctx->ssl)) {
3602
        timeout = 0;
3603
    }
3604
    ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep);
3605
    if (ret > 0) {
3606
        if (ctx->peer_addr.port == 0)
3607
            XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t));
3608
    }
3609
    if (ret == -ETIMEDOUT) {
3610
        return WOLFSSL_CBIO_ERR_WANT_READ;
3611
    }
3612
    return ret;
3613
}
3614
3615
/* GNRC DTLS Generate Cookie callback
3616
 *  return : number of bytes copied into buf, or error
3617
 */
3618
#define GNRC_MAX_TOKEN_SIZE (32)
3619
#if defined(NO_SHA) && !defined(NO_SHA256)
3620
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3621
#elif !defined(NO_SHA)
3622
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3623
#else
3624
    #error Must enable either SHA-1 or SHA256 (or both) for GNRC.
3625
#endif
3626
int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3627
{
3628
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3629
    if (!ctx)
3630
        return WOLFSSL_CBIO_ERR_GENERAL;
3631
    byte token[GNRC_MAX_TOKEN_SIZE];
3632
    byte digest[GNRC_COOKIE_DIGEST_SIZE];
3633
    int  ret = 0;
3634
    size_t token_size = sizeof(sock_udp_ep_t);
3635
    (void)ssl;
3636
    if (token_size > GNRC_MAX_TOKEN_SIZE)
3637
        token_size = GNRC_MAX_TOKEN_SIZE;
3638
    XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE);
3639
    XMEMCPY(token, &ctx->peer_addr, token_size);
3640
#if defined(NO_SHA) && !defined(NO_SHA256)
3641
    ret = wc_Sha256Hash(token, token_size, digest);
3642
#else
3643
    ret = wc_ShaHash(token, token_size, digest);
3644
#endif
3645
    if (ret != 0)
3646
        return ret;
3647
    if (sz > GNRC_COOKIE_DIGEST_SIZE)
3648
        sz = GNRC_COOKIE_DIGEST_SIZE;
3649
    XMEMCPY(buf, digest, sz);
3650
    return sz;
3651
}
3652
3653
#endif /* WOLFSSL_GNRC */
3654
3655
#ifdef WOLFSSL_LWIP_NATIVE
3656
int LwIPNativeSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3657
{
3658
    err_t ret;
3659
    WOLFSSL_LWIP_NATIVE_STATE* nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3660
3661
    if (sz < 0 || sz > (int)WOLFSSL_MAX_16BIT) {
3662
        return BAD_FUNC_ARG;
3663
    }
3664
3665
    ret = tcp_write(nlwip->pcb, buf, (u16_t)sz, TCP_WRITE_FLAG_COPY);
3666
    if (ret != ERR_OK) {
3667
        sz = WOLFSSL_FATAL_ERROR;
3668
    }
3669
3670
    return sz;
3671
}
3672
3673
3674
int LwIPNativeReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3675
{
3676
    struct pbuf *current, *head;
3677
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3678
    int ret = 0;
3679
3680
    if (ctx == NULL) {
3681
        return WOLFSSL_CBIO_ERR_GENERAL;
3682
    }
3683
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3684
3685
    current = nlwip->pbuf;
3686
    if (current == NULL || sz > current->tot_len) {
3687
        WOLFSSL_MSG("LwIP native pbuf list is null or not enough data, want read");
3688
        ret = WOLFSSL_CBIO_ERR_WANT_READ;
3689
    }
3690
    else {
3691
        int read = 0; /* total amount read */
3692
        head = nlwip->pbuf; /* save pointer to current head */
3693
3694
        /* loop through buffers reading data */
3695
        while (current != NULL) {
3696
            int len; /* current amount to be read */
3697
3698
            len = (current->len - nlwip->pulled < sz) ?
3699
                                            (current->len - nlwip->pulled) : sz;
3700
3701
            if (read + len > sz) {
3702
                /* should never be hit but have sanity check before use */
3703
                return WOLFSSL_CBIO_ERR_GENERAL;
3704
            }
3705
3706
            /* check if is a partial read from before */
3707
            XMEMCPY(&buf[read],
3708
                   (const char *)&(((char *)(current->payload))[nlwip->pulled]),
3709
3710
                    len);
3711
            nlwip->pulled = nlwip->pulled + len;
3712
            if (nlwip->pulled >= current->len) {
3713
                WOLFSSL_MSG("Native LwIP read full pbuf");
3714
                nlwip->pbuf = current->next;
3715
                current = nlwip->pbuf;
3716
                nlwip->pulled = 0;
3717
            }
3718
            read = read + len;
3719
            ret  = read;
3720
3721
            /* read enough break out */
3722
            if (read >= sz) {
3723
                /* if more pbuf's are left in the chain then increment the
3724
                 * ref count for next in chain and free all from beginning till
3725
                 * next */
3726
                if (current != NULL) {
3727
                    pbuf_ref(current);
3728
                }
3729
3730
                /* ack and start free'ing from the current head of the chain */
3731
                pbuf_free(head);
3732
                break;
3733
            }
3734
        }
3735
    }
3736
    WOLFSSL_LEAVE("LwIPNativeReceive", ret);
3737
    return ret;
3738
}
3739
3740
3741
static err_t LwIPNativeReceiveCB(void* cb, struct tcp_pcb* pcb,
3742
                                struct pbuf* pbuf, err_t err)
3743
{
3744
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3745
3746
    if (cb == NULL || pcb == NULL) {
3747
        WOLFSSL_MSG("Expected callback was null, abort");
3748
        return ERR_ABRT;
3749
    }
3750
3751
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
3752
    if (pbuf == NULL && err == ERR_OK) {
3753
        return ERR_OK;
3754
    }
3755
3756
    if (nlwip->pbuf == NULL) {
3757
        nlwip->pbuf = pbuf;
3758
    }
3759
    else {
3760
        if (nlwip->pbuf != pbuf) {
3761
            tcp_recved(nlwip->pcb, pbuf->tot_len);
3762
            pbuf_cat(nlwip->pbuf, pbuf); /* add chain to head */
3763
        }
3764
    }
3765
3766
    if (nlwip->recv_fn) {
3767
        return nlwip->recv_fn(nlwip->arg, pcb, pbuf, err);
3768
    }
3769
3770
    WOLFSSL_LEAVE("LwIPNativeReceiveCB", nlwip->pbuf->tot_len);
3771
    return ERR_OK;
3772
}
3773
3774
3775
static err_t LwIPNativeSentCB(void* cb, struct tcp_pcb* pcb, u16_t len)
3776
{
3777
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3778
3779
    if (cb == NULL || pcb == NULL) {
3780
        WOLFSSL_MSG("Expected callback was null, abort");
3781
        return ERR_ABRT;
3782
    }
3783
3784
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
3785
    if (nlwip->sent_fn) {
3786
        return nlwip->sent_fn(nlwip->arg, pcb, len);
3787
    }
3788
    return ERR_OK;
3789
}
3790
3791
3792
int wolfSSL_SetIO_LwIP(WOLFSSL* ssl, void* pcb,
3793
                          tcp_recv_fn recv_fn, tcp_sent_fn sent_fn, void *arg)
3794
{
3795
    if (ssl == NULL || pcb == NULL)
3796
        return BAD_FUNC_ARG;
3797
3798
    ssl->lwipCtx.pcb = (struct tcp_pcb *)pcb;
3799
    ssl->lwipCtx.recv_fn = recv_fn; /*  recv user callback */
3800
    ssl->lwipCtx.sent_fn = sent_fn; /*  sent user callback */
3801
    ssl->lwipCtx.arg  = arg;
3802
    ssl->lwipCtx.pbuf = 0;
3803
    ssl->lwipCtx.pulled = 0;
3804
    ssl->lwipCtx.wait   = 0;
3805
3806
    /* wolfSSL_LwIP_recv/sent_cb invokes recv/sent user callback in them. */
3807
    tcp_recv(pcb, LwIPNativeReceiveCB);
3808
    tcp_sent(pcb, LwIPNativeSentCB);
3809
    tcp_arg (pcb, (void *)&ssl->lwipCtx);
3810
    wolfSSL_SetIOReadCtx(ssl, &ssl->lwipCtx);
3811
    wolfSSL_SetIOWriteCtx(ssl, &ssl->lwipCtx);
3812
3813
    return ERR_OK;
3814
}
3815
#endif /* WOLFSSL_LWIP_NATIVE */
3816
3817
#ifdef WOLFSSL_ISOTP
3818
static int isotp_send_single_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
3819
        word16 length)
3820
{
3821
    /* Length will be at most 7 bytes to get here. Packet is length and type
3822
     * for the first byte, then up to 7 bytes of data */
3823
    ctx->frame.data[0] = ((byte)length) | (ISOTP_FRAME_TYPE_SINGLE << 4);
3824
    XMEMCPY(&ctx->frame.data[1], buf, length);
3825
    ctx->frame.length = length + 1;
3826
    return ctx->send_fn(&ctx->frame, ctx->arg);
3827
}
3828
3829
static int isotp_send_flow_control(struct isotp_wolfssl_ctx *ctx,
3830
        byte overflow)
3831
{
3832
    int ret;
3833
    /* Overflow is set it if we have been asked to receive more data than the
3834
     * user allocated a buffer for */
3835
    if (overflow) {
3836
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_ABORT |
3837
            (ISOTP_FRAME_TYPE_CONTROL << 4);
3838
    } else {
3839
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_CTS |
3840
            (ISOTP_FRAME_TYPE_CONTROL << 4);
3841
    }
3842
    /* Set the number of frames between flow control to infinite */
3843
    ctx->frame.data[1] = ISOTP_FLOW_CONTROL_FRAMES;
3844
    /* User specified frame delay */
3845
    ctx->frame.data[2] = ctx->receive_delay;
3846
    ctx->frame.length = ISOTP_FLOW_CONTROL_PACKET_SIZE;
3847
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
3848
    return ret;
3849
}
3850
3851
static int isotp_receive_flow_control(struct isotp_wolfssl_ctx *ctx)
3852
{
3853
    int ret;
3854
    enum isotp_frame_type type;
3855
    enum isotp_flow_control flow_control;
3856
    ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT);
3857
    if (ret == 0) {
3858
        return WOLFSSL_CBIO_ERR_TIMEOUT;
3859
    } else if (ret < 0) {
3860
        WOLFSSL_MSG("ISO-TP error receiving flow control packet");
3861
        return WOLFSSL_CBIO_ERR_GENERAL;
3862
    }
3863
    /* Flow control is the frame type and flow response for the first byte,
3864
     * number of frames until the next flow control packet for the second
3865
     * byte, time between frames for the third byte */
3866
    type = ctx->frame.data[0] >> 4;
3867
3868
    if (type != ISOTP_FRAME_TYPE_CONTROL) {
3869
        WOLFSSL_MSG("ISO-TP frames out of sequence");
3870
        return WOLFSSL_CBIO_ERR_GENERAL;
3871
    }
3872
3873
    flow_control = ctx->frame.data[0] & 0xf;
3874
3875
    ctx->flow_counter = 0;
3876
    ctx->flow_packets = ctx->frame.data[1];
3877
    ctx->frame_delay = ctx->frame.data[2];
3878
3879
    return flow_control;
3880
}
3881
3882
static int isotp_send_consecutive_frame(struct isotp_wolfssl_ctx *ctx)
3883
{
3884
    /* Sequence is 0 - 15 and then starts again, the first frame has an
3885
     * implied sequence of '0' */
3886
    ctx->sequence += 1;
3887
    if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
3888
        ctx->sequence = 0;
3889
    }
3890
    ctx->flow_counter++;
3891
    /* First byte it type and sequence number, up to 7 bytes of data */
3892
    ctx->frame.data[0] = ctx->sequence | (ISOTP_FRAME_TYPE_CONSECUTIVE << 4);
3893
    if (ctx->buf_length > ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE) {
3894
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr,
3895
                ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE);
3896
        ctx->buf_ptr += ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
3897
        ctx->buf_length -= ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
3898
        ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
3899
    } else {
3900
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr, ctx->buf_length);
3901
        ctx->frame.length = ctx->buf_length + 1;
3902
        ctx->buf_length = 0;
3903
    }
3904
    return ctx->send_fn(&ctx->frame, ctx->arg);
3905
3906
}
3907
3908
static int isotp_send_first_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
3909
        word16 length)
3910
{
3911
    int ret;
3912
    ctx->sequence = 0;
3913
    /* Set to 1 to trigger a flow control straight away, the flow control
3914
     * packet will set these properly */
3915
    ctx->flow_packets = ctx->flow_counter = 1;
3916
    /* First frame has 1 nibble for type, 3 nibbles for length followed by
3917
     * 6 bytes for data*/
3918
    ctx->frame.data[0] = (length >> 8) | (ISOTP_FRAME_TYPE_FIRST << 4);
3919
    ctx->frame.data[1] = length & 0xff;
3920
    XMEMCPY(&ctx->frame.data[2], buf, ISOTP_FIRST_FRAME_DATA_SIZE);
3921
    ctx->buf_ptr = buf + ISOTP_FIRST_FRAME_DATA_SIZE;
3922
    ctx->buf_length = length - ISOTP_FIRST_FRAME_DATA_SIZE;
3923
    ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
3924
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
3925
    if (ret <= 0) {
3926
        WOLFSSL_MSG("ISO-TP error sending first frame");
3927
        return WOLFSSL_CBIO_ERR_GENERAL;
3928
    }
3929
    while(ctx->buf_length) {
3930
        /* The receiver can set how often to get a flow control packet. If it
3931
         * is time, then get the packet. Note that this will always happen
3932
         * after the first packet */
3933
        if ((ctx->flow_packets > 0) &&
3934
                (ctx->flow_counter == ctx->flow_packets)) {
3935
            ret = isotp_receive_flow_control(ctx);
3936
        }
3937
        /* Frame delay <= 0x7f is in ms, 0xfX is X * 100 us */
3938
        if (ctx->frame_delay) {
3939
            if (ctx->frame_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
3940
                ctx->delay_fn(ctx->frame_delay * 1000);
3941
            } else {
3942
                ctx->delay_fn((ctx->frame_delay & 0xf) * 100);
3943
            }
3944
        }
3945
        switch (ret) {
3946
            /* Clear to send */
3947
            case ISOTP_FLOW_CONTROL_CTS:
3948
                if (isotp_send_consecutive_frame(ctx) < 0) {
3949
                    WOLFSSL_MSG("ISO-TP error sending consecutive frame");
3950
                    return WOLFSSL_CBIO_ERR_GENERAL;
3951
                }
3952
                break;
3953
            /* Receiver says "WAIT", so we wait for another flow control
3954
             * packet, or abort if we have waited too long */
3955
            case ISOTP_FLOW_CONTROL_WAIT:
3956
                ctx->wait_counter += 1;
3957
                if (ctx->wait_counter > ISOTP_DEFAULT_WAIT_COUNT) {
3958
                    WOLFSSL_MSG("ISO-TP receiver told us to wait too many"
3959
                            " times");
3960
                    return WOLFSSL_CBIO_ERR_WANT_WRITE;
3961
                }
3962
                break;
3963
            /* Receiver is not ready to receive packet, so abort */
3964
            case ISOTP_FLOW_CONTROL_ABORT:
3965
                WOLFSSL_MSG("ISO-TP receiver aborted transmission");
3966
                return WOLFSSL_CBIO_ERR_WANT_WRITE;
3967
            default:
3968
                WOLFSSL_MSG("ISO-TP got unexpected flow control packet");
3969
                return WOLFSSL_CBIO_ERR_GENERAL;
3970
        }
3971
    }
3972
    return 0;
3973
}
3974
3975
int ISOTP_Send(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3976
{
3977
    int ret;
3978
    struct isotp_wolfssl_ctx *isotp_ctx;
3979
    (void) ssl;
3980
3981
    if (!ctx) {
3982
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
3983
        return WOLFSSL_CBIO_ERR_GENERAL;
3984
    }
3985
    isotp_ctx = (struct isotp_wolfssl_ctx*) ctx;
3986
3987
    /* ISO-TP cannot send more than 4095 bytes, this limits the packet size
3988
     * and wolfSSL will try again with the remaining data */
3989
    if (sz > ISOTP_MAX_DATA_SIZE) {
3990
        sz = ISOTP_MAX_DATA_SIZE;
3991
    }
3992
    /* Can't send whilst we are receiving */
3993
    if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
3994
        return WOLFSSL_ERROR_WANT_WRITE;
3995
    }
3996
    isotp_ctx->state = ISOTP_CONN_STATE_SENDING;
3997
3998
    /* Assuming normal addressing */
3999
    if (sz <= ISOTP_SINGLE_FRAME_DATA_SIZE) {
4000
        ret = isotp_send_single_frame(isotp_ctx, buf, (word16)sz);
4001
    } else {
4002
        ret = isotp_send_first_frame(isotp_ctx, buf, (word16)sz);
4003
    }
4004
    isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4005
4006
    if (ret == 0) {
4007
        return sz;
4008
    }
4009
    return ret;
4010
}
4011
4012
static int isotp_receive_single_frame(struct isotp_wolfssl_ctx *ctx)
4013
{
4014
    byte data_size;
4015
4016
    /* 1 nibble for data size which will be 1 - 7 in a regular 8 byte CAN
4017
     * packet */
4018
    data_size = (byte)ctx->frame.data[0] & 0xf;
4019
    if (ctx->receive_buffer_size < (int)data_size) {
4020
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
4021
        return BUFFER_E;
4022
    }
4023
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[1], data_size);
4024
    return data_size;
4025
}
4026
4027
static int isotp_receive_multi_frame(struct isotp_wolfssl_ctx *ctx)
4028
{
4029
    int ret;
4030
    word16 data_size;
4031
    byte delay = 0;
4032
4033
    /* Increase receive timeout for enforced ms delay */
4034
    if (ctx->receive_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
4035
        delay = ctx->receive_delay;
4036
    }
4037
    /* Still processing first frame.
4038
     * Full data size is lower nibble of first byte for the most significant
4039
     * followed by the second byte for the rest. Last 6 bytes are data */
4040
    data_size = ((ctx->frame.data[0] & 0xf) << 8) + ctx->frame.data[1];
4041
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[2], ISOTP_FIRST_FRAME_DATA_SIZE);
4042
    /* Need to send a flow control packet to either cancel or continue
4043
     * transmission of data */
4044
    if (ctx->receive_buffer_size < data_size) {
4045
        isotp_send_flow_control(ctx, TRUE);
4046
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
4047
        return BUFFER_E;
4048
    }
4049
    isotp_send_flow_control(ctx, FALSE);
4050
4051
    ctx->buf_length = ISOTP_FIRST_FRAME_DATA_SIZE;
4052
    ctx->buf_ptr = ctx->receive_buffer + ISOTP_FIRST_FRAME_DATA_SIZE;
4053
    data_size -= ISOTP_FIRST_FRAME_DATA_SIZE;
4054
    ctx->sequence = 1;
4055
4056
    while(data_size) {
4057
        enum isotp_frame_type type;
4058
        byte sequence;
4059
        byte frame_len;
4060
        ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT +
4061
                (delay / 1000));
4062
        if (ret == 0) {
4063
            return WOLFSSL_CBIO_ERR_TIMEOUT;
4064
        }
4065
        type = ctx->frame.data[0] >> 4;
4066
        /* Consecutive frames have sequence number as lower nibble */
4067
        sequence = ctx->frame.data[0] & 0xf;
4068
        if (type != ISOTP_FRAME_TYPE_CONSECUTIVE) {
4069
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4070
            return WOLFSSL_CBIO_ERR_GENERAL;
4071
        }
4072
        if (sequence != ctx->sequence) {
4073
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4074
            return WOLFSSL_CBIO_ERR_GENERAL;
4075
        }
4076
        /* Last 7 bytes or whatever we got after the first byte is data */
4077
        frame_len = ctx->frame.length - 1;
4078
        XMEMCPY(ctx->buf_ptr, &ctx->frame.data[1], frame_len);
4079
        ctx->buf_ptr += frame_len;
4080
        ctx->buf_length += frame_len;
4081
        data_size -= frame_len;
4082
4083
        /* Sequence is 0 - 15 (first 0 is implied for first packet */
4084
        ctx->sequence++;
4085
        if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
4086
            ctx->sequence = 0;
4087
        }
4088
    }
4089
    return ctx->buf_length;
4090
4091
}
4092
4093
/* The wolfSSL receive callback, needs to buffer because we need to grab all
4094
 * incoming data, even if wolfSSL doesn't want it all yet */
4095
int ISOTP_Receive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
4096
{
4097
    enum isotp_frame_type type;
4098
    int ret;
4099
    struct isotp_wolfssl_ctx *isotp_ctx;
4100
    (void) ssl;
4101
4102
    if (!ctx) {
4103
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
4104
        return WOLFSSL_CBIO_ERR_TIMEOUT;
4105
    }
4106
    isotp_ctx = (struct isotp_wolfssl_ctx*)ctx;
4107
4108
    /* Is buffer empty? If so, fill it */
4109
    if (!isotp_ctx->receive_buffer_len) {
4110
        /* Can't send whilst we are receiving */
4111
        if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
4112
            return WOLFSSL_ERROR_WANT_READ;
4113
        }
4114
        isotp_ctx->state = ISOTP_CONN_STATE_RECEIVING;
4115
        do {
4116
            ret = isotp_ctx->recv_fn(&isotp_ctx->frame, isotp_ctx->arg,
4117
                    ISOTP_DEFAULT_TIMEOUT);
4118
        } while (ret == 0);
4119
        if (ret == 0) {
4120
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4121
            return WOLFSSL_CBIO_ERR_TIMEOUT;
4122
        } else if (ret < 0) {
4123
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4124
            WOLFSSL_MSG("ISO-TP receive error");
4125
            return WOLFSSL_CBIO_ERR_GENERAL;
4126
        }
4127
4128
        type = (enum isotp_frame_type) isotp_ctx->frame.data[0] >> 4;
4129
4130
        if (type == ISOTP_FRAME_TYPE_SINGLE) {
4131
            isotp_ctx->receive_buffer_len =
4132
                isotp_receive_single_frame(isotp_ctx);
4133
        } else if (type == ISOTP_FRAME_TYPE_FIRST) {
4134
            isotp_ctx->receive_buffer_len =
4135
                isotp_receive_multi_frame(isotp_ctx);
4136
        } else {
4137
            /* Should never get here */
4138
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4139
            WOLFSSL_MSG("ISO-TP frames out of sequence");
4140
            return WOLFSSL_CBIO_ERR_GENERAL;
4141
        }
4142
        if (isotp_ctx->receive_buffer_len <= 1) {
4143
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4144
            return isotp_ctx->receive_buffer_len;
4145
        } else {
4146
            isotp_ctx->receive_buffer_ptr = isotp_ctx->receive_buffer;
4147
        }
4148
        isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
4149
    }
4150
4151
    /* Return from the buffer */
4152
    if (isotp_ctx->receive_buffer_len >= sz) {
4153
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr, sz);
4154
        isotp_ctx->receive_buffer_ptr+= sz;
4155
        isotp_ctx->receive_buffer_len-= sz;
4156
        return sz;
4157
    } else {
4158
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr,
4159
                isotp_ctx->receive_buffer_len);
4160
        sz = isotp_ctx->receive_buffer_len;
4161
        isotp_ctx->receive_buffer_len = 0;
4162
        return sz;
4163
    }
4164
}
4165
4166
int wolfSSL_SetIO_ISOTP(WOLFSSL *ssl, isotp_wolfssl_ctx *ctx,
4167
        can_recv_fn recv_fn, can_send_fn send_fn, can_delay_fn delay_fn,
4168
        word32 receive_delay, char *receive_buffer, int receive_buffer_size,
4169
        void *arg)
4170
{
4171
    if (!ctx || !recv_fn || !send_fn || !delay_fn || !receive_buffer) {
4172
        WOLFSSL_MSG("ISO-TP has missing required parameter");
4173
        return WOLFSSL_CBIO_ERR_GENERAL;
4174
    }
4175
    ctx->recv_fn = recv_fn;
4176
    ctx->send_fn = send_fn;
4177
    ctx->arg = arg;
4178
    ctx->delay_fn = delay_fn;
4179
    ctx->frame_delay = 0;
4180
    ctx->receive_buffer = receive_buffer;
4181
    ctx->receive_buffer_size = receive_buffer_size;
4182
    ctx->receive_buffer_len = 0;
4183
    ctx->state = ISOTP_CONN_STATE_IDLE;
4184
4185
    wolfSSL_SetIOReadCtx(ssl, ctx);
4186
    wolfSSL_SetIOWriteCtx(ssl, ctx);
4187
4188
    /* Delay of 100 - 900us is 0xfX where X is value / 100. Delay of
4189
     * >= 1000 is divided by 1000. > 127ms is invalid */
4190
    if (receive_delay < 1000) {
4191
        ctx->receive_delay = 0xf0 + (receive_delay / 100);
4192
    } else if (receive_delay <= ISOTP_MAX_MS_FRAME_DELAY * 1000) {
4193
        ctx->receive_delay = receive_delay / 1000;
4194
    } else {
4195
        WOLFSSL_MSG("ISO-TP delay parameter out of bounds");
4196
        return WOLFSSL_CBIO_ERR_GENERAL;
4197
    }
4198
    return 0;
4199
}
4200
#endif /* WOLFSSL_ISOTP */
4201
#endif /* WOLFCRYPT_ONLY */