Coverage Report

Created: 2025-10-13 06:29

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