Coverage Report

Created: 2025-07-31 06:22

/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 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
23
#ifndef WOLFSSL_STRERROR_BUFFER_SIZE
24
#define WOLFSSL_STRERROR_BUFFER_SIZE 256
25
#endif
26
27
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
28
29
#ifndef WOLFCRYPT_ONLY
30
31
#if defined(HAVE_ERRNO_H) && defined(WOLFSSL_NO_SOCK) && \
32
    (defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT))
33
    /* error codes are needed for TranslateIoReturnCode() and
34
     * wolfIO_TcpConnect() even if defined(WOLFSSL_NO_SOCK), which inhibits
35
     * inclusion of errno.h by wolfio.h.
36
     */
37
    #include <errno.h>
38
#endif
39
40
#include <wolfssl/internal.h>
41
#include <wolfssl/error-ssl.h>
42
#include <wolfssl/wolfio.h>
43
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(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1351
    !defined(SINGLE_THREADED)
1352
    HOSTENT entry_buf, *entry = NULL;
1353
    char *ghbn_r_buf = NULL;
1354
    int ghbn_r_errno;
1355
#else
1356
    HOSTENT *entry;
1357
#endif
1358
#ifdef WOLFSSL_IPV6
1359
    SOCKADDR_IN6 *sin;
1360
#else
1361
    SOCKADDR_IN *sin;
1362
#endif /* WOLFSSL_IPV6 */
1363
#endif /* HAVE_GETADDRINFO */
1364
1365
    if (sockfd == NULL || ip == NULL) {
1366
        return WOLFSSL_FATAL_ERROR;
1367
    }
1368
1369
#if !defined(HAVE_GETADDRINFO)
1370
#ifdef WOLFSSL_IPV6
1371
    sockaddr_len = sizeof(SOCKADDR_IN6);
1372
#else
1373
    sockaddr_len = sizeof(SOCKADDR_IN);
1374
#endif /* WOLFSSL_IPV6 */
1375
#endif /* !HAVE_GETADDRINFO */
1376
    XMEMSET(&addr, 0, sizeof(addr));
1377
1378
#ifdef WOLFIO_DEBUG
1379
    printf("TCP Connect: %s:%d\n", ip, port);
1380
#endif
1381
1382
    /* use gethostbyname for c99 */
1383
#if defined(HAVE_GETADDRINFO)
1384
    XMEMSET(&hints, 0, sizeof(hints));
1385
#ifdef WOLFSSL_IPV6
1386
    hints.ai_family = AF_UNSPEC; /* detect IPv4 or IPv6 */
1387
#else
1388
    hints.ai_family = AF_INET;   /* detect only IPv4 */
1389
#endif
1390
    hints.ai_socktype = SOCK_STREAM;
1391
    hints.ai_protocol = IPPROTO_TCP;
1392
1393
    if (wolfIO_Word16ToString(strPort, port) == 0) {
1394
        WOLFSSL_MSG("invalid port number for responder");
1395
        return WOLFSSL_FATAL_ERROR;
1396
    }
1397
1398
    if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
1399
        WOLFSSL_MSG("no addr info for responder");
1400
        return WOLFSSL_FATAL_ERROR;
1401
    }
1402
1403
    sockaddr_len = answer->ai_addrlen;
1404
    XMEMCPY(&addr, answer->ai_addr, (size_t)sockaddr_len);
1405
    freeaddrinfo(answer);
1406
#else
1407
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1408
    !defined(SINGLE_THREADED)
1409
    /* 2048 is a magic number that empirically works.  the header and
1410
     * documentation provide no guidance on appropriate buffer size other than
1411
     * "if buf is too small, the functions will return ERANGE, and the call
1412
     * should be retried with a larger buffer."
1413
     */
1414
    ghbn_r_buf = (char *)XMALLOC(2048, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1415
    if (ghbn_r_buf != NULL) {
1416
        gethostbyname_r(ip, &entry_buf, ghbn_r_buf, 2048, &entry, &ghbn_r_errno);
1417
    }
1418
#else
1419
    entry = gethostbyname(ip);
1420
#endif
1421
1422
    if (entry) {
1423
    #ifdef WOLFSSL_IPV6
1424
        sin = (SOCKADDR_IN6 *)&addr;
1425
        sin->sin6_family = AF_INET6;
1426
        sin->sin6_port = XHTONS(port);
1427
        XMEMCPY(&sin->sin6_addr, entry->h_addr_list[0], entry->h_length);
1428
    #else
1429
        sin = (SOCKADDR_IN *)&addr;
1430
        sin->sin_family = AF_INET;
1431
        sin->sin_port = XHTONS(port);
1432
        XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
1433
                (size_t)entry->h_length);
1434
    #endif
1435
    }
1436
1437
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && defined(__USE_MISC) && \
1438
    !defined(SINGLE_THREADED)
1439
    XFREE(ghbn_r_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1440
#endif
1441
1442
    if (entry == NULL) {
1443
        WOLFSSL_MSG("no addr info for responder");
1444
        return WOLFSSL_FATAL_ERROR;
1445
    }
1446
#endif
1447
1448
    *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
1449
#ifdef USE_WINDOWS_API
1450
    if (*sockfd == SOCKET_INVALID)
1451
#else
1452
    if (*sockfd <= SOCKET_INVALID)
1453
#endif
1454
    {
1455
        WOLFSSL_MSG("bad socket fd, out of fds?");
1456
        *sockfd = SOCKET_INVALID;
1457
        return WOLFSSL_FATAL_ERROR;
1458
    }
1459
1460
#ifdef HAVE_IO_TIMEOUT
1461
    /* if timeout value provided then set socket non-blocking */
1462
    if (to_sec > 0) {
1463
        wolfIO_SetBlockingMode(*sockfd, 1);
1464
    }
1465
#else
1466
    (void)to_sec;
1467
#endif /* HAVE_IO_TIMEOUT */
1468
1469
    ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
1470
#ifdef HAVE_IO_TIMEOUT
1471
    if ((ret != 0) && (to_sec > 0)) {
1472
#ifdef USE_WINDOWS_API
1473
        if ((ret == SOCKET_ERROR) &&
1474
            (wolfSSL_LastError(ret, *sockfd) == SOCKET_EWOULDBLOCK))
1475
#else
1476
        if (errno == EINPROGRESS)
1477
#endif
1478
        {
1479
            /* wait for connect to complete */
1480
            ret = wolfIO_Select(*sockfd, to_sec);
1481
1482
            /* restore blocking mode */
1483
            wolfIO_SetBlockingMode(*sockfd, 0);
1484
        }
1485
    }
1486
#endif /* HAVE_IO_TIMEOUT */
1487
    if (ret != 0) {
1488
        WOLFSSL_MSG("Responder tcp connect failed");
1489
        CloseSocket(*sockfd);
1490
        *sockfd = SOCKET_INVALID;
1491
        return WOLFSSL_FATAL_ERROR;
1492
    }
1493
    return ret;
1494
#else
1495
    (void)sockfd;
1496
    (void)ip;
1497
    (void)port;
1498
    (void)to_sec;
1499
    return WOLFSSL_FATAL_ERROR;
1500
#endif /* HAVE_SOCKADDR */
1501
}
1502
1503
int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
1504
{
1505
#ifdef HAVE_SOCKADDR
1506
    int ret = 0;
1507
    SOCKADDR_S addr;
1508
    socklen_t sockaddr_len = sizeof(SOCKADDR_IN);
1509
    SOCKADDR_IN *sin = (SOCKADDR_IN *)&addr;
1510
1511
    if (sockfd == NULL || port < 1) {
1512
        return WOLFSSL_FATAL_ERROR;
1513
    }
1514
1515
    XMEMSET(&addr, 0, sizeof(addr));
1516
1517
    sin->sin_family = AF_INET;
1518
    sin->sin_addr.s_addr = INADDR_ANY;
1519
    sin->sin_port = XHTONS(port);
1520
    *sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM, 0);
1521
1522
#ifdef USE_WINDOWS_API
1523
    if (*sockfd == SOCKET_INVALID)
1524
#else
1525
    if (*sockfd <= SOCKET_INVALID)
1526
#endif
1527
    {
1528
        WOLFSSL_MSG("socket failed");
1529
        *sockfd = SOCKET_INVALID;
1530
        return WOLFSSL_FATAL_ERROR;
1531
    }
1532
1533
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
1534
                   && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
1535
    {
1536
        int optval  = 1;
1537
        XSOCKLENT optlen = sizeof(optval);
1538
        ret = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
1539
    }
1540
#endif
1541
1542
    if (ret == 0)
1543
        ret = bind(*sockfd, (SOCKADDR *)sin, sockaddr_len);
1544
    if (ret == 0)
1545
        ret = listen(*sockfd, SOMAXCONN);
1546
1547
    if (ret != 0) {
1548
        WOLFSSL_MSG("wolfIO_TcpBind failed");
1549
        CloseSocket(*sockfd);
1550
        *sockfd = SOCKET_INVALID;
1551
        ret = WOLFSSL_FATAL_ERROR;
1552
    }
1553
1554
    return ret;
1555
#else
1556
    (void)sockfd;
1557
    (void)port;
1558
    return WOLFSSL_FATAL_ERROR;
1559
#endif /* HAVE_SOCKADDR */
1560
}
1561
1562
#ifdef HAVE_SOCKADDR
1563
int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
1564
{
1565
    return (int)accept(sockfd, peer_addr, peer_len);
1566
}
1567
#endif /* HAVE_SOCKADDR */
1568
1569
#ifndef HTTP_SCRATCH_BUFFER_SIZE
1570
    #define HTTP_SCRATCH_BUFFER_SIZE 512
1571
#endif
1572
#ifndef MAX_URL_ITEM_SIZE
1573
    #define MAX_URL_ITEM_SIZE   80
1574
#endif
1575
1576
int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
1577
    word16* outPort)
1578
{
1579
    int result = -1;
1580
1581
    if (url == NULL || urlSz == 0) {
1582
        if (outName)
1583
            *outName = 0;
1584
        if (outPath)
1585
            *outPath = 0;
1586
        if (outPort)
1587
            *outPort = 0;
1588
    }
1589
    else {
1590
        int i, cur;
1591
1592
        /* need to break the url down into scheme, address, and port */
1593
        /*     "http://example.com:8080/" */
1594
        /*     "http://[::1]:443/"        */
1595
        if (XSTRNCMP(url, "http://", 7) == 0) {
1596
            cur = 7;
1597
        } else cur = 0;
1598
1599
        i = 0;
1600
        if (url[cur] == '[') {
1601
            cur++;
1602
            /* copy until ']' */
1603
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1604
                    url[cur] != ']') {
1605
                if (outName)
1606
                    outName[i] = url[cur];
1607
                i++; cur++;
1608
            }
1609
            cur++; /* skip ']' */
1610
        }
1611
        else {
1612
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1613
                    url[cur] != ':' && url[cur] != '/') {
1614
                if (outName)
1615
                    outName[i] = url[cur];
1616
                i++; cur++;
1617
            }
1618
        }
1619
        if (outName)
1620
            outName[i] = 0;
1621
        /* Need to pick out the path after the domain name */
