Coverage Report

Created: 2025-06-23 06:10

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