1 /* wolfio.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <wolfssl/wolfcrypt/settings.h>
29
30 #ifndef WOLFCRYPT_ONLY
31
32 #ifdef _WIN32_WCE
33 /* On WinCE winsock2.h must be included before windows.h for socket stuff */
34 #include <winsock2.h>
35 #endif
36
37 #include <wolfssl/internal.h>
38 #include <wolfssl/error-ssl.h>
39 #include <wolfssl/wolfio.h>
40
41 #if defined(HAVE_HTTP_CLIENT)
42 #include <stdlib.h> /* strtol() */
43 #endif
44
45 /*
46 Possible IO enable options:
47 * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off
48 allows user to define their own using
49 wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
50 * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: on
51 * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
52 (unless HAVE_OCSP or HAVE_CRL_IO defined)
53 * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
54 */
55
56
57 /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
58 automatic setting of default I/O functions EmbedSend() and EmbedReceive()
59 but they'll still need SetCallback xxx() at end of file
60 */
61
62 #if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
63
64 /* Translates return codes returned from
65 * send() and recv() if need be.
66 */
TranslateReturnCode(int old,int sd)67 static WC_INLINE int TranslateReturnCode(int old, int sd)
68 {
69 (void)sd;
70
71 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
72 if (old == 0) {
73 errno = SOCKET_EWOULDBLOCK;
74 return -1; /* convert to BSD style wouldblock as error */
75 }
76
77 if (old < 0) {
78 errno = RTCS_geterror(sd);
79 if (errno == RTCSERR_TCP_CONN_CLOSING)
80 return 0; /* convert to BSD style closing */
81 if (errno == RTCSERR_TCP_CONN_RLSD)
82 errno = SOCKET_ECONNRESET;
83 if (errno == RTCSERR_TCP_TIMED_OUT)
84 errno = SOCKET_EAGAIN;
85 }
86 #endif
87
88 return old;
89 }
90
wolfSSL_LastError(int err)91 static WC_INLINE int wolfSSL_LastError(int err)
92 {
93 (void)err; /* Suppress unused arg */
94
95 #ifdef USE_WINDOWS_API
96 return WSAGetLastError();
97 #elif defined(EBSNET)
98 return xn_getlasterror();
99 #elif defined(WOLFSSL_LINUXKM)
100 return err; /* Return provided error value */
101 #elif defined(FUSION_RTOS)
102 #include <fclerrno.h>
103 return FCL_GET_ERRNO;
104 #else
105 return errno;
106 #endif
107 }
108
TranslateIoError(int err)109 static int TranslateIoError(int err)
110 {
111 if (err > 0)
112 return err;
113
114 err = wolfSSL_LastError(err);
115 #if SOCKET_EWOULDBLOCK != SOCKET_EAGAIN
116 if ((err == SOCKET_EWOULDBLOCK) || (err == SOCKET_EAGAIN))
117 #else
118 if (err == SOCKET_EWOULDBLOCK)
119 #endif
120 {
121 WOLFSSL_MSG("\tWould block");
122 return WOLFSSL_CBIO_ERR_WANT_READ;
123 }
124 else if (err == SOCKET_ECONNRESET) {
125 WOLFSSL_MSG("\tConnection reset");
126 return WOLFSSL_CBIO_ERR_CONN_RST;
127 }
128 else if (err == SOCKET_EINTR) {
129 WOLFSSL_MSG("\tSocket interrupted");
130 return WOLFSSL_CBIO_ERR_ISR;
131 }
132 else if (err == SOCKET_EPIPE) {
133 WOLFSSL_MSG("\tBroken pipe");
134 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
135 }
136 else if (err == SOCKET_ECONNABORTED) {
137 WOLFSSL_MSG("\tConnection aborted");
138 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
139 }
140
141 WOLFSSL_MSG("\tGeneral error");
142 return WOLFSSL_CBIO_ERR_GENERAL;
143 }
144 #endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
145
146 #ifdef OPENSSL_EXTRA
147 #ifndef NO_BIO
148 /* Use the WOLFSSL read BIO for receiving data. This is set by the function
149 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
150 *
151 * ssl WOLFSSL struct passed in that has this function set as the receive
152 * callback.
153 * buf buffer to fill with data read
154 * sz size of buf buffer
155 * ctx a user set context
156 *
157 * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
158 */
BioReceive(WOLFSSL * ssl,char * buf,int sz,void * ctx)159 int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
160 {
161 int recvd = WOLFSSL_CBIO_ERR_GENERAL;
162
163 WOLFSSL_ENTER("BioReceive");
164
165 if (ssl->biord == NULL) {
166 WOLFSSL_MSG("WOLFSSL biord not set");
167 return WOLFSSL_CBIO_ERR_GENERAL;
168 }
169
170 recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
171 if (recvd <= 0) {
172 if (wolfSSL_BIO_supports_pending(ssl->biord) &&
173 wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
174 if (ssl->biowr->type == WOLFSSL_BIO_BIO &&
175 ssl->biowr->wrIdx != 0) {
176 /* Let's signal to the app layer that we have
177 * data pending that needs to be sent. */
178 return WOLFSSL_CBIO_ERR_WANT_WRITE;
179 }
180 return WOLFSSL_CBIO_ERR_WANT_READ;
181 }
182 else if (ssl->biord->type == WOLFSSL_BIO_SOCKET) {
183 if (recvd == 0) {
184 WOLFSSL_MSG("BioReceive connection closed");
185 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
186 }
187 #ifdef USE_WOLFSSL_IO
188 recvd = TranslateIoError(recvd);
189 #endif
190 return recvd;
191 }
192
193 /* If retry and read flags are set, return WANT_READ */
194 if ((ssl->biord->flags & WOLFSSL_BIO_FLAG_READ) &&
195 (ssl->biord->flags & WOLFSSL_BIO_FLAG_RETRY)) {
196 return WOLFSSL_CBIO_ERR_WANT_READ;
197 }
198
199 WOLFSSL_MSG("BIO general error");
200 return WOLFSSL_CBIO_ERR_GENERAL;
201 }
202
203 (void)ctx;
204 return recvd;
205 }
206
207
208 /* Use the WOLFSSL write BIO for sending data. This is set by the function
209 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
210 *
211 * ssl WOLFSSL struct passed in that has this function set as the send callback.
212 * buf buffer with data to write out
213 * sz size of buf buffer
214 * ctx a user set context
215 *
216 * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
217 */
BioSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)218 int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
219 {
220 int sent = WOLFSSL_CBIO_ERR_GENERAL;
221
222 WOLFSSL_ENTER("BioSend");
223
224 if (ssl->biowr == NULL) {
225 WOLFSSL_MSG("WOLFSSL biowr not set");
226 return WOLFSSL_CBIO_ERR_GENERAL;
227 }
228
229 sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
230 if (sent <= 0) {
231 if (ssl->biowr->type == WOLFSSL_BIO_SOCKET) {
232 #ifdef USE_WOLFSSL_IO
233 sent = TranslateIoError(sent);
234 #endif
235 return sent;
236 }
237 else if (ssl->biowr->type == WOLFSSL_BIO_BIO) {
238 if (sent == WOLFSSL_BIO_ERROR) {
239 WOLFSSL_MSG("\tWould Block");
240 return WOLFSSL_CBIO_ERR_WANT_WRITE;
241 }
242 }
243
244 /* If retry and write flags are set, return WANT_WRITE */
245 if ((ssl->biord->flags & WOLFSSL_BIO_FLAG_WRITE) &&
246 (ssl->biord->flags & WOLFSSL_BIO_FLAG_RETRY)) {
247 return WOLFSSL_CBIO_ERR_WANT_WRITE;
248 }
249
250 return WOLFSSL_CBIO_ERR_GENERAL;
251 }
252 (void)ctx;
253
254 return sent;
255 }
256 #endif /* !NO_BIO */
257 #endif /* OPENSSL_EXTRA */
258
259
260 #ifdef USE_WOLFSSL_IO
261
262 /* The receive embedded callback
263 * return : nb bytes read, or error
264 */
EmbedReceive(WOLFSSL * ssl,char * buf,int sz,void * ctx)265 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
266 {
267 int recvd;
268 #ifndef WOLFSSL_LINUXKM
269 int sd = *(int*)ctx;
270 #else
271 struct socket *sd = (struct socket*)ctx;
272 #endif
273
274 recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
275 if (recvd < 0) {
276 WOLFSSL_MSG("Embed Receive error");
277 return TranslateIoError(recvd);
278 }
279 else if (recvd == 0) {
280 WOLFSSL_MSG("Embed receive connection closed");
281 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
282 }
283
284 return recvd;
285 }
286
287 /* The send embedded callback
288 * return : nb bytes sent, or error
289 */
EmbedSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)290 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
291 {
292 int sent;
293 #ifndef WOLFSSL_LINUXKM
294 int sd = *(int*)ctx;
295 #else
296 struct socket *sd = (struct socket*)ctx;
297 #endif
298
299 #ifdef WOLFSSL_MAX_SEND_SZ
300 if (sz > WOLFSSL_MAX_SEND_SZ)
301 sz = WOLFSSL_MAX_SEND_SZ;
302 #endif
303
304 sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
305 if (sent < 0) {
306 WOLFSSL_MSG("Embed Send error");
307 return TranslateIoError(sent);
308 }
309
310 return sent;
311 }
312
313
314 #ifdef WOLFSSL_DTLS
315
316 #include <wolfssl/wolfcrypt/sha.h>
317
318 #define SENDTO_FUNCTION sendto
319 #define RECVFROM_FUNCTION recvfrom
320
321
322 /* The receive embedded callback
323 * return : nb bytes read, or error
324 */
EmbedReceiveFrom(WOLFSSL * ssl,char * buf,int sz,void * ctx)325 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
326 {
327 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
328 int recvd;
329 int sd = dtlsCtx->rfd;
330 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
331 SOCKADDR_S peer;
332 XSOCKLENT peerSz = sizeof(peer);
333
334 WOLFSSL_ENTER("EmbedReceiveFrom()");
335
336 /* Don't use ssl->options.handShakeDone since it is true even if
337 * we are in the process of renegotiation */
338 if (ssl->options.handShakeState == HANDSHAKE_DONE)
339 dtls_timeout = 0;
340
341 if (!wolfSSL_get_using_nonblock(ssl)) {
342 #ifdef USE_WINDOWS_API
343 DWORD timeout = dtls_timeout * 1000;
344 #else
345 struct timeval timeout;
346 XMEMSET(&timeout, 0, sizeof(timeout));
347 timeout.tv_sec = dtls_timeout;
348 #endif
349 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
350 sizeof(timeout)) != 0) {
351 WOLFSSL_MSG("setsockopt rcvtimeo failed");
352 }
353 }
354 #ifndef NO_ASN_TIME
355 else if(IsSCR(ssl)) {
356 if (ssl->dtls_start_timeout &&
357 LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) {
358 ssl->dtls_start_timeout = 0;
359 return WOLFSSL_CBIO_ERR_TIMEOUT;
360 }
361 else if (!ssl->dtls_start_timeout) {
362 ssl->dtls_start_timeout = LowResTimer();
363 }
364 }
365 #endif /* !NO_ASN_TIME */
366
367 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
368 (SOCKADDR*)&peer, &peerSz);
369
370 recvd = TranslateReturnCode(recvd, sd);
371
372 if (recvd < 0) {
373 WOLFSSL_MSG("Embed Receive From error");
374 recvd = TranslateIoError(recvd);
375 if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
376 !wolfSSL_dtls_get_using_nonblock(ssl)) {
377 recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
378 }
379 return recvd;
380 }
381 else {
382 if (dtlsCtx->peer.sz > 0
383 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
384 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
385 WOLFSSL_MSG(" Ignored packet from invalid peer");
386 return WOLFSSL_CBIO_ERR_WANT_READ;
387 }
388 }
389 #ifndef NO_ASN_TIME
390 ssl->dtls_start_timeout = 0;
391 #endif /* !NO_ASN_TIME */
392
393 return recvd;
394 }
395
396
397 /* The send embedded callback
398 * return : nb bytes sent, or error
399 */
EmbedSendTo(WOLFSSL * ssl,char * buf,int sz,void * ctx)400 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
401 {
402 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
403 int sd = dtlsCtx->wfd;
404 int sent;
405
406 WOLFSSL_ENTER("EmbedSendTo()");
407
408 sent = (int)SENDTO_FUNCTION(sd, buf, sz, ssl->wflags,
409 (const SOCKADDR*)dtlsCtx->peer.sa,
410 dtlsCtx->peer.sz);
411
412 sent = TranslateReturnCode(sent, sd);
413
414 if (sent < 0) {
415 WOLFSSL_MSG("Embed Send To error");
416 return TranslateIoError(sent);
417 }
418
419 return sent;
420 }
421
422
423 #ifdef WOLFSSL_MULTICAST
424
425 /* The alternate receive embedded callback for Multicast
426 * return : nb bytes read, or error
427 */
EmbedReceiveFromMcast(WOLFSSL * ssl,char * buf,int sz,void * ctx)428 int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
429 {
430 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
431 int recvd;
432 int sd = dtlsCtx->rfd;
433
434 WOLFSSL_ENTER("EmbedReceiveFromMcast()");
435
436 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
437
438 recvd = TranslateReturnCode(recvd, sd);
439
440 if (recvd < 0) {
441 WOLFSSL_MSG("Embed Receive From error");
442 recvd = TranslateIoError(recvd);
443 if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
444 !wolfSSL_dtls_get_using_nonblock(ssl)) {
445 recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
446 }
447 return recvd;
448 }
449
450 return recvd;
451 }
452 #endif /* WOLFSSL_MULTICAST */
453
454
455 /* The DTLS Generate Cookie callback
456 * return : number of bytes copied into buf, or error
457 */
EmbedGenerateCookie(WOLFSSL * ssl,byte * buf,int sz,void * ctx)458 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
459 {
460 int sd = ssl->wfd;
461 SOCKADDR_S peer;
462 XSOCKLENT peerSz = sizeof(peer);
463 byte digest[WC_SHA256_DIGEST_SIZE];
464 int ret = 0;
465
466 (void)ctx;
467
468 XMEMSET(&peer, 0, sizeof(peer));
469 if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
470 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
471 return GEN_COOKIE_E;
472 }
473
474 ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
475 if (ret != 0)
476 return ret;
477
478 if (sz > WC_SHA256_DIGEST_SIZE)
479 sz = WC_SHA256_DIGEST_SIZE;
480 XMEMCPY(buf, digest, sz);
481
482 return sz;
483 }
484 #endif /* WOLFSSL_DTLS */
485
486 #ifdef WOLFSSL_SESSION_EXPORT
487
488 #ifdef WOLFSSL_DTLS
EmbedGetPeerDTLS(WOLFSSL * ssl,char * ip,int * ipSz,unsigned short * port,int * fam)489 static int EmbedGetPeerDTLS(WOLFSSL* ssl, char* ip, int* ipSz,
490 unsigned short* port, int* fam)
491 {
492 SOCKADDR_S peer;
493 word32 peerSz;
494 int ret;
495
496 /* get peer information stored in ssl struct */
497 peerSz = sizeof(SOCKADDR_S);
498 if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
499 != WOLFSSL_SUCCESS) {
500 return ret;
501 }
502
503 /* extract family, ip, and port */
504 *fam = ((SOCKADDR_S*)&peer)->ss_family;
505 switch (*fam) {
506 case WOLFSSL_IP4:
507 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
508 ip, *ipSz) == NULL) {
509 WOLFSSL_MSG("XINET_NTOP error");
510 return SOCKET_ERROR_E;
511 }
512 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
513 break;
514
515 case WOLFSSL_IP6:
516 #ifdef WOLFSSL_IPV6
517 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
518 ip, *ipSz) == NULL) {
519 WOLFSSL_MSG("XINET_NTOP error");
520 return SOCKET_ERROR_E;
521 }
522 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
523 #endif /* WOLFSSL_IPV6 */
524 break;
525
526 default:
527 WOLFSSL_MSG("Unknown family type");
528 return SOCKET_ERROR_E;
529 }
530 ip[*ipSz - 1] = '\0'; /* make sure has terminator */
531 *ipSz = (word16)XSTRLEN(ip);
532
533 return WOLFSSL_SUCCESS;
534 }
535
EmbedSetPeerDTLS(WOLFSSL * ssl,char * ip,int ipSz,unsigned short port,int fam)536 static int EmbedSetPeerDTLS(WOLFSSL* ssl, char* ip, int ipSz,
537 unsigned short port, int fam)
538 {
539 int ret;
540 SOCKADDR_S addr;
541
542 /* sanity checks on arguments */
543 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
544 return BAD_FUNC_ARG;
545 }
546
547 addr.ss_family = fam;
548 switch (addr.ss_family) {
549 case WOLFSSL_IP4:
550 if (XINET_PTON(addr.ss_family, ip,
551 &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
552 WOLFSSL_MSG("XINET_PTON error");
553 return SOCKET_ERROR_E;
554 }
555 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
556
557 /* peer sa is free'd in SSL_ResourceFree */
558 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
559 sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
560 WOLFSSL_MSG("Import DTLS peer info error");
561 return ret;
562 }
563 break;
564
565 case WOLFSSL_IP6:
566 #ifdef WOLFSSL_IPV6
567 if (XINET_PTON(addr.ss_family, ip,
568 &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
569 WOLFSSL_MSG("XINET_PTON error");
570 return SOCKET_ERROR_E;
571 }
572 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
573
574 /* peer sa is free'd in SSL_ResourceFree */
575 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
576 sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
577 WOLFSSL_MSG("Import DTLS peer info error");
578 return ret;
579 }
580 #endif /* WOLFSSL_IPV6 */
581 break;
582
583 default:
584 WOLFSSL_MSG("Unknown address family");
585 return BUFFER_E;
586 }
587
588 return WOLFSSL_SUCCESS;
589 }
590 #endif
591
592 /* get the peer information in human readable form (ip, port, family)
593 * default function assumes BSD sockets
594 * can be overridden with wolfSSL_CTX_SetIOGetPeer
595 */
EmbedGetPeer(WOLFSSL * ssl,char * ip,int * ipSz,unsigned short * port,int * fam)596 int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
597 unsigned short* port, int* fam)
598 {
599 if (ssl == NULL || ip == NULL || ipSz == NULL ||
600 port == NULL || fam == NULL) {
601 return BAD_FUNC_ARG;
602 }
603
604 if (ssl->options.dtls) {
605 #ifdef WOLFSSL_DTLS
606 return EmbedGetPeerDTLS(ssl, ip, ipSz, port, fam);
607 #else
608 return NOT_COMPILED_IN;
609 #endif
610 }
611 else {
612 *port = wolfSSL_get_fd(ssl);
613 ip[0] = '\0';
614 *ipSz = 0;
615 *fam = 0;
616 return WOLFSSL_SUCCESS;
617 }
618 }
619
620 /* set the peer information in human readable form (ip, port, family)
621 * default function assumes BSD sockets
622 * can be overridden with wolfSSL_CTX_SetIOSetPeer
623 */
EmbedSetPeer(WOLFSSL * ssl,char * ip,int ipSz,unsigned short port,int fam)624 int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
625 unsigned short port, int fam)
626 {
627 /* sanity checks on arguments */
628 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > MAX_EXPORT_IP) {
629 return BAD_FUNC_ARG;
630 }
631
632 if (ssl->options.dtls) {
633 #ifdef WOLFSSL_DTLS
634 return EmbedSetPeerDTLS(ssl, ip, ipSz, port, fam);
635 #else
636 return NOT_COMPILED_IN;
637 #endif
638 }
639 else {
640 wolfSSL_set_fd(ssl, port);
641 (void)fam;
642 return WOLFSSL_SUCCESS;
643 }
644 }
645 #endif /* WOLFSSL_SESSION_EXPORT */
646
647 #ifdef WOLFSSL_LINUXKM
linuxkm_send(struct socket * socket,void * buf,int size,unsigned int flags)648 static int linuxkm_send(struct socket *socket, void *buf, int size,
649 unsigned int flags)
650 {
651 int ret;
652 struct kvec vec = { .iov_base = buf, .iov_len = size };
653 struct msghdr msg = { .msg_flags = flags };
654 ret = kernel_sendmsg(socket, &msg, &vec, 1, size);
655 return ret;
656 }
657
linuxkm_recv(struct socket * socket,void * buf,int size,unsigned int flags)658 static int linuxkm_recv(struct socket *socket, void *buf, int size,
659 unsigned int flags)
660 {
661 int ret;
662 struct kvec vec = { .iov_base = buf, .iov_len = size };
663 struct msghdr msg = { .msg_flags = flags };
664 ret = kernel_recvmsg(socket, &msg, &vec, 1, size, msg.msg_flags);
665 return ret;
666 }
667 #endif /* WOLFSSL_LINUXKM */
668
669
wolfIO_Recv(SOCKET_T sd,char * buf,int sz,int rdFlags)670 int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
671 {
672 int recvd;
673
674 recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
675 recvd = TranslateReturnCode(recvd, sd);
676
677 return recvd;
678 }
679
wolfIO_Send(SOCKET_T sd,char * buf,int sz,int wrFlags)680 int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
681 {
682 int sent;
683
684 sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
685 sent = TranslateReturnCode(sent, sd);
686
687 return sent;
688 }
689
690 #endif /* USE_WOLFSSL_IO */
691
692
693 #ifdef HAVE_HTTP_CLIENT
694
695 #ifndef HAVE_IO_TIMEOUT
696 #define io_timeout_sec 0
697 #else
698
699 #ifndef DEFAULT_TIMEOUT_SEC
700 #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
701 #endif
702
703 static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
704
wolfIO_SetTimeout(int to_sec)705 void wolfIO_SetTimeout(int to_sec)
706 {
707 io_timeout_sec = to_sec;
708 }
709
wolfIO_SetBlockingMode(SOCKET_T sockfd,int non_blocking)710 int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
711 {
712 int ret = 0;
713
714 #ifdef USE_WINDOWS_API
715 unsigned long blocking = non_blocking;
716 ret = ioctlsocket(sockfd, FIONBIO, &blocking);
717 if (ret == SOCKET_ERROR)
718 ret = -1;
719 #else
720 ret = fcntl(sockfd, F_GETFL, 0);
721 if (ret >= 0) {
722 if (non_blocking)
723 ret |= O_NONBLOCK;
724 else
725 ret &= ~O_NONBLOCK;
726 ret = fcntl(sockfd, F_SETFL, ret);
727 }
728 #endif
729 if (ret < 0) {
730 WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
731 }
732
733 return ret;
734 }
735
wolfIO_Select(SOCKET_T sockfd,int to_sec)736 int wolfIO_Select(SOCKET_T sockfd, int to_sec)
737 {
738 fd_set rfds, wfds;
739 int nfds = 0;
740 struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
741 int ret;
742
743 #ifndef USE_WINDOWS_API
744 nfds = (int)sockfd + 1;
745 #endif
746
747 if ((sockfd < 0) || (sockfd >= FD_SETSIZE)) {
748 WOLFSSL_MSG("socket fd out of FDSET range");
749 return -1;
750 }
751
752 FD_ZERO(&rfds);
753 FD_SET(sockfd, &rfds);
754 wfds = rfds;
755
756 ret = select(nfds, &rfds, &wfds, NULL, &timeout);
757 if (ret == 0) {
758 #ifdef DEBUG_HTTP
759 printf("Timeout: %d\n", ret);
760 #endif
761 return HTTP_TIMEOUT;
762 }
763 else if (ret > 0) {
764 if (FD_ISSET(sockfd, &wfds)) {
765 if (!FD_ISSET(sockfd, &rfds)) {
766 return 0;
767 }
768 }
769 }
770
771 WOLFSSL_MSG("Select error");
772 return SOCKET_ERROR_E;
773 }
774 #endif /* HAVE_IO_TIMEOUT */
775
wolfIO_Word16ToString(char * d,word16 number)776 static int wolfIO_Word16ToString(char* d, word16 number)
777 {
778 int i = 0;
779 word16 order = 10000;
780 word16 digit;
781
782 if (d == NULL)
783 return i;
784
785 if (number == 0)
786 d[i++] = '0';
787 else {
788 while (order) {
789 digit = number / order;
790 if (i > 0 || digit != 0)
791 d[i++] = (char)digit + '0';
792 if (digit != 0)
793 number %= digit * order;
794
795 order = (order > 1) ? order / 10 : 0;
796 }
797 }
798 d[i] = 0; /* null terminate */
799
800 return i;
801 }
802
wolfIO_TcpConnect(SOCKET_T * sockfd,const char * ip,word16 port,int to_sec)803 int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
804 {
805 #ifdef HAVE_SOCKADDR
806 int ret = 0;
807 SOCKADDR_S addr;
808 int sockaddr_len = sizeof(SOCKADDR_IN);
809 /* use gethostbyname for c99 */
810 #if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99)
811 ADDRINFO hints;
812 ADDRINFO* answer = NULL;
813 char strPort[6];
814 #else
815 #if !defined(WOLFSSL_USE_POPEN_HOST)
816 HOSTENT* entry;
817 #endif
818 SOCKADDR_IN *sin;
819 #endif
820
821 if (sockfd == NULL || ip == NULL) {
822 return -1;
823 }
824
825 XMEMSET(&addr, 0, sizeof(addr));
826
827 #ifdef WOLFIO_DEBUG
828 printf("TCP Connect: %s:%d\n", ip, port);
829 #endif
830
831 /* use gethostbyname for c99 */
832 #if defined(HAVE_GETADDRINFO) && !defined(WOLF_C99)
833 XMEMSET(&hints, 0, sizeof(hints));
834 hints.ai_family = AF_UNSPEC;
835 hints.ai_socktype = SOCK_STREAM;
836 hints.ai_protocol = IPPROTO_TCP;
837
838 if (wolfIO_Word16ToString(strPort, port) == 0) {
839 WOLFSSL_MSG("invalid port number for responder");
840 return -1;
841 }
842
843 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
844 WOLFSSL_MSG("no addr info for responder");
845 return -1;
846 }
847
848 sockaddr_len = answer->ai_addrlen;
849 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
850 freeaddrinfo(answer);
851 #elif defined(WOLFSSL_USE_POPEN_HOST)
852 {
853 char host_ipaddr[4] = { 127, 0, 0, 1 };
854 int found = 1;
855
856 if ((XSTRNCMP(ip, "localhost", 10) != 0) &&
857 (XSTRNCMP(ip, "127.0.0.1", 10) != 0)) {
858 FILE* fp;
859 char host_out[100];
860 char cmd[100];
861
862 XSTRNCPY(cmd, "host ", 6);
863 XSTRNCAT(cmd, ip, 99 - XSTRLEN(cmd));
864 found = 0;
865 fp = popen(cmd, "r");
866 if (fp != NULL) {
867 while (fgets(host_out, sizeof(host_out), fp) != NULL) {
868 int i;
869 int j = 0;
870 for (j = 0; host_out[j] != '\0'; j++) {
871 if ((host_out[j] >= '0') && (host_out[j] <= '9')) {
872 break;
873 }
874 }
875 found = (host_out[j] >= '0') && (host_out[j] <= '9');
876 if (!found) {
877 continue;
878 }
879
880 for (i = 0; i < 4; i++) {
881 host_ipaddr[i] = atoi(host_out + j);
882 while ((host_out[j] >= '0') && (host_out[j] <= '9')) {
883 j++;
884 }
885 if (host_out[j] == '.') {
886 j++;
887 found &= (i != 3);
888 }
889 else {
890 found &= (i == 3);
891 break;
892 }
893 }
894 if (found) {
895 break;
896 }
897 }
898 pclose(fp);
899 }
900 }
901 if (found) {
902 sin = (SOCKADDR_IN *)&addr;
903
904 sin->sin_family = AF_INET;
905 sin->sin_port = XHTONS(port);
906 XMEMCPY(&sin->sin_addr.s_addr, host_ipaddr, sizeof(host_ipaddr));
907 }
908 else {
909 WOLFSSL_MSG("no addr info for responder");
910 return -1;
911 }
912 }
913 #else
914 entry = gethostbyname(ip);
915 sin = (SOCKADDR_IN *)&addr;
916
917 if (entry) {
918 sin->sin_family = AF_INET;
919 sin->sin_port = XHTONS(port);
920 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
921 }
922 else {
923 WOLFSSL_MSG("no addr info for responder");
924 return -1;
925 }
926 #endif
927
928 *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
929 #ifdef USE_WINDOWS_API
930 if (*sockfd == SOCKET_INVALID)
931 #else
932 if (*sockfd <= SOCKET_INVALID)
933 #endif
934 {
935 WOLFSSL_MSG("bad socket fd, out of fds?");
936 return -1;
937 }
938
939 #ifdef HAVE_IO_TIMEOUT
940 /* if timeout value provided then set socket non-blocking */
941 if (to_sec > 0) {
942 wolfIO_SetBlockingMode(*sockfd, 1);
943 }
944 #else
945 (void)to_sec;
946 #endif
947
948 ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
949 #ifdef HAVE_IO_TIMEOUT
950 if (ret != 0) {
951 if ((errno == EINPROGRESS) && (to_sec > 0)) {
952 /* wait for connect to complete */
953 ret = wolfIO_Select(*sockfd, to_sec);
954
955 /* restore blocking mode */
956 wolfIO_SetBlockingMode(*sockfd, 0);
957 }
958 }
959 #endif
960 if (ret != 0) {
961 WOLFSSL_MSG("Responder tcp connect failed");
962 CloseSocket(*sockfd);
963 *sockfd = SOCKET_INVALID;
964 return -1;
965 }
966 return ret;
967 #else
968 (void)sockfd;
969 (void)ip;
970 (void)port;
971 (void)to_sec;
972 return -1;
973 #endif /* HAVE_SOCKADDR */
974 }
975
wolfIO_TcpBind(SOCKET_T * sockfd,word16 port)976 int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port)
977 {
978 #ifdef HAVE_SOCKADDR
979 int ret = 0;
980 SOCKADDR_S addr;
981 int sockaddr_len = sizeof(SOCKADDR_IN);
982 SOCKADDR_IN *sin = (SOCKADDR_IN *)&addr;
983
984 if (sockfd == NULL || port < 1) {
985 return -1;
986 }
987
988 XMEMSET(&addr, 0, sizeof(addr));
989
990 sin->sin_family = AF_INET;
991 sin->sin_addr.s_addr = INADDR_ANY;
992 sin->sin_port = XHTONS(port);
993 *sockfd = (SOCKET_T)socket(AF_INET, SOCK_STREAM, 0);
994
995 if (*sockfd < 0) {
996 WOLFSSL_MSG("socket failed");
997 *sockfd = SOCKET_INVALID;
998 return -1;
999 }
1000
1001 #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
1002 && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR)
1003 {
1004 int optval = 1;
1005 XSOCKLENT optlen = sizeof(optval);
1006 ret = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
1007 }
1008 #endif
1009
1010 if (ret == 0)
1011 ret = bind(*sockfd, (SOCKADDR *)sin, sockaddr_len);
1012 if (ret == 0)
1013 ret = listen(*sockfd, SOMAXCONN);
1014
1015 if (ret != 0) {
1016 WOLFSSL_MSG("wolfIO_TcpBind failed");
1017 CloseSocket(*sockfd);
1018 *sockfd = SOCKET_INVALID;
1019 ret = -1;
1020 }
1021
1022 return ret;
1023 #else
1024 (void)sockfd;
1025 (void)port;
1026 return -1;
1027 #endif /* HAVE_SOCKADDR */
1028 }
1029
1030 #ifdef HAVE_SOCKADDR
wolfIO_TcpAccept(SOCKET_T sockfd,SOCKADDR * peer_addr,XSOCKLENT * peer_len)1031 int wolfIO_TcpAccept(SOCKET_T sockfd, SOCKADDR* peer_addr, XSOCKLENT* peer_len)
1032 {
1033 return (int)accept(sockfd, peer_addr, peer_len);
1034 }
1035 #endif /* HAVE_SOCKADDR */
1036
1037 #ifndef HTTP_SCRATCH_BUFFER_SIZE
1038 #define HTTP_SCRATCH_BUFFER_SIZE 512
1039 #endif
1040 #ifndef MAX_URL_ITEM_SIZE
1041 #define MAX_URL_ITEM_SIZE 80
1042 #endif
1043
wolfIO_DecodeUrl(const char * url,int urlSz,char * outName,char * outPath,word16 * outPort)1044 int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
1045 word16* outPort)
1046 {
1047 int result = -1;
1048
1049 if (url == NULL || urlSz == 0) {
1050 if (outName)
1051 *outName = 0;
1052 if (outPath)
1053 *outPath = 0;
1054 if (outPort)
1055 *outPort = 0;
1056 }
1057 else {
1058 int i, cur;
1059
1060 /* need to break the url down into scheme, address, and port */
1061 /* "http://example.com:8080/" */
1062 /* "http://[::1]:443/" */
1063 if (XSTRNCMP(url, "http://", 7) == 0) {
1064 cur = 7;
1065 } else cur = 0;
1066
1067 i = 0;
1068 if (url[cur] == '[') {
1069 cur++;
1070 /* copy until ']' */
1071 while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1072 url[cur] != ']') {
1073 if (outName)
1074 outName[i] = url[cur];
1075 i++; cur++;
1076 }
1077 cur++; /* skip ']' */
1078 }
1079 else {
1080 while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0 &&
1081 url[cur] != ':' && url[cur] != '/') {
1082 if (outName)
1083 outName[i] = url[cur];
1084 i++; cur++;
1085 }
1086 }
1087 if (outName)
1088 outName[i] = 0;
1089 /* Need to pick out the path after the domain name */
1090
1091 if (cur < urlSz && url[cur] == ':') {
1092 char port[6];
1093 int j;
1094 word32 bigPort = 0;
1095 i = 0;
1096 cur++;
1097 while (i < 6 && cur < urlSz && url[cur] != 0 && url[cur] != '/') {
1098 port[i] = url[cur];
1099 i++; cur++;
1100 }
1101
1102 for (j = 0; j < i; j++) {
1103 if (port[j] < '0' || port[j] > '9') return -1;
1104 bigPort = (bigPort * 10) + (port[j] - '0');
1105 }
1106 if (outPort)
1107 *outPort = (word16)bigPort;
1108 }
1109 else if (outPort)
1110 *outPort = 80;
1111
1112
1113 if (cur < urlSz && url[cur] == '/') {
1114 i = 0;
1115 while (i < MAX_URL_ITEM_SIZE-1 && cur < urlSz && url[cur] != 0) {
1116 if (outPath)
1117 outPath[i] = url[cur];
1118 i++; cur++;
1119 }
1120 if (outPath)
1121 outPath[i] = 0;
1122 }
1123 else if (outPath) {
1124 outPath[0] = '/';
1125 outPath[1] = 0;
1126 }
1127
1128 result = 0;
1129 }
1130
1131 return result;
1132 }
1133
wolfIO_HttpProcessResponseBuf(int sfd,byte ** recvBuf,int * recvBufSz,int chunkSz,char * start,int len,int dynType,void * heap)1134 static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf,
1135 int* recvBufSz, int chunkSz, char* start, int len, int dynType, void* heap)
1136 {
1137 byte* newRecvBuf = NULL;
1138 int newRecvSz = *recvBufSz + chunkSz;
1139 int pos = 0;
1140
1141 WOLFSSL_MSG("Processing HTTP response");
1142 #ifdef WOLFIO_DEBUG
1143 printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
1144 #endif
1145
1146 (void)heap;
1147 (void)dynType;
1148
1149 if (chunkSz < 0 || len < 0) {
1150 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf invalid chunk or length size");
1151 return MEMORY_E;
1152 }
1153
1154 if (newRecvSz <= 0) {
1155 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf new receive size overflow");
1156 return MEMORY_E;
1157 }
1158
1159 newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
1160 if (newRecvBuf == NULL) {
1161 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
1162 return MEMORY_E;
1163 }
1164
1165 /* if buffer already exists, then we are growing it */
1166 if (*recvBuf) {
1167 XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
1168 XFREE(*recvBuf, heap, dynType);
1169 pos += *recvBufSz;
1170 *recvBuf = NULL;
1171 }
1172
1173 /* copy the remainder of the httpBuf into the respBuf */
1174 if (len != 0) {
1175 if (pos + len <= newRecvSz) {
1176 XMEMCPY(&newRecvBuf[pos], start, len);
1177 pos += len;
1178 }
1179 else {
1180 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf bad size");
1181 XFREE(newRecvBuf, heap, dynType);
1182 return -1;
1183 }
1184 }
1185
1186 /* receive the remainder of chunk */
1187 while (len < chunkSz) {
1188 int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
1189 if (rxSz > 0) {
1190 len += rxSz;
1191 pos += rxSz;
1192 }
1193 else {
1194 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
1195 XFREE(newRecvBuf, heap, dynType);
1196 return -1;
1197 }
1198 }
1199
1200 *recvBuf = newRecvBuf;
1201 *recvBufSz = newRecvSz;
1202
1203 return 0;
1204 }
1205
wolfIO_HttpProcessResponse(int sfd,const char ** appStrList,byte ** respBuf,byte * httpBuf,int httpBufSz,int dynType,void * heap)1206 int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
1207 byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
1208 {
1209 static const char HTTP_PROTO[] = "HTTP/1.";
1210 static const char HTTP_STATUS_200[] = "200";
1211 int result = 0;
1212 int len = 0;
1213 char *start, *end;
1214 int respBufSz = 0;
1215 int isChunked = 0, chunkSz = 0;
1216 enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
1217 phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
1218 phr_http_end
1219 } state = phr_init;
1220
1221 WOLFSSL_ENTER("wolfIO_HttpProcessResponse");
1222
1223 *respBuf = NULL;
1224 start = end = NULL;
1225 do {
1226 if (state == phr_get_chunk_data) {
1227 /* get chunk of data */
1228 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
1229 chunkSz, start, len, dynType, heap);
1230
1231 state = (result != 0) ? phr_http_end : phr_get_chunk_len;
1232 end = NULL;
1233 len = 0;
1234 }
1235
1236 /* read data if no \r\n or first time */
1237 if (end == NULL) {
1238 result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
1239 if (result > 0) {
1240 len += result;
1241 start = (char*)httpBuf;
1242 start[len] = 0;
1243 }
1244 else {
1245 result = TranslateReturnCode(result, sfd);
1246 result = wolfSSL_LastError(result);
1247 if (result == SOCKET_EWOULDBLOCK || result == SOCKET_EAGAIN) {
1248 return OCSP_WANT_READ;
1249 }
1250
1251 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
1252 return HTTP_RECV_ERR;
1253 }
1254 }
1255 end = XSTRSTR(start, "\r\n"); /* locate end */
1256
1257 /* handle incomplete rx */
1258 if (end == NULL) {
1259 if (len != 0)
1260 XMEMMOVE(httpBuf, start, len);
1261 start = end = NULL;
1262 }
1263 /* when start is "\r\n" */
1264 else if (end == start) {
1265 /* if waiting for end or need chunk len */
1266 if (state == phr_wait_end || state == phr_get_chunk_len) {
1267 state = (isChunked) ? phr_get_chunk_len : phr_http_end;
1268 len -= 2; start += 2; /* skip \r\n */
1269 }
1270 else {
1271 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
1272 return HTTP_HEADER_ERR;
1273 }
1274 }
1275 else {
1276 *end = 0; /* null terminate */
1277 len -= (int)(end - start) + 2;
1278 /* adjust len to remove the first line including the /r/n */
1279
1280 #ifdef WOLFIO_DEBUG
1281 printf("HTTP Resp: %s\n", start);
1282 #endif
1283
1284 switch (state) {
1285 case phr_init:
1286 /* length of "HTTP/1.x 200" == 12*/
1287 if (XSTRLEN(start) < 12) {
1288 WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1289 "too short.");
1290 return HTTP_HEADER_ERR;
1291 }
1292 if (XSTRNCASECMP(start, HTTP_PROTO,
1293 sizeof(HTTP_PROTO) - 1) != 0) {
1294 WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1295 "doesn't start with HTTP/1.");
1296 return HTTP_PROTO_ERR;
1297 }
1298 /* +2 for HTTP minor version and space between version and
1299 * status code. */
1300 start += sizeof(HTTP_PROTO) - 1 + 2 ;
1301 if (XSTRNCASECMP(start, HTTP_STATUS_200,
1302 sizeof(HTTP_STATUS_200) - 1) != 0) {
1303 WOLFSSL_MSG("wolfIO_HttpProcessResponse HTTP header "
1304 "doesn't have status code 200.");
1305 return HTTP_STATUS_ERR;
1306 }
1307 state = phr_http_start;
1308 break;
1309 case phr_http_start:
1310 case phr_have_length:
1311 case phr_have_type:
1312 if (XSTRLEN(start) < 13) { /* 13 is the shortest of the following
1313 next lines we're checking for. */
1314 WOLFSSL_MSG("wolfIO_HttpProcessResponse content type is too short.");
1315 return HTTP_VERSION_ERR;
1316 }
1317
1318 if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
1319 int i;
1320
1321 start += 13;
1322 while (*start == ' ') start++;
1323
1324 /* try and match against appStrList */
1325 i = 0;
1326 while (appStrList[i] != NULL) {
1327 if (XSTRNCASECMP(start, appStrList[i],
1328 XSTRLEN(appStrList[i])) == 0) {
1329 break;
1330 }
1331 i++;
1332 }
1333 if (appStrList[i] == NULL) {
1334 WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
1335 return HTTP_APPSTR_ERR;
1336 }
1337 state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
1338 }
1339 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
1340 start += 15;
1341 while (*start == ' ') start++;
1342 chunkSz = XATOI(start);
1343 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1344 }
1345 else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
1346 start += 18;
1347 while (*start == ' ') start++;
1348 if (XSTRNCASECMP(start, "chunked", 7) == 0) {
1349 isChunked = 1;
1350 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1351 }
1352 }
1353 break;
1354 case phr_get_chunk_len:
1355 chunkSz = (int)strtol(start, NULL, 16); /* hex format */
1356 state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
1357 break;
1358 case phr_get_chunk_data:
1359 /* processing for chunk data done above, since \r\n isn't required */
1360 case phr_wait_end:
1361 case phr_http_end:
1362 /* do nothing */
1363 break;
1364 } /* switch (state) */
1365
1366 /* skip to end plus \r\n */
1367 start = end + 2;
1368 }
1369 } while (state != phr_http_end);
1370
1371 if (!isChunked) {
1372 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
1373 start, len, dynType, heap);
1374 }
1375
1376 if (result >= 0) {
1377 result = respBufSz;
1378 }
1379 else {
1380 WOLFSSL_ERROR(result);
1381 }
1382
1383 return result;
1384 }
wolfIO_HttpBuildRequest(const char * reqType,const char * domainName,const char * path,int pathLen,int reqSz,const char * contentType,byte * buf,int bufSize)1385 int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName,
1386 const char *path, int pathLen, int reqSz, const char *contentType,
1387 byte *buf, int bufSize)
1388 {
1389 return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize);
1390 }
1391
wolfIO_HttpBuildRequest_ex(const char * reqType,const char * domainName,const char * path,int pathLen,int reqSz,const char * contentType,const char * exHdrs,byte * buf,int bufSize)1392 int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName,
1393 const char *path, int pathLen, int reqSz, const char *contentType,
1394 const char *exHdrs, byte *buf, int bufSize)
1395 {
1396 word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen;
1397 char reqSzStr[6];
1398 char* req = (char*)buf;
1399 const char* blankStr = " ";
1400 const char* http11Str = " HTTP/1.1";
1401 const char* hostStr = "\r\nHost: ";
1402 const char* contentLenStr = "\r\nContent-Length: ";
1403 const char* contentTypeStr = "\r\nContent-Type: ";
1404 const char* singleCrLfStr = "\r\n";
1405 const char* doubleCrLfStr = "\r\n\r\n";
1406 word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
1407 contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen;
1408
1409 reqTypeLen = (word32)XSTRLEN(reqType);
1410 domainNameLen = (word32)XSTRLEN(domainName);
1411 reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
1412 contentTypeLen = (word32)XSTRLEN(contentType);
1413
1414 blankStrLen = (word32)XSTRLEN(blankStr);
1415 http11StrLen = (word32)XSTRLEN(http11Str);
1416 hostStrLen = (word32)XSTRLEN(hostStr);
1417 contentLenStrLen = (word32)XSTRLEN(contentLenStr);
1418 contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
1419
1420 if(exHdrs){
1421 singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr);
1422 exHdrsLen = (word32)XSTRLEN(exHdrs);
1423 } else {
1424 singleCrLfStrLen = 0;
1425 exHdrsLen = 0;
1426 }
1427
1428 doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
1429
1430 /* determine max length and check it */
1431 maxLen =
1432 reqTypeLen +
1433 blankStrLen +
1434 pathLen +
1435 http11StrLen +
1436 hostStrLen +
1437 domainNameLen +
1438 contentLenStrLen +
1439 reqSzStrLen +
1440 contentTypeStrLen +
1441 contentTypeLen +
1442 singleCrLfStrLen +
1443 exHdrsLen +
1444 doubleCrLfStrLen +
1445 1 /* null term */;
1446 if (maxLen > (word32)bufSize)
1447 return 0;
1448
1449 XSTRNCPY((char*)buf, reqType, bufSize);
1450 buf += reqTypeLen; bufSize -= reqTypeLen;
1451 XSTRNCPY((char*)buf, blankStr, bufSize);
1452 buf += blankStrLen; bufSize -= blankStrLen;
1453 XSTRNCPY((char*)buf, path, bufSize);
1454 buf += pathLen; bufSize -= pathLen;
1455 XSTRNCPY((char*)buf, http11Str, bufSize);
1456 buf += http11StrLen; bufSize -= http11StrLen;
1457 if (domainNameLen > 0) {
1458 XSTRNCPY((char*)buf, hostStr, bufSize);
1459 buf += hostStrLen; bufSize -= hostStrLen;
1460 XSTRNCPY((char*)buf, domainName, bufSize);
1461 buf += domainNameLen; bufSize -= domainNameLen;
1462 }
1463 if (reqSz > 0 && reqSzStrLen > 0) {
1464 XSTRNCPY((char*)buf, contentLenStr, bufSize);
1465 buf += contentLenStrLen; bufSize -= contentLenStrLen;
1466 XSTRNCPY((char*)buf, reqSzStr, bufSize);
1467 buf += reqSzStrLen; bufSize -= reqSzStrLen;
1468 }
1469 if (contentTypeLen > 0) {
1470 XSTRNCPY((char*)buf, contentTypeStr, bufSize);
1471 buf += contentTypeStrLen; bufSize -= contentTypeStrLen;
1472 XSTRNCPY((char*)buf, contentType, bufSize);
1473 buf += contentTypeLen; bufSize -= contentTypeLen;
1474 }
1475 if (exHdrsLen > 0)
1476 {
1477 XSTRNCPY((char *)buf, singleCrLfStr, bufSize);
1478 buf += singleCrLfStrLen;
1479 bufSize -= singleCrLfStrLen;
1480 XSTRNCPY((char *)buf, exHdrs, bufSize);
1481 buf += exHdrsLen;
1482 bufSize -= exHdrsLen;
1483 }
1484 XSTRNCPY((char*)buf, doubleCrLfStr, bufSize);
1485 buf += doubleCrLfStrLen;
1486
1487 #ifdef WOLFIO_DEBUG
1488 printf("HTTP %s: %s", reqType, req);
1489 #endif
1490
1491 /* calculate actual length based on original and new pointer */
1492 return (int)((char*)buf - req);
1493 }
1494
1495
1496 #ifdef HAVE_OCSP
1497
wolfIO_HttpBuildRequestOcsp(const char * domainName,const char * path,int ocspReqSz,byte * buf,int bufSize)1498 int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
1499 int ocspReqSz, byte* buf, int bufSize)
1500 {
1501 const char *cacheCtl = "Cache-Control: no-cache";
1502 return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path),
1503 ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize);
1504 }
1505
1506 /* return: >0 OCSP Response Size
1507 * -1 error */
wolfIO_HttpProcessResponseOcsp(int sfd,byte ** respBuf,byte * httpBuf,int httpBufSz,void * heap)1508 int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
1509 byte* httpBuf, int httpBufSz, void* heap)
1510 {
1511 const char* appStrList[] = {
1512 "application/ocsp-response",
1513 NULL
1514 };
1515
1516 return wolfIO_HttpProcessResponse(sfd, appStrList,
1517 respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
1518 }
1519
1520 /* in default wolfSSL callback ctx is the heap pointer */
EmbedOcspLookup(void * ctx,const char * url,int urlSz,byte * ocspReqBuf,int ocspReqSz,byte ** ocspRespBuf)1521 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
1522 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
1523 {
1524 SOCKET_T sfd = SOCKET_INVALID;
1525 word16 port;
1526 int ret = -1;
1527 #ifdef WOLFSSL_SMALL_STACK
1528 char* path;
1529 char* domainName;
1530 #else
1531 char path[MAX_URL_ITEM_SIZE];
1532 char domainName[MAX_URL_ITEM_SIZE];
1533 #endif
1534
1535 #ifdef WOLFSSL_SMALL_STACK
1536 path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1537 if (path == NULL)
1538 return MEMORY_E;
1539
1540 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL,
1541 DYNAMIC_TYPE_TMP_BUFFER);
1542 if (domainName == NULL) {
1543 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1544 return MEMORY_E;
1545 }
1546 #endif
1547
1548 if (ocspReqBuf == NULL || ocspReqSz == 0) {
1549 WOLFSSL_MSG("OCSP request is required for lookup");
1550 }
1551 else if (ocspRespBuf == NULL) {
1552 WOLFSSL_MSG("Cannot save OCSP response");
1553 }
1554 else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
1555 WOLFSSL_MSG("Unable to decode OCSP URL");
1556 }
1557 else {
1558 /* Note, the library uses the EmbedOcspRespFree() callback to
1559 * free this buffer. */
1560 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1561 byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
1562
1563 if (httpBuf == NULL) {
1564 WOLFSSL_MSG("Unable to create OCSP response buffer");
1565 }
1566 else {
1567 httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
1568 httpBuf, httpBufSz);
1569
1570 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1571 if (ret != 0) {
1572 WOLFSSL_MSG("OCSP Responder connection failed");
1573 }
1574 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
1575 httpBufSz) {
1576 WOLFSSL_MSG("OCSP http request failed");
1577 }
1578 else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
1579 ocspReqSz) {
1580 WOLFSSL_MSG("OCSP ocsp request failed");
1581 }
1582 else {
1583 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
1584 HTTP_SCRATCH_BUFFER_SIZE, ctx);
1585 }
1586 if (sfd != SOCKET_INVALID)
1587 CloseSocket(sfd);
1588 XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
1589 }
1590 }
1591
1592 #ifdef WOLFSSL_SMALL_STACK
1593 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1594 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1595 #endif
1596
1597 return ret;
1598 }
1599
1600 /* in default callback ctx is heap hint */
EmbedOcspRespFree(void * ctx,byte * resp)1601 void EmbedOcspRespFree(void* ctx, byte *resp)
1602 {
1603 if (resp)
1604 XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
1605
1606 (void)ctx;
1607 }
1608 #endif /* HAVE_OCSP */
1609
1610
1611 #if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
1612
wolfIO_HttpBuildRequestCrl(const char * url,int urlSz,const char * domainName,byte * buf,int bufSize)1613 int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
1614 const char* domainName, byte* buf, int bufSize)
1615 {
1616 const char *cacheCtl = "Cache-Control: no-cache";
1617 return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "",
1618 cacheCtl, buf, bufSize);
1619 }
1620
wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL * crl,int sfd,byte * httpBuf,int httpBufSz)1621 int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
1622 int httpBufSz)
1623 {
1624 int ret;
1625 byte *respBuf = NULL;
1626
1627 const char* appStrList[] = {
1628 "application/pkix-crl",
1629 "application/x-pkcs7-crl",
1630 NULL
1631 };
1632
1633
1634 ret = wolfIO_HttpProcessResponse(sfd, appStrList,
1635 &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
1636 if (ret >= 0) {
1637 ret = BufferLoadCRL(crl, respBuf, ret, WOLFSSL_FILETYPE_ASN1, 0);
1638 }
1639 XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
1640
1641 return ret;
1642 }
1643
EmbedCrlLookup(WOLFSSL_CRL * crl,const char * url,int urlSz)1644 int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
1645 {
1646 SOCKET_T sfd = SOCKET_INVALID;
1647 word16 port;
1648 int ret = -1;
1649 #ifdef WOLFSSL_SMALL_STACK
1650 char* domainName;
1651 #else
1652 char domainName[MAX_URL_ITEM_SIZE];
1653 #endif
1654
1655 #ifdef WOLFSSL_SMALL_STACK
1656 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
1657 DYNAMIC_TYPE_TMP_BUFFER);
1658 if (domainName == NULL) {
1659 return MEMORY_E;
1660 }
1661 #endif
1662
1663 if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
1664 WOLFSSL_MSG("Unable to decode CRL URL");
1665 }
1666 else {
1667 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1668 byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap,
1669 DYNAMIC_TYPE_CRL);
1670 if (httpBuf == NULL) {
1671 WOLFSSL_MSG("Unable to create CRL response buffer");
1672 }
1673 else {
1674 httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
1675 httpBuf, httpBufSz);
1676
1677 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1678 if (ret != 0) {
1679 WOLFSSL_MSG("CRL connection failed");
1680 }
1681 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
1682 != httpBufSz) {
1683 WOLFSSL_MSG("CRL http get failed");
1684 }
1685 else {
1686 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
1687 HTTP_SCRATCH_BUFFER_SIZE);
1688 }
1689 if (sfd != SOCKET_INVALID)
1690 CloseSocket(sfd);
1691 XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
1692 }
1693 }
1694
1695 #ifdef WOLFSSL_SMALL_STACK
1696 XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1697 #endif
1698
1699 return ret;
1700 }
1701 #endif /* HAVE_CRL && HAVE_CRL_IO */
1702
1703 #endif /* HAVE_HTTP_CLIENT */
1704
1705
1706
wolfSSL_CTX_SetIORecv(WOLFSSL_CTX * ctx,CallbackIORecv CBIORecv)1707 void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
1708 {
1709 if (ctx) {
1710 ctx->CBIORecv = CBIORecv;
1711 #ifdef OPENSSL_EXTRA
1712 ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
1713 #endif
1714 }
1715 }
1716
1717
wolfSSL_CTX_SetIOSend(WOLFSSL_CTX * ctx,CallbackIOSend CBIOSend)1718 void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
1719 {
1720 if (ctx) {
1721 ctx->CBIOSend = CBIOSend;
1722 #ifdef OPENSSL_EXTRA
1723 ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
1724 #endif
1725 }
1726 }
1727
1728
1729 /* sets the IO callback to use for receives at WOLFSSL level */
wolfSSL_SSLSetIORecv(WOLFSSL * ssl,CallbackIORecv CBIORecv)1730 void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv)
1731 {
1732 if (ssl) {
1733 ssl->CBIORecv = CBIORecv;
1734 #ifdef OPENSSL_EXTRA
1735 ssl->cbioFlag |= WOLFSSL_CBIO_RECV;
1736 #endif
1737 }
1738 }
1739
1740
1741 /* sets the IO callback to use for sends at WOLFSSL level */
wolfSSL_SSLSetIOSend(WOLFSSL * ssl,CallbackIOSend CBIOSend)1742 void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
1743 {
1744 if (ssl) {
1745 ssl->CBIOSend = CBIOSend;
1746 #ifdef OPENSSL_EXTRA
1747 ssl->cbioFlag |= WOLFSSL_CBIO_SEND;
1748 #endif
1749 }
1750 }
1751
1752
wolfSSL_SetIOReadCtx(WOLFSSL * ssl,void * rctx)1753 void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
1754 {
1755 if (ssl)
1756 ssl->IOCB_ReadCtx = rctx;
1757 }
1758
1759
wolfSSL_SetIOWriteCtx(WOLFSSL * ssl,void * wctx)1760 void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
1761 {
1762 if (ssl)
1763 ssl->IOCB_WriteCtx = wctx;
1764 }
1765
1766
wolfSSL_GetIOReadCtx(WOLFSSL * ssl)1767 void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
1768 {
1769 if (ssl)
1770 return ssl->IOCB_ReadCtx;
1771
1772 return NULL;
1773 }
1774
1775
wolfSSL_GetIOWriteCtx(WOLFSSL * ssl)1776 void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
1777 {
1778 if (ssl)
1779 return ssl->IOCB_WriteCtx;
1780
1781 return NULL;
1782 }
1783
1784
wolfSSL_SetIOReadFlags(WOLFSSL * ssl,int flags)1785 void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
1786 {
1787 if (ssl)
1788 ssl->rflags = flags;
1789 }
1790
1791
wolfSSL_SetIOWriteFlags(WOLFSSL * ssl,int flags)1792 void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1793 {
1794 if (ssl)
1795 ssl->wflags = flags;
1796 }
1797
1798
1799 #ifdef WOLFSSL_DTLS
1800
wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX * ctx,CallbackGenCookie cb)1801 void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1802 {
1803 if (ctx)
1804 ctx->CBIOCookie = cb;
1805 }
1806
1807
wolfSSL_SetCookieCtx(WOLFSSL * ssl,void * ctx)1808 void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1809 {
1810 if (ssl)
1811 ssl->IOCB_CookieCtx = ctx;
1812 }
1813
1814
wolfSSL_GetCookieCtx(WOLFSSL * ssl)1815 void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1816 {
1817 if (ssl)
1818 return ssl->IOCB_CookieCtx;
1819
1820 return NULL;
1821 }
1822 #endif /* WOLFSSL_DTLS */
1823
1824 #ifdef WOLFSSL_SESSION_EXPORT
1825
wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX * ctx,CallbackGetPeer cb)1826 void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
1827 {
1828 if (ctx)
1829 ctx->CBGetPeer = cb;
1830 }
1831
1832
wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX * ctx,CallbackSetPeer cb)1833 void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
1834 {
1835 if (ctx)
1836 ctx->CBSetPeer = cb;
1837 }
1838
1839 #endif /* WOLFSSL_SESSION_EXPORT */
1840
1841
1842 #ifdef HAVE_NETX
1843
1844 /* The NetX receive callback
1845 * return : bytes read, or error
1846 */
NetX_Receive(WOLFSSL * ssl,char * buf,int sz,void * ctx)1847 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1848 {
1849 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1850 ULONG left;
1851 ULONG total;
1852 ULONG copied = 0;
1853 UINT status;
1854
1855 (void)ssl;
1856
1857 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1858 WOLFSSL_MSG("NetX Recv NULL parameters");
1859 return WOLFSSL_CBIO_ERR_GENERAL;
1860 }
1861
1862 if (nxCtx->nxPacket == NULL) {
1863 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1864 nxCtx->nxWait);
1865 if (status != NX_SUCCESS) {
1866 WOLFSSL_MSG("NetX Recv receive error");
1867 return WOLFSSL_CBIO_ERR_GENERAL;
1868 }
1869 }
1870
1871 if (nxCtx->nxPacket) {
1872 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1873 if (status != NX_SUCCESS) {
1874 WOLFSSL_MSG("NetX Recv length get error");
1875 return WOLFSSL_CBIO_ERR_GENERAL;
1876 }
1877
1878 left = total - nxCtx->nxOffset;
1879 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1880 buf, sz, &copied);
1881 if (status != NX_SUCCESS) {
1882 WOLFSSL_MSG("NetX Recv data extract offset error");
1883 return WOLFSSL_CBIO_ERR_GENERAL;
1884 }
1885
1886 nxCtx->nxOffset += copied;
1887
1888 if (copied == left) {
1889 WOLFSSL_MSG("NetX Recv Drained packet");
1890 nx_packet_release(nxCtx->nxPacket);
1891 nxCtx->nxPacket = NULL;
1892 nxCtx->nxOffset = 0;
1893 }
1894 }
1895
1896 return copied;
1897 }
1898
1899
1900 /* The NetX send callback
1901 * return : bytes sent, or error
1902 */
NetX_Send(WOLFSSL * ssl,char * buf,int sz,void * ctx)1903 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1904 {
1905 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1906 NX_PACKET* packet;
1907 NX_PACKET_POOL* pool; /* shorthand */
1908 UINT status;
1909
1910 (void)ssl;
1911
1912 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1913 WOLFSSL_MSG("NetX Send NULL parameters");
1914 return WOLFSSL_CBIO_ERR_GENERAL;
1915 }
1916
1917 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1918 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1919 nxCtx->nxWait);
1920 if (status != NX_SUCCESS) {
1921 WOLFSSL_MSG("NetX Send packet alloc error");
1922 return WOLFSSL_CBIO_ERR_GENERAL;
1923 }
1924
1925 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1926 if (status != NX_SUCCESS) {
1927 nx_packet_release(packet);
1928 WOLFSSL_MSG("NetX Send data append error");
1929 return WOLFSSL_CBIO_ERR_GENERAL;
1930 }
1931
1932 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1933 if (status != NX_SUCCESS) {
1934 nx_packet_release(packet);
1935 WOLFSSL_MSG("NetX Send socket send error");
1936 return WOLFSSL_CBIO_ERR_GENERAL;
1937 }
1938
1939 return sz;
1940 }
1941
1942
1943 /* like set_fd, but for default NetX context */
wolfSSL_SetIO_NetX(WOLFSSL * ssl,NX_TCP_SOCKET * nxSocket,ULONG waitOption)1944 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1945 {
1946 if (ssl) {
1947 ssl->nxCtx.nxSocket = nxSocket;
1948 ssl->nxCtx.nxWait = waitOption;
1949 }
1950 }
1951
1952 #endif /* HAVE_NETX */
1953
1954
1955 #ifdef MICRIUM
1956
1957 /* Micrium uTCP/IP port, using the NetSock API
1958 * TCP and UDP are currently supported with the callbacks below.
1959 *
1960 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
1961 * and EmbedSetPeer() callbacks implemented.
1962 *
1963 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
1964 * callback implemented.
1965 *
1966 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
1967 * callback implemented.
1968 */
1969
1970 /* The Micrium uTCP/IP send callback
1971 * return : bytes sent, or error
1972 */
MicriumSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)1973 int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
1974 {
1975 NET_SOCK_ID sd = *(int*)ctx;
1976 NET_SOCK_RTN_CODE ret;
1977 NET_ERR err;
1978
1979 ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
1980 if (ret < 0) {
1981 WOLFSSL_MSG("Embed Send error");
1982
1983 if (err == NET_ERR_TX) {
1984 WOLFSSL_MSG("\tWould block");
1985 return WOLFSSL_CBIO_ERR_WANT_WRITE;
1986
1987 } else {
1988 WOLFSSL_MSG("\tGeneral error");
1989 return WOLFSSL_CBIO_ERR_GENERAL;
1990 }
1991 }
1992
1993 return ret;
1994 }
1995
1996 /* The Micrium uTCP/IP receive callback
1997 * return : nb bytes read, or error
1998 */
MicriumReceive(WOLFSSL * ssl,char * buf,int sz,void * ctx)1999 int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2000 {
2001 NET_SOCK_ID sd = *(int*)ctx;
2002 NET_SOCK_RTN_CODE ret;
2003 NET_ERR err;
2004
2005 #ifdef WOLFSSL_DTLS
2006 {
2007 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
2008 if (wolfSSL_dtls(ssl)
2009 && !wolfSSL_dtls_get_using_nonblock(ssl)
2010 && dtls_timeout != 0) {
2011 /* needs timeout in milliseconds */
2012 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
2013 if (err != NET_SOCK_ERR_NONE) {
2014 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
2015 }
2016 }
2017 }
2018 #endif
2019
2020 ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
2021 if (ret < 0) {
2022 WOLFSSL_MSG("Embed Receive error");
2023
2024 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
2025 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
2026 if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
2027 WOLFSSL_MSG("\tWould block");
2028 return WOLFSSL_CBIO_ERR_WANT_READ;
2029 }
2030 else {
2031 WOLFSSL_MSG("\tSocket timeout");
2032 return WOLFSSL_CBIO_ERR_TIMEOUT;
2033 }
2034
2035 } else if (err == NET_SOCK_ERR_CLOSED) {
2036 WOLFSSL_MSG("Embed receive connection closed");
2037 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
2038
2039 } else {
2040 WOLFSSL_MSG("\tGeneral error");
2041 return WOLFSSL_CBIO_ERR_GENERAL;
2042 }
2043 }
2044
2045 return ret;
2046 }
2047
2048 /* The Micrium uTCP/IP receivefrom callback
2049 * return : nb bytes read, or error
2050 */
MicriumReceiveFrom(WOLFSSL * ssl,char * buf,int sz,void * ctx)2051 int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2052 {
2053 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
2054 NET_SOCK_ID sd = dtlsCtx->rfd;
2055 NET_SOCK_ADDR peer;
2056 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
2057 NET_SOCK_RTN_CODE ret;
2058 NET_ERR err;
2059 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
2060
2061 WOLFSSL_ENTER("MicriumReceiveFrom()");
2062
2063 if (ssl->options.handShakeDone)
2064 dtls_timeout = 0;
2065
2066 if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
2067 /* needs timeout in milliseconds */
2068 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
2069 if (err != NET_SOCK_ERR_NONE) {
2070 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
2071 }
2072 }
2073
2074 ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
2075 0, 0, 0, &err);
2076 if (ret < 0) {
2077 WOLFSSL_MSG("Embed Receive From error");
2078
2079 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
2080 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
2081 if (wolfSSL_dtls_get_using_nonblock(ssl)) {
2082 WOLFSSL_MSG("\tWould block");
2083 return WOLFSSL_CBIO_ERR_WANT_READ;
2084 }
2085 else {
2086 WOLFSSL_MSG("\tSocket timeout");
2087 return WOLFSSL_CBIO_ERR_TIMEOUT;
2088 }
2089 } else {
2090 WOLFSSL_MSG("\tGeneral error");
2091 return WOLFSSL_CBIO_ERR_GENERAL;
2092 }
2093 }
2094 else {
2095 if (dtlsCtx->peer.sz > 0
2096 && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
2097 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
2098 WOLFSSL_MSG("\tIgnored packet from invalid peer");
2099 return WOLFSSL_CBIO_ERR_WANT_READ;
2100 }
2101 }
2102
2103 return ret;
2104 }
2105
2106 /* The Micrium uTCP/IP sendto callback
2107 * return : nb bytes sent, or error
2108 */
MicriumSendTo(WOLFSSL * ssl,char * buf,int sz,void * ctx)2109 int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2110 {
2111 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
2112 NET_SOCK_ID sd = dtlsCtx->wfd;
2113 NET_SOCK_RTN_CODE ret;
2114 NET_ERR err;
2115
2116 WOLFSSL_ENTER("MicriumSendTo()");
2117
2118 ret = NetSock_TxDataTo(sd, buf, sz, ssl->wflags,
2119 (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
2120 (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
2121 &err);
2122 if (err < 0) {
2123 WOLFSSL_MSG("Embed Send To error");
2124
2125 if (err == NET_ERR_TX) {
2126 WOLFSSL_MSG("\tWould block");
2127 return WOLFSSL_CBIO_ERR_WANT_WRITE;
2128
2129 } else {
2130 WOLFSSL_MSG("\tGeneral error");
2131 return WOLFSSL_CBIO_ERR_GENERAL;
2132 }
2133 }
2134
2135 return ret;
2136 }
2137
2138 /* Micrium DTLS Generate Cookie callback
2139 * return : number of bytes copied into buf, or error
2140 */
MicriumGenerateCookie(WOLFSSL * ssl,byte * buf,int sz,void * ctx)2141 int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
2142 {
2143 NET_SOCK_ADDR peer;
2144 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
2145 byte digest[WC_SHA_DIGEST_SIZE];
2146 int ret = 0;
2147
2148 (void)ctx;
2149
2150 XMEMSET(&peer, 0, sizeof(peer));
2151 if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
2152 (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
2153 WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
2154 return GEN_COOKIE_E;
2155 }
2156
2157 ret = wc_ShaHash((byte*)&peer, peerSz, digest);
2158 if (ret != 0)
2159 return ret;
2160
2161 if (sz > WC_SHA_DIGEST_SIZE)
2162 sz = WC_SHA_DIGEST_SIZE;
2163 XMEMCPY(buf, digest, sz);
2164
2165 return sz;
2166 }
2167
2168 #endif /* MICRIUM */
2169
2170 #if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
2171
2172 #include <os/os_error.h>
2173 #include <os/os_mbuf.h>
2174 #include <os/os_mempool.h>
2175
2176 #define MB_NAME "wolfssl_mb"
2177
2178 typedef struct Mynewt_Ctx {
2179 struct mn_socket *mnSocket; /* send/recv socket handler */
2180 struct mn_sockaddr_in mnSockAddrIn; /* socket address */
2181 struct os_mbuf *mnPacket; /* incoming packet handle
2182 for short reads */
2183 int reading; /* reading flag */
2184
2185 /* private */
2186 void *mnMemBuffer; /* memory buffer for mempool */
2187 struct os_mempool mnMempool; /* mempool */
2188 struct os_mbuf_pool mnMbufpool; /* mbuf pool */
2189 } Mynewt_Ctx;
2190
mynewt_ctx_clear(void * ctx)2191 void mynewt_ctx_clear(void *ctx) {
2192 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2193 if(!mynewt_ctx) return;
2194
2195 if(mynewt_ctx->mnPacket) {
2196 os_mbuf_free_chain(mynewt_ctx->mnPacket);
2197 mynewt_ctx->mnPacket = NULL;
2198 }
2199 os_mempool_clear(&mynewt_ctx->mnMempool);
2200 XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
2201 XFREE(mynewt_ctx, 0, 0);
2202 }
2203
2204 /* return Mynewt_Ctx instance */
mynewt_ctx_new()2205 void* mynewt_ctx_new() {
2206 int rc = 0;
2207 Mynewt_Ctx *mynewt_ctx;
2208 int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
2209 int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
2210 int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
2211
2212 mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
2213 NULL, DYNAMIC_TYPE_TMP_BUFFER);
2214 if(!mynewt_ctx) return NULL;
2215
2216 XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
2217 mynewt_ctx->mnMemBuffer = (void *)XMALLOC(mempool_bytes, 0, 0);
2218 if(!mynewt_ctx->mnMemBuffer) {
2219 mynewt_ctx_clear((void*)mynewt_ctx);
2220 return NULL;
2221 }
2222
2223 rc = os_mempool_init(&mynewt_ctx->mnMempool,
2224 mem_buf_count, mem_buf_size,
2225 mynewt_ctx->mnMemBuffer, MB_NAME);
2226 if(rc != 0) {
2227 mynewt_ctx_clear((void*)mynewt_ctx);
2228 return NULL;
2229 }
2230 rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
2231 mem_buf_count, mem_buf_size);
2232 if(rc != 0) {
2233 mynewt_ctx_clear((void*)mynewt_ctx);
2234 return NULL;
2235 }
2236
2237 return mynewt_ctx;
2238 }
2239
2240 static void mynewt_sock_writable(void *arg, int err);
2241 static void mynewt_sock_readable(void *arg, int err);
2242 static const union mn_socket_cb mynewt_sock_cbs = {
2243 .socket.writable = mynewt_sock_writable,
2244 .socket.readable = mynewt_sock_readable,
2245 };
mynewt_sock_writable(void * arg,int err)2246 static void mynewt_sock_writable(void *arg, int err)
2247 {
2248 /* do nothing */
2249 }
mynewt_sock_readable(void * arg,int err)2250 static void mynewt_sock_readable(void *arg, int err)
2251 {
2252 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
2253 if (err && mynewt_ctx->reading) {
2254 mynewt_ctx->reading = 0;
2255 }
2256 }
2257
2258 /* The Mynewt receive callback
2259 * return : bytes read, or error
2260 */
Mynewt_Receive(WOLFSSL * ssl,char * buf,int sz,void * ctx)2261 int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
2262 {
2263 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2264 int rc = 0;
2265 struct mn_sockaddr_in from;
2266 struct os_mbuf *m;
2267 int read_sz = 0;
2268 word16 total;
2269
2270 if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
2271 WOLFSSL_MSG("Mynewt Recv NULL parameters");
2272 return WOLFSSL_CBIO_ERR_GENERAL;
2273 }
2274
2275 if(mynewt_ctx->mnPacket == NULL) {
2276 mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
2277 if(mynewt_ctx->mnPacket == NULL) {
2278 return MEMORY_E;
2279 }
2280
2281 mynewt_ctx->reading = 1;
2282 while(mynewt_ctx->reading && rc == 0) {
2283 rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
2284 if(rc == MN_ECONNABORTED) {
2285 rc = 0;
2286 mynewt_ctx->reading = 0;
2287 break;
2288 }
2289 if (!(rc == 0 || rc == MN_EAGAIN)) {
2290 WOLFSSL_MSG("Mynewt Recv receive error");
2291 mynewt_ctx->reading = 0;
2292 break;
2293 }
2294 if(rc == 0) {
2295 int len = OS_MBUF_PKTLEN(m);
2296 if(len == 0) {
2297 break;
2298 }
2299 rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
2300 if(rc != 0) {
2301 WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
2302 break;
2303 }
2304 os_mbuf_free_chain(m);
2305 m = NULL;
2306 } else if(rc == MN_EAGAIN) {
2307 /* continue to until reading all of packet data. */
2308 rc = 0;
2309 break;
2310 }
2311 }
2312 if(rc != 0) {
2313 mynewt_ctx->reading = 0;
2314 os_mbuf_free_chain(mynewt_ctx->mnPacket);
2315 mynewt_ctx->mnPacket = NULL;
2316 return rc;
2317 }
2318 }
2319
2320 if(mynewt_ctx->mnPacket) {
2321 total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
2322 read_sz = (total >= sz)? sz : total;
2323
2324 os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
2325 os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
2326
2327 if (read_sz == total) {
2328 WOLFSSL_MSG("Mynewt Recv Drained packet");
2329 os_mbuf_free_chain(mynewt_ctx->mnPacket);
2330 mynewt_ctx->mnPacket = NULL;
2331 }
2332 }
2333
2334 return read_sz;
2335 }
2336
2337 /* The Mynewt send callback
2338 * return : bytes sent, or error
2339 */
Mynewt_Send(WOLFSSL * ssl,char * buf,int sz,void * ctx)2340 int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2341 {
2342 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2343 int rc = 0;
2344 struct os_mbuf *m;
2345 int write_sz = 0;
2346 m = os_msys_get_pkthdr(sz, 0);
2347 if (!m) {
2348 WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
2349 return WOLFSSL_CBIO_ERR_GENERAL;
2350 }
2351 rc = os_mbuf_copyinto(m, 0, buf, sz);
2352 if (rc != 0) {
2353 WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
2354 os_mbuf_free_chain(m);
2355 return rc;
2356 }
2357 rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
2358 if(rc != 0) {
2359 WOLFSSL_MSG("Mynewt Send mn_sendto error");
2360 os_mbuf_free_chain(m);
2361 return rc;
2362 }
2363 write_sz = sz;
2364 return write_sz;
2365 }
2366
2367 /* like set_fd, but for default NetX context */
wolfSSL_SetIO_Mynewt(WOLFSSL * ssl,struct mn_socket * mnSocket,struct mn_sockaddr_in * mnSockAddrIn)2368 void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
2369 {
2370 if (ssl && ssl->mnCtx) {
2371 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
2372 mynewt_ctx->mnSocket = mnSocket;
2373 XMEMCPY(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
2374 mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
2375 }
2376 }
2377
2378 #endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
2379
2380 #ifdef WOLFSSL_UIP
2381 #include <uip.h>
2382 #include <stdio.h>
2383
2384 /* uIP TCP/IP port, using the native tcp/udp socket api.
2385 * TCP and UDP are currently supported with the callbacks below.
2386 *
2387 */
2388 /* The uIP tcp send callback
2389 * return : bytes sent, or error
2390 */
uIPSend(WOLFSSL * ssl,char * buf,int sz,void * _ctx)2391 int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
2392 {
2393 uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
2394 int ret;
2395 unsigned int max_sendlen;
2396 int total_written = 0;
2397 (void)ssl;
2398 do {
2399 unsigned int bytes_left = sz - total_written;
2400 max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
2401 if (bytes_left > max_sendlen) {
2402 printf("Send limited by buffer\r\n");
2403 bytes_left = max_sendlen;
2404 }
2405 if (bytes_left == 0) {
2406 printf("Buffer full!\r\n");
2407 break;
2408 }
2409 ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
2410 if (ret <= 0)
2411 break;
2412 total_written += ret;
2413 } while(total_written < sz);
2414 if (total_written == 0)
2415 return WOLFSSL_CBIO_ERR_WANT_WRITE;
2416 return total_written;
2417 }
2418
uIPSendTo(WOLFSSL * ssl,char * buf,int sz,void * _ctx)2419 int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
2420 {
2421 uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
2422 int ret = 0;
2423 (void)ssl;
2424 ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
2425 if (ret == 0)
2426 return WOLFSSL_CBIO_ERR_WANT_WRITE;
2427 return ret;
2428 }
2429
2430 /* The uIP uTCP/IP receive callback
2431 * return : nb bytes read, or error
2432 */
uIPReceive(WOLFSSL * ssl,char * buf,int sz,void * _ctx)2433 int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
2434 {
2435 uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
2436 if (!ctx || !ctx->ssl_rx_databuf)
2437 return -1;
2438 (void)ssl;
2439 if (ctx->ssl_rb_len > 0) {
2440 if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
2441 sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
2442 XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
2443 ctx->ssl_rb_off += sz;
2444 if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
2445 ctx->ssl_rb_len = 0;
2446 ctx->ssl_rb_off = 0;
2447 }
2448 return sz;
2449 } else {
2450 return WOLFSSL_CBIO_ERR_WANT_READ;
2451 }
2452 }
2453
2454 /* uIP DTLS Generate Cookie callback
2455 * return : number of bytes copied into buf, or error
2456 */
uIPGenerateCookie(WOLFSSL * ssl,byte * buf,int sz,void * _ctx)2457 int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
2458 {
2459 uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
2460 byte token[32];
2461 byte digest[WC_SHA_DIGEST_SIZE];
2462 int ret = 0;
2463 XMEMSET(token, 0, sizeof(token));
2464 XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
2465 XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
2466 ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
2467 if (ret != 0)
2468 return ret;
2469 if (sz > WC_SHA_DIGEST_SIZE)
2470 sz = WC_SHA_DIGEST_SIZE;
2471 XMEMCPY(buf, digest, sz);
2472 return sz;
2473 }
2474
2475 #endif /* WOLFSSL_UIP */
2476
2477 #ifdef WOLFSSL_GNRC
2478
2479 #include <net/sock.h>
2480 #include <net/sock/tcp.h>
2481 #include <stdio.h>
2482
2483 /* GNRC TCP/IP port, using the native tcp/udp socket api.
2484 * TCP and UDP are currently supported with the callbacks below.
2485 *
2486 */
2487 /* The GNRC tcp send callback
2488 * return : bytes sent, or error
2489 */
2490
GNRC_SendTo(WOLFSSL * ssl,char * buf,int sz,void * _ctx)2491 int GNRC_SendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
2492 {
2493 sock_tls_t *ctx = (sock_tls_t *)_ctx;
2494 int ret = 0;
2495 (void)ssl;
2496 if (!ctx)
2497 return WOLFSSL_CBIO_ERR_GENERAL;
2498 ret = sock_udp_send(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr);
2499 if (ret == 0)
2500 return WOLFSSL_CBIO_ERR_WANT_WRITE;
2501 return ret;
2502 }
2503
2504 /* The GNRC TCP/IP receive callback
2505 * return : nb bytes read, or error
2506 */
GNRC_ReceiveFrom(WOLFSSL * ssl,char * buf,int sz,void * _ctx)2507 int GNRC_ReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
2508 {
2509 sock_udp_ep_t ep;
2510 int ret;
2511 word32 timeout = wolfSSL_dtls_get_current_timeout(ssl) * 1000000;
2512 sock_tls_t *ctx = (sock_tls_t *)_ctx;
2513 if (!ctx)
2514 return WOLFSSL_CBIO_ERR_GENERAL;
2515 (void)ssl;
2516 if (wolfSSL_get_using_nonblock(ctx->ssl)) {
2517 timeout = 0;
2518 }
2519 ret = sock_udp_recv(&ctx->conn.udp, buf, sz, timeout, &ep);
2520 if (ret > 0) {
2521 if (ctx->peer_addr.port == 0)
2522 XMEMCPY(&ctx->peer_addr, &ep, sizeof(sock_udp_ep_t));
2523 }
2524 if (ret == -ETIMEDOUT) {
2525 return WOLFSSL_CBIO_ERR_WANT_READ;
2526 }
2527 return ret;
2528 }
2529
2530 /* GNRC DTLS Generate Cookie callback
2531 * return : number of bytes copied into buf, or error
2532 */
2533 #define GNRC_MAX_TOKEN_SIZE (32)
GNRC_GenerateCookie(WOLFSSL * ssl,byte * buf,int sz,void * _ctx)2534 int GNRC_GenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
2535 {
2536 sock_tls_t *ctx = (sock_tls_t *)_ctx;
2537 if (!ctx)
2538 return WOLFSSL_CBIO_ERR_GENERAL;
2539 byte token[GNRC_MAX_TOKEN_SIZE];
2540 byte digest[WC_SHA_DIGEST_SIZE];
2541 int ret = 0;
2542 size_t token_size = sizeof(sock_udp_ep_t);
2543 (void)ssl;
2544 if (token_size > GNRC_MAX_TOKEN_SIZE)
2545 token_size = GNRC_MAX_TOKEN_SIZE;
2546 XMEMSET(token, 0, GNRC_MAX_TOKEN_SIZE);
2547 XMEMCPY(token, &ctx->peer_addr, token_size);
2548 ret = wc_ShaHash(token, token_size, digest);
2549 if (ret != 0)
2550 return ret;
2551 if (sz > WC_SHA_DIGEST_SIZE)
2552 sz = WC_SHA_DIGEST_SIZE;
2553 XMEMCPY(buf, digest, sz);
2554 return sz;
2555 }
2556
2557 #endif /* WOLFSSL_GNRC */
2558
2559 #ifdef WOLFSSL_LWIP_NATIVE
LwIPNativeSend(WOLFSSL * ssl,char * buf,int sz,void * ctx)2560 int LwIPNativeSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2561 {
2562 err_t ret;
2563 WOLFSSL_LWIP_NATIVE_STATE* nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
2564
2565 ret = tcp_write(nlwip->pcb, buf, sz, TCP_WRITE_FLAG_COPY);
2566 if (ret != ERR_OK) {
2567 sz = -1;
2568 }
2569
2570 return sz;
2571 }
2572
2573
LwIPNativeReceive(WOLFSSL * ssl,char * buf,int sz,void * ctx)2574 int LwIPNativeReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
2575 {
2576 struct pbuf *current, *head;
2577 WOLFSSL_LWIP_NATIVE_STATE* nlwip;
2578 int ret = 0;
2579
2580 if (nlwip == NULL || ctx == NULL) {
2581 return WOLFSSL_CBIO_ERR_GENERAL;
2582 }
2583 nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)ctx;
2584
2585 current = nlwip->pbuf;
2586 if (current == NULL || sz > current->tot_len) {
2587 WOLFSSL_MSG("LwIP native pbuf list is null or not enough data, want read");
2588 ret = WOLFSSL_CBIO_ERR_WANT_READ;
2589 }
2590 else {
2591 int read = 0; /* total amount read */
2592 head = nlwip->pbuf; /* save pointer to current head */
2593
2594 /* loop through buffers reading data */
2595 while (current != NULL) {
2596 int len; /* current amount to be read */
2597
2598 len = (current->len - nlwip->pulled < sz) ?
2599 (current->len - nlwip->pulled) : sz;
2600
2601 if (read + len > sz) {
2602 /* should never be hit but have sanity check before use */
2603 return WOLFSSL_CBIO_ERR_GENERAL;
2604 }
2605
2606 /* check if is a partial read from before */
2607 XMEMCPY(&buf[read],
2608 (const char *)&(((char *)(current->payload))[nlwip->pulled]),
2609
2610 len);
2611 nlwip->pulled = nlwip->pulled + len;
2612 if (nlwip->pulled >= current->len) {
2613 WOLFSSL_MSG("Native LwIP read full pbuf");
2614 nlwip->pbuf = current->next;
2615 current = nlwip->pbuf;
2616 nlwip->pulled = 0;
2617 }
2618 read = read + len;
2619 ret = read;
2620
2621 /* read enough break out */
2622 if (read >= sz) {
2623 /* if more pbuf's are left in the chain then increment the
2624 * ref count for next in chain and free all from begining till
2625 * next */
2626 if (current != NULL) {
2627 pbuf_ref(current);
2628 }
2629
2630 /* ack and start free'ing from the current head of the chain */
2631 pbuf_free(head);
2632 break;
2633 }
2634 }
2635 }
2636 WOLFSSL_LEAVE("LwIPNativeReceive", ret);
2637 return ret;
2638 }
2639
2640
LwIPNativeReceiveCB(void * cb,struct tcp_pcb * pcb,struct pbuf * pbuf,err_t err)2641 static err_t LwIPNativeReceiveCB(void* cb, struct tcp_pcb* pcb,
2642 struct pbuf* pbuf, err_t err)
2643 {
2644 WOLFSSL_LWIP_NATIVE_STATE* nlwip;
2645
2646 if (cb == NULL || pcb == NULL) {
2647 WOLFSSL_MSG("Expected callback was null, abort");
2648 return ERR_ABRT;
2649 }
2650
2651 nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
2652 if (pbuf == NULL && err == ERR_OK) {
2653 return ERR_OK;
2654 }
2655
2656 if (nlwip->pbuf == NULL) {
2657 nlwip->pbuf = pbuf;
2658 }
2659 else {
2660 if (nlwip->pbuf != pbuf) {
2661 tcp_recved(nlwip->pcb, pbuf->tot_len);
2662 pbuf_cat(nlwip->pbuf, pbuf); /* add chain to head */
2663 }
2664 }
2665
2666 if (nlwip->recv_fn) {
2667 return nlwip->recv_fn(nlwip->arg, pcb, pbuf, err);
2668 }
2669
2670 WOLFSSL_LEAVE("LwIPNativeReceiveCB", nlwip->pbuf->tot_len);
2671 return ERR_OK;
2672 }
2673
2674
LwIPNativeSentCB(void * cb,struct tcp_pcb * pcb,u16_t len)2675 static err_t LwIPNativeSentCB(void* cb, struct tcp_pcb* pcb, u16_t len)
2676 {
2677 WOLFSSL_LWIP_NATIVE_STATE* nlwip;
2678
2679 if (cb == NULL || pcb == NULL) {
2680 WOLFSSL_MSG("Expected callback was null, abort");
2681 return ERR_ABRT;
2682 }
2683
2684 nlwip = (WOLFSSL_LWIP_NATIVE_STATE*)cb;
2685 if (nlwip->sent_fn) {
2686 return nlwip->sent_fn(nlwip->arg, pcb, len);
2687 }
2688 return ERR_OK;
2689 }
2690
2691
wolfSSL_SetIO_LwIP(WOLFSSL * ssl,void * pcb,tcp_recv_fn recv_fn,tcp_sent_fn sent_fn,void * arg)2692 int wolfSSL_SetIO_LwIP(WOLFSSL* ssl, void* pcb,
2693 tcp_recv_fn recv_fn, tcp_sent_fn sent_fn, void *arg)
2694 {
2695 if (ssl == NULL || pcb == NULL)
2696 return BAD_FUNC_ARG;
2697
2698 ssl->lwipCtx.pcb = (struct tcp_pcb *)pcb;
2699 ssl->lwipCtx.recv_fn = recv_fn; /* recv user callback */
2700 ssl->lwipCtx.sent_fn = sent_fn; /* sent user callback */
2701 ssl->lwipCtx.arg = arg;
2702 ssl->lwipCtx.pbuf = 0;
2703 ssl->lwipCtx.pulled = 0;
2704 ssl->lwipCtx.wait = 0;
2705
2706 /* wolfSSL_LwIP_recv/sent_cb invokes recv/sent user callback in them. */
2707 tcp_recv(pcb, LwIPNativeReceiveCB);
2708 tcp_sent(pcb, LwIPNativeSentCB);
2709 tcp_arg (pcb, (void *)&ssl->lwipCtx);
2710 wolfSSL_SetIOReadCtx(ssl, &ssl->lwipCtx);
2711 wolfSSL_SetIOWriteCtx(ssl, &ssl->lwipCtx);
2712
2713 return ERR_OK;
2714 }
2715 #endif
2716
2717 #endif /* WOLFCRYPT_ONLY */
2718