1622
1623
        if (cur < urlSz && url[cur] == ':') {
1624
            char port[6];
1625
            int j;
1626
            word32 bigPort = 0;
1627
            i = 0;
1628
            cur++;
1629
1630
            XMEMSET(port, 0, sizeof(port));
1631
1632
            while (i < 6 && cur < urlSz && url[cur] != 0 && url[cur] != '/') {
1633
                port[i] = url[cur];
1634
                i++; cur++;
1635
            }
1636
1637
            for (j = 0; j < i; j++) {
1638
                if (port[j] < '0' || port[j] > '9') return WOLFSSL_FATAL_ERROR;
1639
                bigPort = (bigPort * 10) + (word32)(port[j] - '0');
1640
            }
1641
            if (outPort)
1642
                *outPort = (word16)bigPort;
1643
        }
1644
        else if (outPort)
1645
            *outPort = 80;
1646
1647
1648
        if (cur < urlSz && url[cur] == '/') {
1649
            i = 0;
1650
            while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) {
1651
                if (outPath)
1652
                    outPath[i] = url[cur];
1653
                i++; cur++;
1654
            }
1655
            if (outPath)
1656
                outPath[i] = 0;
1657
        }
1658
        else if (outPath) {
1659
            outPath[0] = '/';
1660
            outPath[1] = 0;
1661
        }
1662
1663
        result = 0;
1664
    }
1665
1666
    return result;
1667
}
1668
1669
static int wolfIO_HttpProcessResponseBuf(WolfSSLGenericIORecvCb ioCb,
1670
    void* ioCbCtx, byte **recvBuf, int* recvBufSz, int chunkSz, char* start,
1671
    int len, int dynType, void* heap)
1672
{
1673
    byte* newRecvBuf = NULL;
1674
    int newRecvSz = *recvBufSz + chunkSz;
1675
    int pos = 0;
1676
1677
    WOLFSSL_MSG("Processing HTTP response");
1678
#ifdef WOLFIO_DEBUG
1679
    printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
1680
#endif
1681
1682
    (void)heap;
1683
    (void)dynType;
1684
1685
    if (chunkSz < 0 || len < 0) {
1686
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size");
1687
        return MEMORY_E;
1688
    }
1689
1690
    if (newRecvSz <= 0) {
1691
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow");
1692
        return MEMORY_E;
1693
    }
1694
1695
    newRecvBuf = (byte*)XMALLOC((size_t)newRecvSz, heap, dynType);
1696
    if (newRecvBuf == NULL) {
1697
        WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
1698
        return MEMORY_E;
1699
    }
1700
1701
    /* if buffer already exists, then we are growing it */
1702
    if (*recvBuf) {
1703
        XMEMCPY(&newRecvBuf[pos], *recvBuf, (size_t) *recvBufSz);
1704
        XFREE(*recvBuf, heap, dynType);
1705
        pos += *recvBufSz;
1706
        *recvBuf = NULL;
1707
    }
1708
1709
    /* copy the remainder of the httpBuf into the respBuf */
1710
    if (len != 0) {
1711
        if (pos + len <= newRecvSz) {
1712
            XMEMCPY(&newRecvBuf[pos], start, (size_t)len);
1713
            pos += len;
1714
        }
1715
        else {
1716
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size");
1717
            XFREE(newRecvBuf, heap, dynType);
1718
            return WOLFSSL_FATAL_ERROR;
1719
        }
1720
    }
1721
1722
    /* receive the remainder of chunk */
1723
    while (len < chunkSz) {
1724
        int rxSz = ioCb((char*)&newRecvBuf[pos], chunkSz-len, ioCbCtx);
1725
        if (rxSz > 0) {
1726
            len += rxSz;
1727
            pos += rxSz;
1728
        }
1729
        else {
1730
            WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
1731
            XFREE(newRecvBuf, heap, dynType);
1732
            return WOLFSSL_FATAL_ERROR;
1733
        }
1734
    }
1735
1736
    *recvBuf = newRecvBuf;
1737
    *recvBufSz = newRecvSz;
1738
1739
    return 0;
1740
}
1741
1742
int wolfIO_HttpProcessResponseGenericIO(WolfSSLGenericIORecvCb ioCb,
1743
    void* ioCbCtx, const char** appStrList, unsigned char** respBuf,
1744
    unsigned char* httpBuf, int httpBufSz, int dynType, void* heap)
1745
{
1746
    static const char HTTP_PROTO[] = "HTTP/1.";
1747
    static const char HTTP_STATUS_200[] = "200";
1748
    int result = 0;
1749
    int len = 0;
1750
    char *start, *end;
1751
    int respBufSz = 0;
1752
    int isChunked = 0, chunkSz = 0;
1753
    enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
1754
                     phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
1755
                     phr_http_end
1756
    } state = phr_init;
1757
1758
    WOLFSSL_ENTER("wolfIO_HttpProcessResponse");
1759
1760
    *respBuf = NULL;
1761
    start = end = NULL;
1762
    do {
1763
        if (state == phr_get_chunk_data) {
1764
            /* get chunk of data */
1765
            result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
1766
                &respBufSz, chunkSz, start, len, dynType, heap);
1767
1768
            state = (result != 0) ? phr_http_end : phr_get_chunk_len;
1769
            end = NULL;
1770
            len = 0;
1771
        }
1772
1773
        /* read data if no \r\n or first time */
1774
        if ((start == NULL) || (end == NULL)) {
1775
            if (httpBufSz < len + 1) {
1776
                return BUFFER_ERROR; /* can't happen, but Coverity thinks it
1777
                                      * can.
1778
                                      */
1779
            }
1780
            result = ioCb((char*)httpBuf+len, httpBufSz-len-1, ioCbCtx);
1781
            if (result > 0) {
1782
                len += result;
1783
                start = (char*)httpBuf;
1784
                start[len] = 0;
1785
            }
1786
            else {
1787
                if (result == WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_WANT_READ)) {
1788
                    return OCSP_WANT_READ;
1789
                }
1790
1791
                WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
1792
                return HTTP_RECV_ERR;
1793
            }
1794
        }
1795
        end = XSTRSTR(start, "\r\n"); /* locate end */
1796
1797
        /* handle incomplete rx */
1798
        if (end == NULL) {
1799
            if (len != 0)
1800
                XMEMMOVE(httpBuf, start, (size_t)len);
1801
            start = end = NULL;
1802
        }
1803
        /* when start is "\r\n" */
1804
        else if (end == start) {
1805
            /* if waiting for end or need chunk len */
1806
            if (state == phr_wait_end || state == phr_get_chunk_len) {
1807
                state = (isChunked) ? phr_get_chunk_len : phr_http_end;
1808
                len -= 2; start += 2; /* skip \r\n */
1809
             }
1810
             else {
1811
                WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
1812
                return HTTP_HEADER_ERR;
1813
             }
1814
        }
1815
        else {
1816
            *end = 0; /* null terminate */
1817
            len -= (int)(end - start) + 2;
1818
                /* adjust len to remove the first line including the /r/n */
1819
1820
        #ifdef WOLFIO_DEBUG
1821
            printf("HTTP Resp: %s\n", start);
1822
        #endif
1823
1824
            switch (state) {
1825
                case phr_init:
1826
                    /* length of "HTTP/1.x 200" == 12*/
1827
                    if (XSTRLEN(start) < 12) {
1828
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1829
                            "too short.");
1830
                        return HTTP_HEADER_ERR;
1831
                    }
1832
                    if (XSTRNCASECMP(start, HTTP_PROTO,
1833
                                     sizeof(HTTP_PROTO) - 1) != 0) {
1834
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1835
                            "doesn't start with HTTP/1.");
1836
                        return HTTP_PROTO_ERR;
1837
                    }
1838
                    /* +2 for HTTP minor version and space between version and
1839
                     * status code. */
1840
                    start += sizeof(HTTP_PROTO) - 1 + 2 ;
1841
                    if (XSTRNCASECMP(start, HTTP_STATUS_200,
1842
                                     sizeof(HTTP_STATUS_200) - 1) != 0) {
1843
                        WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1844
                            "doesn't have status code 200.");
1845
                        return HTTP_STATUS_ERR;
1846
                    }
1847
                    state = phr_http_start;
1848
                    break;
1849
                case phr_http_start:
1850
                case phr_have_length:
1851
                case phr_have_type:
1852
                    if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
1853
                        int i;
1854
1855
                        start += 13;
1856
                        while (*start == ' ') start++;
1857
1858
                        /* try and match against appStrList */
1859
                        i = 0;
1860
                        while (appStrList[i] != NULL) {
1861
                            if (XSTRNCASECMP(start, appStrList[i],
1862
                                                XSTRLEN(appStrList[i])) == 0) {
1863
                                break;
1864
                            }
1865
                            i++;
1866
                        }
1867
                        if (appStrList[i] == NULL) {
1868
                            WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
1869
                            return HTTP_APPSTR_ERR;
1870
                        }
1871
                        state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
1872
                    }
1873
                    else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
1874
                        start += 15;
1875
                        while (*start == ' ') start++;
1876
                        chunkSz = XATOI(start);
1877
                        state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1878
                    }
1879
                    else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
1880
                        start += 18;
1881
                        while (*start == ' ') start++;
1882
                        if (XSTRNCASECMP(start, "chunked", 7) == 0) {
1883
                            isChunked = 1;
1884
                            state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1885
                        }
1886
                    }
1887
                    break;
1888
                case phr_get_chunk_len:
1889
                    chunkSz = (int)strtol(start, NULL, 16); /* hex format */
1890
                    state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
1891
                    break;
1892
                case phr_get_chunk_data:
1893
                    /* processing for chunk data done above, since \r\n isn't required */
1894
                case phr_wait_end:
1895
                case phr_http_end:
1896
                    /* do nothing */
1897
                    break;
1898
            } /* switch (state) */
1899
1900
            /* skip to end plus \r\n */
1901
            start = end + 2;
1902
        }
1903
    } while (state != phr_http_end);
1904
1905
    if (!isChunked) {
1906
        result = wolfIO_HttpProcessResponseBuf(ioCb, ioCbCtx, respBuf,
1907
                &respBufSz, chunkSz, start, len, dynType, heap);
1908
    }
1909
1910
    if (result >= 0) {
1911
        result = respBufSz;
1912
    }
1913
    else {
1914
        WOLFSSL_ERROR(result);
1915
    }
1916
1917
    return result;
1918
}
1919
1920
static int httpResponseIoCb(char* buf, int sz, void* ctx)
1921
{
1922
    /* Double cast to silence the compiler int/pointer width msg */
1923
    return wolfIO_Recv((SOCKET_T)(uintptr_t)ctx, buf, sz, 0);
1924
}
1925
1926
int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
1927
    byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
1928
{
1929
    return wolfIO_HttpProcessResponseGenericIO(httpResponseIoCb,
1930
            /* Double cast to silence the compiler int/pointer width msg */
1931
            (void*)(uintptr_t)sfd, appStrList, respBuf, httpBuf, httpBufSz,
1932
            dynType, heap);
1933
}
1934
1935
int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
1936
                               const char *path, int pathLen, int reqSz, const char *contentType,
1937
                               byte *buf, int bufSize)
1938
{
1939
    return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize);
1940
}
1941
1942
int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
1943
                                const char *path, int pathLen, int reqSz, const char *contentType,
1944
                                const char *exHdrs, byte *buf, int bufSize)
1945
    {
1946
    word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen;
1947
    char reqSzStr[6];
1948
    char* req = (char*)buf;
1949
    const char* blankStr = " ";
1950
    const char* http11Str = " HTTP/1.1";
1951
    const char* hostStr = "\r\nHost: ";
1952
    const char* contentLenStr = "\r\nContent-Length: ";
1953
    const char* contentTypeStr = "\r\nContent-Type: ";
1954
    const char* singleCrLfStr = "\r\n";
1955
    const char* doubleCrLfStr = "\r\n\r\n";
1956
    word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
1957
        contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen;
1958
1959
    reqTypeLen = (word32)XSTRLEN(reqType);
1960
    domainNameLen = (word32)XSTRLEN(domainName);
1961
    reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
1962
    contentTypeLen = (word32)XSTRLEN(contentType);
1963
1964
    blankStrLen = (word32)XSTRLEN(blankStr);
1965
    http11StrLen = (word32)XSTRLEN(http11Str);
1966
    hostStrLen = (word32)XSTRLEN(hostStr);
1967
    contentLenStrLen = (word32)XSTRLEN(contentLenStr);
1968
    contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
1969
1970
    if(exHdrs){
1971
        singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr);
1972
        exHdrsLen = (word32)XSTRLEN(exHdrs);
1973
    } else {
1974
        singleCrLfStrLen = 0;
1975
        exHdrsLen = 0;
1976
    }
1977
1978
    doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
1979
1980
    /* determine max length and check it */
1981
    maxLen =
1982
        reqTypeLen +
1983
        blankStrLen +
1984
        (word32)pathLen +
1985
        http11StrLen +
1986
        hostStrLen +
1987
        domainNameLen +
1988
        contentLenStrLen +
1989
        reqSzStrLen +
1990
        contentTypeStrLen +
1991
        contentTypeLen +
1992
        singleCrLfStrLen +
1993
        exHdrsLen +
1994
        doubleCrLfStrLen +
1995
        (word32)1 /* null term */;
1996
    if (maxLen > (word32)bufSize)
1997
        return 0;
1998
1999
    XSTRNCPY((char*)buf, reqType, (size_t)bufSize);
2000
    buf += reqTypeLen; bufSize -= (int)reqTypeLen;
2001
    XSTRNCPY((char*)buf, blankStr, (size_t)bufSize);
2002
    buf += blankStrLen; bufSize -= (int)blankStrLen;
2003
    XSTRNCPY((char*)buf, path, (size_t)bufSize);
2004
    buf += pathLen; bufSize -= (int)pathLen;
2005
    XSTRNCPY((char*)buf, http11Str, (size_t)bufSize);
2006
    buf += http11StrLen; bufSize -= (int)http11StrLen;
2007
    if (domainNameLen > 0) {
2008
        XSTRNCPY((char*)buf, hostStr, (size_t)bufSize);
2009
        buf += hostStrLen; bufSize -= (int)hostStrLen;
2010
        XSTRNCPY((char*)buf, domainName, (size_t)bufSize);
2011
        buf += domainNameLen; bufSize -= (int)domainNameLen;
2012
    }
2013
    if (reqSz > 0 && reqSzStrLen > 0) {
2014
        XSTRNCPY((char*)buf, contentLenStr, (size_t)bufSize);
2015
        buf += contentLenStrLen; bufSize -= (int)contentLenStrLen;
2016
        XSTRNCPY((char*)buf, reqSzStr, (size_t)bufSize);
2017
        buf += reqSzStrLen; bufSize -= (int)reqSzStrLen;
2018
    }
2019
    if (contentTypeLen > 0) {
2020
        XSTRNCPY((char*)buf, contentTypeStr, (size_t)bufSize);
2021
        buf += contentTypeStrLen; bufSize -= (int)contentTypeStrLen;
2022
        XSTRNCPY((char*)buf, contentType, (size_t)bufSize);
2023
        buf += contentTypeLen; bufSize -= (int)contentTypeLen;
2024
    }
2025
    if (exHdrsLen > 0)
2026
    {
2027
        XSTRNCPY((char *)buf, singleCrLfStr, (size_t)bufSize);
2028
        buf += singleCrLfStrLen;
2029
        bufSize -= (int)singleCrLfStrLen;
2030
        XSTRNCPY((char *)buf, exHdrs, (size_t)bufSize);
2031
        buf += exHdrsLen;
2032
        bufSize -= (int)exHdrsLen;
2033
    }
2034
    XSTRNCPY((char*)buf, doubleCrLfStr, (size_t)bufSize);
2035
    buf += doubleCrLfStrLen;
2036
2037
#ifdef WOLFIO_DEBUG
2038
    printf("HTTP %s: %s", reqType, req);
2039
#endif
2040
2041
    /* calculate actual length based on original and new pointer */
2042
    return (int)((char*)buf - req);
2043
}
2044
2045
2046
#ifdef HAVE_OCSP
2047
2048
int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
2049
                                    int ocspReqSz, byte* buf, int bufSize)
2050
{
2051
    const char *cacheCtl = "Cache-Control: no-cache";
2052
    return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path),
2053
        ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize);
2054
}
2055
2056
static const char* ocspAppStrList[] = {
2057
    "application/ocsp-response",
2058
    NULL
2059
};
2060
2061
int wolfIO_HttpProcessResponseOcspGenericIO(
2062
    WolfSSLGenericIORecvCb ioCb, void* ioCbCtx, unsigned char** respBuf,
2063
    unsigned char* httpBuf, int httpBufSz, void* heap)
2064
{
2065
    return wolfIO_HttpProcessResponseGenericIO(ioCb, ioCbCtx,
2066
          ocspAppStrList, respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2067
}
2068
2069
/* return: >0 OCSP Response Size
2070
 *         -1 error */
2071
int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
2072
                                       byte* httpBuf, int httpBufSz, void* heap)
2073
{
2074
    return wolfIO_HttpProcessResponse(sfd, ocspAppStrList,
2075
        respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
2076
}
2077
2078
/* in default wolfSSL callback ctx is the heap pointer */
2079
int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
2080
                        byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
2081
{
2082
    SOCKET_T sfd = SOCKET_INVALID;
2083
    word16   port;
2084
    int      ret = -1;
2085
#ifdef WOLFSSL_SMALL_STACK
2086
    char*    path;
2087
    char*    domainName;
2088
#else
2089
    char     path[MAX_URL_ITEM_SIZE];
2090
    char     domainName[MAX_URL_ITEM_SIZE];
2091
#endif
2092
2093
#ifdef WOLFSSL_SMALL_STACK
2094
    path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2095
    if (path == NULL)
2096
        return MEMORY_E;
2097
2098
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL,
2099
            DYNAMIC_TYPE_TMP_BUFFER);
2100
    if (domainName == NULL) {
2101
        XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2102
        return MEMORY_E;
2103
    }
2104
#endif
2105
2106
    if (ocspReqBuf == NULL || ocspReqSz == 0) {
2107
        WOLFSSL_MSG("OCSP request is required for lookup");
2108
    }
2109
    else if (ocspRespBuf == NULL) {
2110
        WOLFSSL_MSG("Cannot save OCSP response");
2111
    }
2112
    else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
2113
        WOLFSSL_MSG("Unable to decode OCSP URL");
2114
    }
2115
    else {
2116
        /* Note, the library uses the EmbedOcspRespFree() callback to
2117
         * free this buffer. */
2118
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2119
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
2120
2121
        if (httpBuf == NULL) {
2122
            WOLFSSL_MSG("Unable to create OCSP response buffer");
2123
        }
2124
        else {
2125
            httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
2126
                                                            httpBuf, httpBufSz);
2127
2128
            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
2129
            if (ret != 0) {
2130
                WOLFSSL_MSG("OCSP Responder connection failed");
2131
            }
2132
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
2133
                                                                    httpBufSz) {
2134
                WOLFSSL_MSG("OCSP http request failed");
2135
            }
2136
            else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
2137
                                                                    ocspReqSz) {
2138
                WOLFSSL_MSG("OCSP ocsp request failed");
2139
            }
2140
            else {
2141
                ret = wolfIO_HttpProcessResponseOcsp((int)sfd, ocspRespBuf, httpBuf,
2142
                                                 HTTP_SCRATCH_BUFFER_SIZE, ctx);
2143
            }
2144
            if (sfd != SOCKET_INVALID)
2145
                CloseSocket(sfd);
2146
            XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
2147
        }
2148
    }
2149
2150
#ifdef WOLFSSL_SMALL_STACK
2151
    XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
2152
    XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2153
#endif
2154
2155
    return ret;
2156
}
2157
2158
/* in default callback ctx is heap hint */
2159
void EmbedOcspRespFree(void* ctx, byte *resp)
2160
{
2161
    XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
2162
2163
    (void)ctx;
2164
}
2165
#endif /* HAVE_OCSP */
2166
2167
2168
#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
2169
2170
int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
2171
    const char* domainName, byte* buf, int bufSize)
2172
{
2173
    const char *cacheCtl = "Cache-Control: no-cache";
2174
    return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "",
2175
                                   cacheCtl, buf, bufSize);
2176
}
2177
2178
int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
2179
    int httpBufSz)
2180
{
2181
    int ret;
2182
    byte *respBuf = NULL;
2183
2184
    const char* appStrList[] = {
2185
        "application/pkix-crl",
2186
        "application/x-pkcs7-crl",
2187
        NULL
2188
    };
2189
2190
2191
    ret = wolfIO_HttpProcessResponse(sfd, appStrList,
2192
        &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
2193
    if (ret >= 0) {
2194
        ret = BufferLoadCRL(crl, respBuf, ret, WOLFSSL_FILETYPE_ASN1, 0);
2195
    }
2196
    XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
2197
2198
    return ret;
2199
}
2200
2201
int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
2202
{
2203
    SOCKET_T sfd = SOCKET_INVALID;
2204
    word16   port;
2205
    int      ret = -1;
2206
#ifdef WOLFSSL_SMALL_STACK
2207
    char*    domainName;
2208
#else
2209
    char     domainName[MAX_URL_ITEM_SIZE];
2210
#endif
2211
2212
#ifdef WOLFSSL_SMALL_STACK
2213
    domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
2214
                                                       DYNAMIC_TYPE_TMP_BUFFER);
2215
    if (domainName == NULL) {
2216
        return MEMORY_E;
2217
    }
2218
#endif
2219
2220
    if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
2221
        WOLFSSL_MSG("Unable to decode CRL URL");
2222
    }
2223
    else {
2224
        int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
2225
        byte* httpBuf   = (byte*)XMALLOC((size_t)httpBufSz, crl->heap,
2226
                                                              DYNAMIC_TYPE_CRL);
2227
        if (httpBuf == NULL) {
2228
            WOLFSSL_MSG("Unable to create CRL response buffer");
2229
        }
2230
        else {
2231
            httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
2232
                httpBuf, httpBufSz);
2233
2234
            ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
2235
            if (ret != 0) {
2236
                WOLFSSL_MSG("CRL connection failed");
2237
            }
2238
            else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
2239
                                                                 != httpBufSz) {
2240
                WOLFSSL_MSG("CRL http get failed");
2241
            }
2242
            else {
2243
                ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
2244
                                                      HTTP_SCRATCH_BUFFER_SIZE);
2245
            }
2246
            if (sfd != SOCKET_INVALID)
2247
                CloseSocket(sfd);
2248
            XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
2249
        }
2250
    }
2251
2252
#ifdef WOLFSSL_SMALL_STACK
2253
    XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
2254
#endif
2255
2256
    return ret;
2257
}
2258
#endif /* HAVE_CRL && HAVE_CRL_IO */
2259
2260
#endif /* HAVE_HTTP_CLIENT */
2261
2262
2263
2264
void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
2265
0
{
2266
0
    if (ctx) {
2267
0
        ctx->CBIORecv = CBIORecv;
2268
    #ifdef OPENSSL_EXTRA
2269
        ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
2270
    #endif
2271
0
    }
2272
0
}
2273
2274
2275
void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
2276
0
{
2277
0
    if (ctx) {
2278
0
        ctx->CBIOSend = CBIOSend;
2279
    #ifdef OPENSSL_EXTRA
2280
        ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
2281
    #endif
2282
0
    }
2283
0
}
2284
2285
2286
/* sets the IO callback to use for receives at WOLFSSL level */
2287
void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv)
2288
0
{
2289
0
    if (ssl) {
2290
0
        ssl->CBIORecv = CBIORecv;
2291
    #ifdef OPENSSL_EXTRA
2292
        ssl->cbioFlag |= WOLFSSL_CBIO_RECV;
2293
    #endif
2294
0
    }
2295
0
}
2296
2297
2298
/* sets the IO callback to use for sends at WOLFSSL level */
2299
void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
2300
0
{
2301
0
    if (ssl) {
2302
0
        ssl->CBIOSend = CBIOSend;
2303
    #ifdef OPENSSL_EXTRA
2304
        ssl->cbioFlag |= WOLFSSL_CBIO_SEND;
2305
    #endif
2306
0
    }
2307
0
}
2308
2309
void wolfSSL_SSLDisableRead(WOLFSSL *ssl)
2310
0
{
2311
0
    if (ssl) {
2312
0
        ssl->options.disableRead = 1;
2313
0
    }
2314
0
}
2315
2316
void wolfSSL_SSLEnableRead(WOLFSSL *ssl)
2317
0
{
2318
0
    if (ssl) {
2319
0
        ssl->options.disableRead = 0;
2320
0
    }
2321
0
}
2322
2323
2324
void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
2325
0
{
2326
0
    if (ssl)
2327
0
        ssl->IOCB_ReadCtx = rctx;
2328
0
}
2329
2330
2331
void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
2332
0
{
2333
0
    if (ssl)
2334
0
        ssl->IOCB_WriteCtx = wctx;
2335
0
}
2336
2337
2338
void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
2339
0
{
2340
0
    if (ssl)
2341
0
        return ssl->IOCB_ReadCtx;
2342
2343
0
    return NULL;
2344
0
}
2345
2346
2347
void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
2348
0
{
2349
0
    if (ssl)
2350
0
        return ssl->IOCB_WriteCtx;
2351
2352
0
    return NULL;
2353
0
}
2354
2355
2356
void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
2357
0
{
2358
0
    if (ssl)
2359
0
        ssl->rflags = flags;
2360
0
}
2361
2362
2363
void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
2364
0
{
2365
0
    if (ssl)
2366
0
        ssl->wflags = flags;
2367
0
}
2368
2369
2370
#ifdef WOLFSSL_DTLS
2371
2372
void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
2373
{
2374
    if (ctx)
2375
        ctx->CBIOCookie = cb;
2376
}
2377
2378
2379
void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
2380
{
2381
    if (ssl)
2382
        ssl->IOCB_CookieCtx = ctx;
2383
}
2384
2385
2386
void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
2387
{
2388
    if (ssl)
2389
        return ssl->IOCB_CookieCtx;
2390
2391
    return NULL;
2392
}
2393
#endif /* WOLFSSL_DTLS */
2394
2395
#ifdef WOLFSSL_SESSION_EXPORT
2396
2397
void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
2398
{
2399
    if (ctx)
2400
        ctx->CBGetPeer = cb;
2401
}
2402
2403
2404
void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
2405
{
2406
    if (ctx)
2407
        ctx->CBSetPeer = cb;
2408
}
2409
2410
#endif /* WOLFSSL_SESSION_EXPORT */
2411
2412
2413
#ifdef HAVE_NETX
2414
2415
/* The NetX receive callback
2416
 *  return :  bytes read, or error
2417
 */
2418
int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2419
{
2420
    NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
2421
    ULONG left;
2422
    ULONG total;
2423
    ULONG copied = 0;
2424
    UINT  status;
2425
2426
    (void)ssl;
2427
2428
    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
2429
        WOLFSSL_MSG("NetX Recv NULL parameters");
2430
        return WOLFSSL_CBIO_ERR_GENERAL;
2431
    }
2432
2433
    if (nxCtx->nxPacket == NULL) {
2434
        status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
2435
                                       nxCtx->nxWait);
2436
        if (status != NX_SUCCESS) {
2437
            WOLFSSL_MSG("NetX Recv receive error");
2438
            return WOLFSSL_CBIO_ERR_GENERAL;
2439
        }
2440
    }
2441
2442
    if (nxCtx->nxPacket) {
2443
        status = nx_packet_length_get(nxCtx->nxPacket, &total);
2444
        if (status != NX_SUCCESS) {
2445
            WOLFSSL_MSG("NetX Recv length get error");
2446
            return WOLFSSL_CBIO_ERR_GENERAL;
2447
        }
2448
2449
        left = total - nxCtx->nxOffset;
2450
        status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
2451
                                               buf, sz, &copied);
2452
        if (status != NX_SUCCESS) {
2453
            WOLFSSL_MSG("NetX Recv data extract offset error");
2454
            return WOLFSSL_CBIO_ERR_GENERAL;
2455
        }
2456
2457
        nxCtx->nxOffset += copied;
2458
2459
        if (copied == left) {
2460
            WOLFSSL_MSG("NetX Recv Drained packet");
2461
            nx_packet_release(nxCtx->nxPacket);
2462
            nxCtx->nxPacket = NULL;
2463
            nxCtx->nxOffset = 0;
2464
        }
2465
    }
2466
2467
    return copied;
2468
}
2469
2470
2471
/* The NetX send callback
2472
 *  return : bytes sent, or error
2473
 */
2474
int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2475
{
2476
    NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
2477
    NX_PACKET*      packet;
2478
    NX_PACKET_POOL* pool;   /* shorthand */
2479
    UINT            status;
2480
2481
    (void)ssl;
2482
2483
    if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
2484
        WOLFSSL_MSG("NetX Send NULL parameters");
2485
        return WOLFSSL_CBIO_ERR_GENERAL;
2486
    }
2487
2488
    pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
2489
    status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
2490
                                nxCtx->nxWait);
2491
    if (status != NX_SUCCESS) {
2492
        WOLFSSL_MSG("NetX Send packet alloc error");
2493
        return WOLFSSL_CBIO_ERR_GENERAL;
2494
    }
2495
2496
    status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
2497
    if (status != NX_SUCCESS) {
2498
        nx_packet_release(packet);
2499
        WOLFSSL_MSG("NetX Send data append error");
2500
        return WOLFSSL_CBIO_ERR_GENERAL;
2501
    }
2502
2503
    status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
2504
    if (status != NX_SUCCESS) {
2505
        nx_packet_release(packet);
2506
        WOLFSSL_MSG("NetX Send socket send error");
2507
        return WOLFSSL_CBIO_ERR_GENERAL;
2508
    }
2509
2510
    return sz;
2511
}
2512
2513
2514
/* like set_fd, but for default NetX context */
2515
void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
2516
{
2517
    if (ssl) {
2518
        ssl->nxCtx.nxSocket = nxSocket;
2519
        ssl->nxCtx.nxWait   = waitOption;
2520
    }
2521
}
2522
2523
#endif /* HAVE_NETX */
2524
2525
2526
#ifdef MICRIUM
2527
2528
/* Micrium uTCP/IP port, using the NetSock API
2529
 * TCP and UDP are currently supported with the callbacks below.
2530
 *
2531
 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
2532
 * and EmbedSetPeer() callbacks implemented.
2533
 *
2534
 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
2535
 * callback implemented.
2536
 *
2537
 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
2538
 * callback implemented.
2539
 */
2540
2541
/* The Micrium uTCP/IP send callback
2542
 * return : bytes sent, or error
2543
 */
2544
int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2545
{
2546
    NET_SOCK_ID sd = *(int*)ctx;
2547
    NET_SOCK_RTN_CODE ret;
2548
    NET_ERR err;
2549
2550
    ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
2551
    if (ret < 0) {
2552
        WOLFSSL_MSG("Embed Send error");
2553
2554
        if (err == NET_ERR_TX) {
2555
            WOLFSSL_MSG("\tWould block");
2556
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
2557
2558
        } else {
2559
            WOLFSSL_MSG("\tGeneral error");
2560
            return WOLFSSL_CBIO_ERR_GENERAL;
2561
        }
2562
    }
2563
2564
    return ret;
2565
}
2566
2567
/* The Micrium uTCP/IP receive callback
2568
 *  return : nb bytes read, or error
2569
 */
2570
int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2571
{
2572
    NET_SOCK_ID sd = *(int*)ctx;
2573
    NET_SOCK_RTN_CODE ret;
2574
    NET_ERR err;
2575
2576
    #ifdef WOLFSSL_DTLS
2577
    {
2578
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
2579
        /* Don't use ssl->options.handShakeDone since it is true even if
2580
         * we are in the process of renegotiation */
2581
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
2582
        #ifdef WOLFSSL_DTLS13
2583
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
2584
            doDtlsTimeout =
2585
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
2586
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
2587
        }
2588
        #endif /* WOLFSSL_DTLS13 */
2589
2590
        if (!doDtlsTimeout)
2591
            dtls_timeout = 0;
2592
2593
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
2594
            /* needs timeout in milliseconds */
2595
            #ifdef WOLFSSL_DTLS13
2596
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
2597
                IsAtLeastTLSv1_3(ssl->version)) {
2598
                dtls_timeout = (1000 * dtls_timeout) / 4;
2599
            } else
2600
            #endif /* WOLFSSL_DTLS13 */
2601
                dtls_timeout = 1000 * dtls_timeout;
2602
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
2603
            if (err != NET_SOCK_ERR_NONE) {
2604
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
2605
            }
2606
        }
2607
    }
2608
    #endif /* WOLFSSL_DTLS */
2609
2610
    ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
2611
    if (ret < 0) {
2612
        WOLFSSL_MSG("Embed Receive error");
2613
2614
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
2615
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
2616
            if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
2617
                WOLFSSL_MSG("\tWould block");
2618
                return WOLFSSL_CBIO_ERR_WANT_READ;
2619
            }
2620
            else {
2621
                WOLFSSL_MSG("\tSocket timeout");
2622
                return WOLFSSL_CBIO_ERR_TIMEOUT;
2623
            }
2624
2625
        } else if (err == NET_SOCK_ERR_CLOSED) {
2626
            WOLFSSL_MSG("Embed receive connection closed");
2627
            return WOLFSSL_CBIO_ERR_CONN_CLOSE;
2628
2629
        } else {
2630
            WOLFSSL_MSG("\tGeneral error");
2631
            return WOLFSSL_CBIO_ERR_GENERAL;
2632
        }
2633
    }
2634
2635
    return ret;
2636
}
2637
2638
/* The Micrium uTCP/IP receivefrom callback
2639
 *  return : nb bytes read, or error
2640
 */
2641
int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2642
{
2643
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
2644
    NET_SOCK_ID       sd = dtlsCtx->rfd;
2645
    NET_SOCK_ADDR     peer;
2646
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
2647
    NET_SOCK_RTN_CODE ret;
2648
    NET_ERR err;
2649
2650
    WOLFSSL_ENTER("MicriumReceiveFrom");
2651
2652
#ifdef WOLFSSL_DTLS
2653
    {
2654
        int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
2655
        /* Don't use ssl->options.handShakeDone since it is true even if
2656
         * we are in the process of renegotiation */
2657
        byte doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
2658
2659
        #ifdef WOLFSSL_DTLS13
2660
        if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
2661
            doDtlsTimeout =
2662
                doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL ||
2663
                (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
2664
        }
2665
        #endif /* WOLFSSL_DTLS13 */
2666
2667
        if (!doDtlsTimeout)
2668
            dtls_timeout = 0;
2669
2670
        if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
2671
            /* needs timeout in milliseconds */
2672
            #ifdef WOLFSSL_DTLS13
2673
            if (wolfSSL_dtls13_use_quick_timeout(ssl) &&
2674
                IsAtLeastTLSv1_3(ssl->version)) {
2675
                dtls_timeout = (1000 * dtls_timeout) / 4;
2676
            } else
2677
            #endif /* WOLFSSL_DTLS13 */
2678
                dtls_timeout = 1000 * dtls_timeout;
2679
            NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout, &err);
2680
            if (err != NET_SOCK_ERR_NONE) {
2681
                WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
2682
            }
2683
        }
2684
    }
2685
#endif /* WOLFSSL_DTLS */
2686
2687
    ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
2688
                             0, 0, 0, &err);
2689
    if (ret < 0) {
2690
        WOLFSSL_MSG("Embed Receive From error");
2691
2692
        if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
2693
            err == NET_ERR_FAULT_LOCK_ACQUIRE) {
2694
            if (wolfSSL_dtls_get_using_nonblock(ssl)) {
2695
                WOLFSSL_MSG("\tWould block");
2696
                return WOLFSSL_CBIO_ERR_WANT_READ;
2697
            }
2698
            else {
2699
                WOLFSSL_MSG("\tSocket timeout");
2700
                return WOLFSSL_CBIO_ERR_TIMEOUT;
2701
            }
2702
        } else {
2703
            WOLFSSL_MSG("\tGeneral error");
2704
            return WOLFSSL_CBIO_ERR_GENERAL;
2705
        }
2706
    }
2707
    else {
2708
        if (dtlsCtx->peer.sz > 0
2709
                && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
2710
                && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
2711
            WOLFSSL_MSG("\tIgnored packet from invalid peer");
2712
            return WOLFSSL_CBIO_ERR_WANT_READ;
2713
        }
2714
    }
2715
2716
    return ret;
2717
}
2718
2719
/* The Micrium uTCP/IP sendto callback
2720
 *  return : nb bytes sent, or error
2721
 */
2722
int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2723
{
2724
    WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
2725
    NET_SOCK_ID sd = dtlsCtx->wfd;
2726
    NET_SOCK_RTN_CODE ret;
2727
    NET_ERR err;
2728
2729
    WOLFSSL_ENTER("MicriumSendTo");
2730
2731
    ret = NetSock_TxDataTo(sd, buf, sz, ssl->wflags,
2732
                           (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
2733
                           (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
2734
                           &err);
2735
    if (err < 0) {
2736
        WOLFSSL_MSG("Embed Send To error");
2737
2738
        if (err == NET_ERR_TX) {
2739
            WOLFSSL_MSG("\tWould block");
2740
            return WOLFSSL_CBIO_ERR_WANT_WRITE;
2741
2742
        } else {
2743
            WOLFSSL_MSG("\tGeneral error");
2744
            return WOLFSSL_CBIO_ERR_GENERAL;
2745
        }
2746
    }
2747
2748
    return ret;
2749
}
2750
2751
/* Micrium DTLS Generate Cookie callback
2752
 *  return : number of bytes copied into buf, or error
2753
 */
2754
#if defined(NO_SHA) && !defined(NO_SHA256)
2755
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
2756
#elif !defined(NO_SHA)
2757
    #define MICRIUM_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
2758
#else
2759
    #error Must enable either SHA-1 or SHA256 (or both) for Micrium.
2760
#endif
2761
int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
2762
{
2763
    NET_SOCK_ADDR peer;
2764
    NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
2765
    byte digest[MICRIUM_COOKIE_DIGEST_SIZE];
2766
    int  ret = 0;
2767
2768
    (void)ctx;
2769
2770
    XMEMSET(&peer, 0, sizeof(peer));
2771
    if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
2772
                              (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
2773
        WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
2774
        return GEN_COOKIE_E;
2775
    }
2776
2777
#if defined(NO_SHA) && !defined(NO_SHA256)
2778
    ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
2779
#else
2780
    ret = wc_ShaHash((byte*)&peer, peerSz, digest);
2781
#endif
2782
    if (ret != 0)
2783
        return ret;
2784
2785
    if (sz > MICRIUM_COOKIE_DIGEST_SIZE)
2786
        sz = MICRIUM_COOKIE_DIGEST_SIZE;
2787
    XMEMCPY(buf, digest, sz);
2788
2789
    return sz;
2790
}
2791
2792
#endif /* MICRIUM */
2793
2794
#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
2795
2796
#include <os/os_error.h>
2797
#include <os/os_mbuf.h>
2798
#include <os/os_mempool.h>
2799
2800
#define MB_NAME "wolfssl_mb"
2801
2802
typedef struct Mynewt_Ctx {
2803
        struct mn_socket *mnSocket;          /* send/recv socket handler */
2804
        struct mn_sockaddr_in mnSockAddrIn;  /* socket address */
2805
        struct os_mbuf *mnPacket;            /* incoming packet handle
2806
                                                for short reads */
2807
        int reading;                         /* reading flag */
2808
2809
        /* private */
2810
        void *mnMemBuffer;                   /* memory buffer for mempool */
2811
        struct os_mempool mnMempool;         /* mempool */
2812
        struct os_mbuf_pool mnMbufpool;      /* mbuf pool */
2813
} Mynewt_Ctx;
2814
2815
void mynewt_ctx_clear(void *ctx) {
2816
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2817
    if(!mynewt_ctx) return;
2818
2819
    if(mynewt_ctx->mnPacket) {
2820
        os_mbuf_free_chain(mynewt_ctx->mnPacket);
2821
        mynewt_ctx->mnPacket = NULL;
2822
    }
2823
    os_mempool_clear(&mynewt_ctx->mnMempool);
2824
    XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
2825
    XFREE(mynewt_ctx, 0, 0);
2826
}
2827
2828
/* return Mynewt_Ctx instance */
2829
void* mynewt_ctx_new() {
2830
    int rc = 0;
2831
    Mynewt_Ctx *mynewt_ctx;
2832
    int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
2833
    int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
2834
    int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
2835
2836
    mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
2837
                                       NULL, DYNAMIC_TYPE_TMP_BUFFER);
2838
    if(!mynewt_ctx) return NULL;
2839
2840
    XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
2841
    mynewt_ctx->mnMemBuffer = (void *)XMALLOC(mempool_bytes, 0, 0);
2842
    if(!mynewt_ctx->mnMemBuffer) {
2843
        mynewt_ctx_clear((void*)mynewt_ctx);
2844
        return NULL;
2845
    }
2846
2847
    rc = os_mempool_init(&mynewt_ctx->mnMempool,
2848
                         mem_buf_count, mem_buf_size,
2849
                         mynewt_ctx->mnMemBuffer, MB_NAME);
2850
    if(rc != 0) {
2851
        mynewt_ctx_clear((void*)mynewt_ctx);
2852
        return NULL;
2853
    }
2854
    rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
2855
                           mem_buf_count, mem_buf_size);
2856
    if(rc != 0) {
2857
        mynewt_ctx_clear((void*)mynewt_ctx);
2858
        return NULL;
2859
    }
2860
2861
    return mynewt_ctx;
2862
}
2863
2864
static void mynewt_sock_writable(void *arg, int err);
2865
static void mynewt_sock_readable(void *arg, int err);
2866
static const union mn_socket_cb mynewt_sock_cbs = {
2867
    .socket.writable = mynewt_sock_writable,
2868
    .socket.readable = mynewt_sock_readable,
2869
};
2870
static void mynewt_sock_writable(void *arg, int err)
2871
{
2872
    /* do nothing */
2873
}
2874
static void mynewt_sock_readable(void *arg, int err)
2875
{
2876
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
2877
    if (err && mynewt_ctx->reading) {
2878
        mynewt_ctx->reading = 0;
2879
    }
2880
}
2881
2882
/* The Mynewt receive callback
2883
 *  return :  bytes read, or error
2884
 */
2885
int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2886
{
2887
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2888
    int rc = 0;
2889
    struct mn_sockaddr_in from;
2890
    struct os_mbuf *m;
2891
    int read_sz = 0;
2892
    word16 total;
2893
2894
    if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
2895
        WOLFSSL_MSG("Mynewt Recv NULL parameters");
2896
        return WOLFSSL_CBIO_ERR_GENERAL;
2897
    }
2898
2899
    if(mynewt_ctx->mnPacket == NULL) {
2900
        mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
2901
        if(mynewt_ctx->mnPacket == NULL) {
2902
            return MEMORY_E;
2903
        }
2904
2905
        mynewt_ctx->reading = 1;
2906
        while(mynewt_ctx->reading && rc == 0) {
2907
            rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
2908
            if(rc == MN_ECONNABORTED) {
2909
                rc = 0;
2910
                mynewt_ctx->reading = 0;
2911
                break;
2912
            }
2913
            if (!(rc == 0 || rc == MN_EAGAIN)) {
2914
                WOLFSSL_MSG("Mynewt Recv receive error");
2915
                mynewt_ctx->reading = 0;
2916
                break;
2917
            }
2918
            if(rc == 0) {
2919
                int len = OS_MBUF_PKTLEN(m);
2920
                if(len == 0) {
2921
                    break;
2922
                }
2923
                rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
2924
                if(rc != 0) {
2925
                    WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
2926
                    break;
2927
                }
2928
                os_mbuf_free_chain(m);
2929
                m = NULL;
2930
            } else if(rc == MN_EAGAIN) {
2931
                /* continue to until reading all of packet data. */
2932
                rc = 0;
2933
                break;
2934
            }
2935
        }
2936
        if(rc != 0) {
2937
            mynewt_ctx->reading = 0;
2938
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
2939
            mynewt_ctx->mnPacket = NULL;
2940
            return rc;
2941
        }
2942
    }
2943
2944
    if(mynewt_ctx->mnPacket) {
2945
        total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
2946
        read_sz = (total >= sz)? sz : total;
2947
2948
        os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
2949
        os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
2950
2951
        if (read_sz == total) {
2952
            WOLFSSL_MSG("Mynewt Recv Drained packet");
2953
            os_mbuf_free_chain(mynewt_ctx->mnPacket);
2954
            mynewt_ctx->mnPacket = NULL;
2955
        }
2956
    }
2957
2958
    return read_sz;
2959
}
2960
2961
/* The Mynewt send callback
2962
 *  return : bytes sent, or error
2963
 */
2964
int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2965
{
2966
    Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2967
    int rc = 0;
2968
    struct os_mbuf *m;
2969
    int write_sz = 0;
2970
    m = os_msys_get_pkthdr(sz, 0);
2971
    if (!m) {
2972
        WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
2973
        return WOLFSSL_CBIO_ERR_GENERAL;
2974
    }
2975
    rc = os_mbuf_copyinto(m, 0, buf, sz);
2976
    if (rc != 0) {
2977
        WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
2978
        os_mbuf_free_chain(m);
2979
        return rc;
2980
    }
2981
    rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
2982
    if(rc != 0) {
2983
        WOLFSSL_MSG("Mynewt Send mn_sendto error");
2984
        os_mbuf_free_chain(m);
2985
        return rc;
2986
    }
2987
    write_sz = sz;
2988
    return write_sz;
2989
}
2990
2991
/* like set_fd, but for default NetX context */
2992
void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
2993
{
2994
    if (ssl && ssl->mnCtx) {
2995
        Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
2996
        mynewt_ctx->mnSocket = mnSocket;
2997
        XMEMCPY(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
2998
        mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
2999
    }
3000
}
3001
3002
#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
3003
3004
#ifdef WOLFSSL_UIP
3005
#include <uip.h>
3006
#include <stdio.h>
3007
3008
/* uIP TCP/IP port, using the native tcp/udp socket api.
3009
 * TCP and UDP are currently supported with the callbacks below.
3010
 *
3011
 */
3012
/* The uIP tcp send callback
3013
 * return : bytes sent, or error
3014
 */
3015
int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3016
{
3017
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3018
    int total_written = 0;
3019
    (void)ssl;
3020
    do {
3021
        int ret;
3022
        unsigned int bytes_left = sz - total_written;
3023
        unsigned int max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
3024
        if (bytes_left > max_sendlen) {
3025
            fprintf(stderr, "uIPSend: Send limited by buffer\r\n");
3026
            bytes_left = max_sendlen;
3027
        }
3028
        if (bytes_left == 0) {
3029
            fprintf(stderr, "uIPSend: Buffer full!\r\n");
3030
            break;
3031
        }
3032
        ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
3033
        if (ret <= 0)
3034
            break;
3035
        total_written += ret;
3036
    } while(total_written < sz);
3037
    if (total_written == 0)
3038
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3039
    return total_written;
3040
}
3041
3042
int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3043
{
3044
    uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
3045
    int ret = 0;
3046
    (void)ssl;
3047
    ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
3048
    if (ret == 0)
3049
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3050
    return ret;
3051
}
3052
3053
/* The uIP uTCP/IP receive callback
3054
 *  return : nb bytes read, or error
3055
 */
3056
int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3057
{
3058
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3059
    if (!ctx || !ctx->ssl_rx_databuf)
3060
        return WOLFSSL_FATAL_ERROR;
3061
    (void)ssl;
3062
    if (ctx->ssl_rb_len > 0) {
3063
        if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
3064
            sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
3065
        XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
3066
        ctx->ssl_rb_off += sz;
3067
        if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
3068
            ctx->ssl_rb_len = 0;
3069
            ctx->ssl_rb_off = 0;
3070
        }
3071
        return sz;
3072
    } else {
3073
        return WOLFSSL_CBIO_ERR_WANT_READ;
3074
    }
3075
}
3076
3077
/* uIP DTLS Generate Cookie callback
3078
 *  return : number of bytes copied into buf, or error
3079
 */
3080
#if defined(NO_SHA) && !defined(NO_SHA256)
3081
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3082
#elif !defined(NO_SHA)
3083
    #define UIP_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3084
#else
3085
    #error Must enable either SHA-1 or SHA256 (or both) for uIP.
3086
#endif
3087
int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3088
{
3089
    uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
3090
    byte token[32];
3091
    byte digest[UIP_COOKIE_DIGEST_SIZE];
3092
    int  ret = 0;
3093
    XMEMSET(token, 0, sizeof(token));
3094
    XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
3095
    XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
3096
#if defined(NO_SHA) && !defined(NO_SHA256)
3097
    ret = wc_Sha256Hash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3098
#else
3099
    ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
3100
#endif
3101
    if (ret != 0)
3102
        return ret;
3103
    if (sz > UIP_COOKIE_DIGEST_SIZE)
3104
        sz = UIP_COOKIE_DIGEST_SIZE;
3105
    XMEMCPY(buf, digest, sz);
3106
    return sz;
3107
}
3108
3109
#endif /* WOLFSSL_UIP */
3110
3111
#ifdef WOLFSSL_GNRC
3112
3113
#include <net/sock.h>
3114
#include <net/sock/tcp.h>
3115
#include <stdio.h>
3116
3117
/* GNRC TCP/IP port, using the native tcp/udp socket api.
3118
 * TCP and UDP are currently supported with the callbacks below.
3119
 *
3120
 */
3121
/* The GNRC tcp send callback
3122
 * return : bytes sent, or error
3123
 */
3124
3125
int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
3126
{
3127
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3128
    int ret = 0;
3129
    (void)ssl;
3130
    if (!ctx)
3131
        return WOLFSSL_CBIO_ERR_GENERAL;
3132
    ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr);
3133
    if (ret == 0)
3134
        return WOLFSSL_CBIO_ERR_WANT_WRITE;
3135
    return ret;
3136
}
3137
3138
/* The GNRC TCP/IP receive callback
3139
 *  return : nb bytes read, or error
3140
 */
3141
int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
3142
{
3143
    sock_udp_ep_t ep;
3144
    int ret;
3145
    word32 timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000;
3146
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3147
    if (!ctx)
3148
        return WOLFSSL_CBIO_ERR_GENERAL;
3149
    (void)ssl;
3150
    if (wolfSSL_get_using_nonblock(ctx->ssl)) {
3151
        timeout = 0;
3152
    }
3153
    ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep);
3154
    if (ret > 0) {
3155
        if (ctx->peer_addr.port == 0)
3156
            XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t));
3157
    }
3158
    if (ret == -ETIMEDOUT) {
3159
        return WOLFSSL_CBIO_ERR_WANT_READ;
3160
    }
3161
    return ret;
3162
}
3163
3164
/* GNRC DTLS Generate Cookie callback
3165
 *  return : number of bytes copied into buf, or error
3166
 */
3167
#define GNRC_MAX_TOKEN_SIZE (32)
3168
#if defined(NO_SHA) && !defined(NO_SHA256)
3169
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
3170
#elif !defined(NO_SHA)
3171
    #define GNRC_COOKIE_DIGEST_SIZE WC_SHA_DIGEST_SIZE
3172
#else
3173
    #error Must enable either SHA-1 or SHA256 (or both) for GNRC.
3174
#endif
3175
int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
3176
{
3177
    sock_tls_t *ctx = (sock_tls_t *)_ctx;
3178
    if (!ctx)
3179
        return WOLFSSL_CBIO_ERR_GENERAL;
3180
    byte token[GNRC_MAX_TOKEN_SIZE];
3181
    byte digest[GNRC_COOKIE_DIGEST_SIZE];
3182
    int  ret = 0;
3183
    size_t token_size = sizeof(sock_udp_ep_t);
3184
    (void)ssl;
3185
    if (token_size > GNRC_MAX_TOKEN_SIZE)
3186
        token_size = GNRC_MAX_TOKEN_SIZE;
3187
    XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE);
3188
    XMEMCPY(token, &ctx->peer_addr, token_size);
3189
#if defined(NO_SHA) && !defined(NO_SHA256)
3190
    ret = wc_Sha256Hash(token, token_size, digest);
3191
#else
3192
    ret = wc_ShaHash(token, token_size, digest);
3193
#endif
3194
    if (ret != 0)
3195
        return ret;
3196
    if (sz > GNRC_COOKIE_DIGEST_SIZE)
3197
        sz = GNRC_COOKIE_DIGEST_SIZE;
3198
    XMEMCPY(buf, digest, sz);
3199
    return sz;
3200
}
3201
3202
#endif /* WOLFSSL_GNRC */
3203
3204
#ifdef WOLFSSL_LWIP_NATIVE
3205
int LwIPNativeSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3206
{
3207
    err_t ret;
3208
    WOLFSSL_LWIP_NATIVE_STATE* nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3209
3210
    ret = tcp_write(nlwip->pcb, buf, sz, TCP_WRITE_FLAG_COPY);
3211
    if (ret != ERR_OK) {
3212
        sz = WOLFSSL_FATAL_ERROR;
3213
    }
3214
3215
    return sz;
3216
}
3217
3218
3219
int LwIPNativeReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3220
{
3221
    struct pbuf *current, *head;
3222
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3223
    int ret = 0;
3224
3225
    if (ctx == NULL) {
3226
        return WOLFSSL_CBIO_ERR_GENERAL;
3227
    }
3228
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
3229
3230
    current = nlwip->pbuf;
3231
    if (current == NULL || sz > current->tot_len) {
3232
        WOLFSSL_MSG("LwIP native pbuf list is null or not enough data, want read");
3233
        ret = WOLFSSL_CBIO_ERR_WANT_READ;
3234
    }
3235
    else {
3236
        int read = 0; /* total amount read */
3237
        head = nlwip->pbuf; /* save pointer to current head */
3238
3239
        /* loop through buffers reading data */
3240
        while (current != NULL) {
3241
            int len; /* current amount to be read */
3242
3243
            len = (current->len - nlwip->pulled < sz) ?
3244
                                            (current->len - nlwip->pulled) : sz;
3245
3246
            if (read + len > sz) {
3247
                /* should never be hit but have sanity check before use */
3248
                return WOLFSSL_CBIO_ERR_GENERAL;
3249
            }
3250
3251
            /* check if is a partial read from before */
3252
            XMEMCPY(&buf[read],
3253
                   (const char *)&(((char *)(current->payload))[nlwip->pulled]),
3254
3255
                    len);
3256
            nlwip->pulled = nlwip->pulled + len;
3257
            if (nlwip->pulled >= current->len) {
3258
                WOLFSSL_MSG("Native LwIP read full pbuf");
3259
                nlwip->pbuf = current->next;
3260
                current = nlwip->pbuf;
3261
                nlwip->pulled = 0;
3262
            }
3263
            read = read + len;
3264
            ret  = read;
3265
3266
            /* read enough break out */
3267
            if (read >= sz) {
3268
                /* if more pbuf's are left in the chain then increment the
3269
                 * ref count for next in chain and free all from beginning till
3270
                 * next */
3271
                if (current != NULL) {
3272
                    pbuf_ref(current);
3273
                }
3274
3275
                /* ack and start free'ing from the current head of the chain */
3276
                pbuf_free(head);
3277
                break;
3278
            }
3279
        }
3280
    }
3281
    WOLFSSL_LEAVE("LwIPNativeReceive", ret);
3282
    return ret;
3283
}
3284
3285
3286
static err_t LwIPNativeReceiveCB(void* cb, struct tcp_pcb* pcb,
3287
                                struct pbuf* pbuf, err_t err)
3288
{
3289
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3290
3291
    if (cb == NULL || pcb == NULL) {
3292
        WOLFSSL_MSG("Expected callback was null, abort");
3293
        return ERR_ABRT;
3294
    }
3295
3296
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
3297
    if (pbuf == NULL && err == ERR_OK) {
3298
        return ERR_OK;
3299
    }
3300
3301
    if (nlwip->pbuf == NULL) {
3302
        nlwip->pbuf = pbuf;
3303
    }
3304
    else {
3305
        if (nlwip->pbuf != pbuf) {
3306
            tcp_recved(nlwip->pcb, pbuf->tot_len);
3307
            pbuf_cat(nlwip->pbuf, pbuf); /* add chain to head */
3308
        }
3309
    }
3310
3311
    if (nlwip->recv_fn) {
3312
        return nlwip->recv_fn(nlwip->arg, pcb, pbuf, err);
3313
    }
3314
3315
    WOLFSSL_LEAVE("LwIPNativeReceiveCB", nlwip->pbuf->tot_len);
3316
    return ERR_OK;
3317
}
3318
3319
3320
static err_t LwIPNativeSentCB(void* cb, struct tcp_pcb* pcb, u16_t len)
3321
{
3322
    WOLFSSL_LWIP_NATIVE_STATE* nlwip;
3323
3324
    if (cb == NULL || pcb == NULL) {
3325
        WOLFSSL_MSG("Expected callback was null, abort");
3326
        return ERR_ABRT;
3327
    }
3328
3329
    nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
3330
    if (nlwip->sent_fn) {
3331
        return nlwip->sent_fn(nlwip->arg, pcb, len);
3332
    }
3333
    return ERR_OK;
3334
}
3335
3336
3337
int wolfSSL_SetIO_LwIP(WOLFSSL* ssl, void* pcb,
3338
                          tcp_recv_fn recv_fn, tcp_sent_fn sent_fn, void *arg)
3339
{
3340
    if (ssl == NULL || pcb == NULL)
3341
        return BAD_FUNC_ARG;
3342
3343
    ssl->lwipCtx.pcb = (struct tcp_pcb *)pcb;
3344
    ssl->lwipCtx.recv_fn = recv_fn; /*  recv user callback */
3345
    ssl->lwipCtx.sent_fn = sent_fn; /*  sent user callback */
3346
    ssl->lwipCtx.arg  = arg;
3347
    ssl->lwipCtx.pbuf = 0;
3348
    ssl->lwipCtx.pulled = 0;
3349
    ssl->lwipCtx.wait   = 0;
3350
3351
    /* wolfSSL_LwIP_recv/sent_cb invokes recv/sent user callback in them. */
3352
    tcp_recv(pcb, LwIPNativeReceiveCB);
3353
    tcp_sent(pcb, LwIPNativeSentCB);
3354
    tcp_arg (pcb, (void *)&ssl->lwipCtx);
3355
    wolfSSL_SetIOReadCtx(ssl, &ssl->lwipCtx);
3356
    wolfSSL_SetIOWriteCtx(ssl, &ssl->lwipCtx);
3357
3358
    return ERR_OK;
3359
}
3360
#endif /* WOLFSSL_LWIP_NATIVE */
3361
3362
#ifdef WOLFSSL_ISOTP
3363
static int isotp_send_single_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
3364
        word16 length)
3365
{
3366
    /* Length will be at most 7 bytes to get here. Packet is length and type
3367
     * for the first byte, then up to 7 bytes of data */
3368
    ctx->frame.data[0] = ((byte)length) | (ISOTP_FRAME_TYPE_SINGLE << 4);
3369
    XMEMCPY(&ctx->frame.data[1], buf, length);
3370
    ctx->frame.length = length + 1;
3371
    return ctx->send_fn(&ctx->frame, ctx->arg);
3372
}
3373
3374
static int isotp_send_flow_control(struct isotp_wolfssl_ctx *ctx,
3375
        byte overflow)
3376
{
3377
    int ret;
3378
    /* Overflow is set it if we have been asked to receive more data than the
3379
     * user allocated a buffer for */
3380
    if (overflow) {
3381
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_ABORT |
3382
            (ISOTP_FRAME_TYPE_CONTROL << 4);
3383
    } else {
3384
        ctx->frame.data[0] = ISOTP_FLOW_CONTROL_CTS |
3385
            (ISOTP_FRAME_TYPE_CONTROL << 4);
3386
    }
3387
    /* Set the number of frames between flow control to infinite */
3388
    ctx->frame.data[1] = ISOTP_FLOW_CONTROL_FRAMES;
3389
    /* User specified frame delay */
3390
    ctx->frame.data[2] = ctx->receive_delay;
3391
    ctx->frame.length = ISOTP_FLOW_CONTROL_PACKET_SIZE;
3392
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
3393
    return ret;
3394
}
3395
3396
static int isotp_receive_flow_control(struct isotp_wolfssl_ctx *ctx)
3397
{
3398
    int ret;
3399
    enum isotp_frame_type type;
3400
    enum isotp_flow_control flow_control;
3401
    ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT);
3402
    if (ret == 0) {
3403
        return WOLFSSL_CBIO_ERR_TIMEOUT;
3404
    } else if (ret < 0) {
3405
        WOLFSSL_MSG("ISO-TP error receiving flow control packet");
3406
        return WOLFSSL_CBIO_ERR_GENERAL;
3407
    }
3408
    /* Flow control is the frame type and flow response for the first byte,
3409
     * number of frames until the next flow control packet for the second
3410
     * byte, time between frames for the third byte */
3411
    type = ctx->frame.data[0] >> 4;
3412
3413
    if (type != ISOTP_FRAME_TYPE_CONTROL) {
3414
        WOLFSSL_MSG("ISO-TP frames out of sequence");
3415
        return WOLFSSL_CBIO_ERR_GENERAL;
3416
    }
3417
3418
    flow_control = ctx->frame.data[0] & 0xf;
3419
3420
    ctx->flow_counter = 0;
3421
    ctx->flow_packets = ctx->frame.data[1];
3422
    ctx->frame_delay = ctx->frame.data[2];
3423
3424
    return flow_control;
3425
}
3426
3427
static int isotp_send_consecutive_frame(struct isotp_wolfssl_ctx *ctx)
3428
{
3429
    /* Sequence is 0 - 15 and then starts again, the first frame has an
3430
     * implied sequence of '0' */
3431
    ctx->sequence += 1;
3432
    if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
3433
        ctx->sequence = 0;
3434
    }
3435
    ctx->flow_counter++;
3436
    /* First byte it type and sequence number, up to 7 bytes of data */
3437
    ctx->frame.data[0] = ctx->sequence | (ISOTP_FRAME_TYPE_CONSECUTIVE << 4);
3438
    if (ctx->buf_length > ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE) {
3439
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr,
3440
                ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE);
3441
        ctx->buf_ptr += ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
3442
        ctx->buf_length -= ISOTP_MAX_CONSECUTIVE_FRAME_DATA_SIZE;
3443
        ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
3444
    } else {
3445
        XMEMCPY(&ctx->frame.data[1], ctx->buf_ptr, ctx->buf_length);
3446
        ctx->frame.length = ctx->buf_length + 1;
3447
        ctx->buf_length = 0;
3448
    }
3449
    return ctx->send_fn(&ctx->frame, ctx->arg);
3450
3451
}
3452
3453
static int isotp_send_first_frame(struct isotp_wolfssl_ctx *ctx, char *buf,
3454
        word16 length)
3455
{
3456
    int ret;
3457
    ctx->sequence = 0;
3458
    /* Set to 1 to trigger a flow control straight away, the flow control
3459
     * packet will set these properly */
3460
    ctx->flow_packets = ctx->flow_counter = 1;
3461
    /* First frame has 1 nibble for type, 3 nibbles for length followed by
3462
     * 6 bytes for data*/
3463
    ctx->frame.data[0] = (length >> 8) | (ISOTP_FRAME_TYPE_FIRST << 4);
3464
    ctx->frame.data[1] = length & 0xff;
3465
    XMEMCPY(&ctx->frame.data[2], buf, ISOTP_FIRST_FRAME_DATA_SIZE);
3466
    ctx->buf_ptr = buf + ISOTP_FIRST_FRAME_DATA_SIZE;
3467
    ctx->buf_length = length - ISOTP_FIRST_FRAME_DATA_SIZE;
3468
    ctx->frame.length = ISOTP_CAN_BUS_PAYLOAD_SIZE;
3469
    ret = ctx->send_fn(&ctx->frame, ctx->arg);
3470
    if (ret <= 0) {
3471
        WOLFSSL_MSG("ISO-TP error sending first frame");
3472
        return WOLFSSL_CBIO_ERR_GENERAL;
3473
    }
3474
    while(ctx->buf_length) {
3475
        /* The receiver can set how often to get a flow control packet. If it
3476
         * is time, then get the packet. Note that this will always happen
3477
         * after the first packet */
3478
        if ((ctx->flow_packets > 0) &&
3479
                (ctx->flow_counter == ctx->flow_packets)) {
3480
            ret = isotp_receive_flow_control(ctx);
3481
        }
3482
        /* Frame delay <= 0x7f is in ms, 0xfX is X * 100 us */
3483
        if (ctx->frame_delay) {
3484
            if (ctx->frame_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
3485
                ctx->delay_fn(ctx->frame_delay * 1000);
3486
            } else {
3487
                ctx->delay_fn((ctx->frame_delay & 0xf) * 100);
3488
            }
3489
        }
3490
        switch (ret) {
3491
            /* Clear to send */
3492
            case ISOTP_FLOW_CONTROL_CTS:
3493
                if (isotp_send_consecutive_frame(ctx) < 0) {
3494
                    WOLFSSL_MSG("ISO-TP error sending consecutive frame");
3495
                    return WOLFSSL_CBIO_ERR_GENERAL;
3496
                }
3497
                break;
3498
            /* Receiver says "WAIT", so we wait for another flow control
3499
             * packet, or abort if we have waited too long */
3500
            case ISOTP_FLOW_CONTROL_WAIT:
3501
                ctx->wait_counter += 1;
3502
                if (ctx->wait_counter > ISOTP_DEFAULT_WAIT_COUNT) {
3503
                    WOLFSSL_MSG("ISO-TP receiver told us to wait too many"
3504
                            " times");
3505
                    return WOLFSSL_CBIO_ERR_WANT_WRITE;
3506
                }
3507
                break;
3508
            /* Receiver is not ready to receive packet, so abort */
3509
            case ISOTP_FLOW_CONTROL_ABORT:
3510
                WOLFSSL_MSG("ISO-TP receiver aborted transmission");
3511
                return WOLFSSL_CBIO_ERR_WANT_WRITE;
3512
            default:
3513
                WOLFSSL_MSG("ISO-TP got unexpected flow control packet");
3514
                return WOLFSSL_CBIO_ERR_GENERAL;
3515
        }
3516
    }
3517
    return 0;
3518
}
3519
3520
int ISOTP_Send(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3521
{
3522
    int ret;
3523
    struct isotp_wolfssl_ctx *isotp_ctx;
3524
    (void) ssl;
3525
3526
    if (!ctx) {
3527
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
3528
        return WOLFSSL_CBIO_ERR_GENERAL;
3529
    }
3530
    isotp_ctx = (struct isotp_wolfssl_ctx*) ctx;
3531
3532
    /* ISO-TP cannot send more than 4095 bytes, this limits the packet size
3533
     * and wolfSSL will try again with the remaining data */
3534
    if (sz > ISOTP_MAX_DATA_SIZE) {
3535
        sz = ISOTP_MAX_DATA_SIZE;
3536
    }
3537
    /* Can't send whilst we are receiving */
3538
    if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
3539
        return WOLFSSL_ERROR_WANT_WRITE;
3540
    }
3541
    isotp_ctx->state = ISOTP_CONN_STATE_SENDING;
3542
3543
    /* Assuming normal addressing */
3544
    if (sz <= ISOTP_SINGLE_FRAME_DATA_SIZE) {
3545
        ret = isotp_send_single_frame(isotp_ctx, buf, (word16)sz);
3546
    } else {
3547
        ret = isotp_send_first_frame(isotp_ctx, buf, (word16)sz);
3548
    }
3549
    isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3550
3551
    if (ret == 0) {
3552
        return sz;
3553
    }
3554
    return ret;
3555
}
3556
3557
static int isotp_receive_single_frame(struct isotp_wolfssl_ctx *ctx)
3558
{
3559
    byte data_size;
3560
3561
    /* 1 nibble for data size which will be 1 - 7 in a regular 8 byte CAN
3562
     * packet */
3563
    data_size = (byte)ctx->frame.data[0] & 0xf;
3564
    if (ctx->receive_buffer_size < (int)data_size) {
3565
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
3566
        return BUFFER_E;
3567
    }
3568
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[1], data_size);
3569
    return data_size;
3570
}
3571
3572
static int isotp_receive_multi_frame(struct isotp_wolfssl_ctx *ctx)
3573
{
3574
    int ret;
3575
    word16 data_size;
3576
    byte delay = 0;
3577
3578
    /* Increase receive timeout for enforced ms delay */
3579
    if (ctx->receive_delay <= ISOTP_MAX_MS_FRAME_DELAY) {
3580
        delay = ctx->receive_delay;
3581
    }
3582
    /* Still processing first frame.
3583
     * Full data size is lower nibble of first byte for the most significant
3584
     * followed by the second byte for the rest. Last 6 bytes are data */
3585
    data_size = ((ctx->frame.data[0] & 0xf) << 8) + ctx->frame.data[1];
3586
    XMEMCPY(ctx->receive_buffer, &ctx->frame.data[2], ISOTP_FIRST_FRAME_DATA_SIZE);
3587
    /* Need to send a flow control packet to either cancel or continue
3588
     * transmission of data */
3589
    if (ctx->receive_buffer_size < data_size) {
3590
        isotp_send_flow_control(ctx, TRUE);
3591
        WOLFSSL_MSG("ISO-TP buffer is too small to receive data");
3592
        return BUFFER_E;
3593
    }
3594
    isotp_send_flow_control(ctx, FALSE);
3595
3596
    ctx->buf_length = ISOTP_FIRST_FRAME_DATA_SIZE;
3597
    ctx->buf_ptr = ctx->receive_buffer + ISOTP_FIRST_FRAME_DATA_SIZE;
3598
    data_size -= ISOTP_FIRST_FRAME_DATA_SIZE;
3599
    ctx->sequence = 1;
3600
3601
    while(data_size) {
3602
        enum isotp_frame_type type;
3603
        byte sequence;
3604
        byte frame_len;
3605
        ret = ctx->recv_fn(&ctx->frame, ctx->arg, ISOTP_DEFAULT_TIMEOUT +
3606
                (delay / 1000));
3607
        if (ret == 0) {
3608
            return WOLFSSL_CBIO_ERR_TIMEOUT;
3609
        }
3610
        type = ctx->frame.data[0] >> 4;
3611
        /* Consecutive frames have sequence number as lower nibble */
3612
        sequence = ctx->frame.data[0] & 0xf;
3613
        if (type != ISOTP_FRAME_TYPE_CONSECUTIVE) {
3614
            WOLFSSL_MSG("ISO-TP frames out of sequence");
3615
            return WOLFSSL_CBIO_ERR_GENERAL;
3616
        }
3617
        if (sequence != ctx->sequence) {
3618
            WOLFSSL_MSG("ISO-TP frames out of sequence");
3619
            return WOLFSSL_CBIO_ERR_GENERAL;
3620
        }
3621
        /* Last 7 bytes or whatever we got after the first byte is data */
3622
        frame_len = ctx->frame.length - 1;
3623
        XMEMCPY(ctx->buf_ptr, &ctx->frame.data[1], frame_len);
3624
        ctx->buf_ptr += frame_len;
3625
        ctx->buf_length += frame_len;
3626
        data_size -= frame_len;
3627
3628
        /* Sequence is 0 - 15 (first 0 is implied for first packet */
3629
        ctx->sequence++;
3630
        if (ctx->sequence > ISOTP_MAX_SEQUENCE_COUNTER) {
3631
            ctx->sequence = 0;
3632
        }
3633
    }
3634
    return ctx->buf_length;
3635
3636
}
3637
3638
/* The wolfSSL receive callback, needs to buffer because we need to grab all
3639
 * incoming data, even if wolfSSL doesn't want it all yet */
3640
int ISOTP_Receive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
3641
{
3642
    enum isotp_frame_type type;
3643
    int ret;
3644
    struct isotp_wolfssl_ctx *isotp_ctx;
3645
    (void) ssl;
3646
3647
    if (!ctx) {
3648
        WOLFSSL_MSG("ISO-TP requires wolfSSL_SetIO_ISOTP to be called first");
3649
        return WOLFSSL_CBIO_ERR_TIMEOUT;
3650
    }
3651
    isotp_ctx = (struct isotp_wolfssl_ctx*)ctx;
3652
3653
    /* Is buffer empty? If so, fill it */
3654
    if (!isotp_ctx->receive_buffer_len) {
3655
        /* Can't send whilst we are receiving */
3656
        if (isotp_ctx->state != ISOTP_CONN_STATE_IDLE) {
3657
            return WOLFSSL_ERROR_WANT_READ;
3658
        }
3659
        isotp_ctx->state = ISOTP_CONN_STATE_RECEIVING;
3660
        do {
3661
            ret = isotp_ctx->recv_fn(&isotp_ctx->frame, isotp_ctx->arg,
3662
                    ISOTP_DEFAULT_TIMEOUT);
3663
        } while (ret == 0);
3664
        if (ret == 0) {
3665
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3666
            return WOLFSSL_CBIO_ERR_TIMEOUT;
3667
        } else if (ret < 0) {
3668
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3669
            WOLFSSL_MSG("ISO-TP receive error");
3670
            return WOLFSSL_CBIO_ERR_GENERAL;
3671
        }
3672
3673
        type = (enum isotp_frame_type) isotp_ctx->frame.data[0] >> 4;
3674
3675
        if (type == ISOTP_FRAME_TYPE_SINGLE) {
3676
            isotp_ctx->receive_buffer_len =
3677
                isotp_receive_single_frame(isotp_ctx);
3678
        } else if (type == ISOTP_FRAME_TYPE_FIRST) {
3679
            isotp_ctx->receive_buffer_len =
3680
                isotp_receive_multi_frame(isotp_ctx);
3681
        } else {
3682
            /* Should never get here */
3683
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3684
            WOLFSSL_MSG("ISO-TP frames out of sequence");
3685
            return WOLFSSL_CBIO_ERR_GENERAL;
3686
        }
3687
        if (isotp_ctx->receive_buffer_len <= 1) {
3688
            isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3689
            return isotp_ctx->receive_buffer_len;
3690
        } else {
3691
            isotp_ctx->receive_buffer_ptr = isotp_ctx->receive_buffer;
3692
        }
3693
        isotp_ctx->state = ISOTP_CONN_STATE_IDLE;
3694
    }
3695
3696
    /* Return from the buffer */
3697
    if (isotp_ctx->receive_buffer_len >= sz) {
3698
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr, sz);
3699
        isotp_ctx->receive_buffer_ptr+= sz;
3700
        isotp_ctx->receive_buffer_len-= sz;
3701
        return sz;
3702
    } else {
3703
        XMEMCPY(buf, isotp_ctx->receive_buffer_ptr,
3704
                isotp_ctx->receive_buffer_len);
3705
        sz = isotp_ctx->receive_buffer_len;
3706
        isotp_ctx->receive_buffer_len = 0;
3707
        return sz;
3708
    }
3709
}
3710
3711
int wolfSSL_SetIO_ISOTP(WOLFSSL *ssl, isotp_wolfssl_ctx *ctx,
3712
        can_recv_fn recv_fn, can_send_fn send_fn, can_delay_fn delay_fn,
3713
        word32 receive_delay, char *receive_buffer, int receive_buffer_size,
3714
        void *arg)
3715
{
3716
    if (!ctx || !recv_fn || !send_fn || !delay_fn || !receive_buffer) {
3717
        WOLFSSL_MSG("ISO-TP has missing required parameter");
3718
        return WOLFSSL_CBIO_ERR_GENERAL;
3719
    }
3720
    ctx->recv_fn = recv_fn;
3721
    ctx->send_fn = send_fn;
3722
    ctx->arg = arg;
3723
    ctx->delay_fn = delay_fn;
3724
    ctx->frame_delay = 0;
3725
    ctx->receive_buffer = receive_buffer;
3726
    ctx->receive_buffer_size = receive_buffer_size;
3727
    ctx->receive_buffer_len = 0;
3728
    ctx->state = ISOTP_CONN_STATE_IDLE;
3729
3730
    wolfSSL_SetIOReadCtx(ssl, ctx);
3731
    wolfSSL_SetIOWriteCtx(ssl, ctx);
3732
3733
    /* Delay of 100 - 900us is 0xfX where X is value / 100. Delay of
3734
     * >= 1000 is divided by 1000. > 127ms is invalid */
3735
    if (receive_delay < 1000) {
3736
        ctx->receive_delay = 0xf0 + (receive_delay / 100);
3737
    } else if (receive_delay <= ISOTP_MAX_MS_FRAME_DELAY * 1000) {
3738
        ctx->receive_delay = receive_delay / 1000;
3739
    } else {
3740
        WOLFSSL_MSG("ISO-TP delay parameter out of bounds");
3741
        return WOLFSSL_CBIO_ERR_GENERAL;
3742
    }
3743
    return 0;
3744
}
3745
#endif /* WOLFSSL_ISOTP */
3746
#endif /* WOLFCRYPT_ONLY */