source: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/src/wolfio.c@ 372

Last change on this file since 372 was 372, checked in by coas-nagasima, 5 years ago

wolfsslを3.15.7にバージョンアップ

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 61.6 KB
Line 
1/* wolfio.c
2 *
3 * Copyright (C) 2006-2017 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> /* atoi(), strtol() */
43#endif
44
45/*
46Possible 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: off
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 */
67static 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
91static WC_INLINE int wolfSSL_LastError(void)
92{
93#ifdef USE_WINDOWS_API
94 return WSAGetLastError();
95#elif defined(EBSNET)
96 return xn_getlasterror();
97#else
98 return errno;
99#endif
100}
101
102#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
103
104
105#ifdef OPENSSL_EXTRA
106/* Use the WOLFSSL read BIO for receiving data. This is set by the function
107 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
108 *
109 * ssl WOLFSSL struct passed in that has this function set as the receive
110 * callback.
111 * buf buffer to fill with data read
112 * sz size of buf buffer
113 * ctx a user set context
114 *
115 * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
116 */
117int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
118{
119 int recvd = WOLFSSL_CBIO_ERR_GENERAL;
120
121 WOLFSSL_ENTER("BioReceive");
122
123 if (ssl->biord == NULL) {
124 WOLFSSL_MSG("WOLFSSL biord not set");
125 return WOLFSSL_CBIO_ERR_GENERAL;
126 }
127
128 switch (ssl->biord->type) {
129 case WOLFSSL_BIO_MEMORY:
130 case WOLFSSL_BIO_BIO:
131 if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
132 return WOLFSSL_CBIO_ERR_WANT_READ;
133 }
134 recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
135 if (recvd <= 0) {
136 return WOLFSSL_CBIO_ERR_GENERAL;
137 }
138 break;
139
140 default:
141 WOLFSSL_MSG("This BIO type is unknown / unsupported");
142 return WOLFSSL_CBIO_ERR_GENERAL;
143 }
144
145 (void)ctx;
146 return recvd;
147}
148
149
150/* Use the WOLFSSL write BIO for sending data. This is set by the function
151 * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
152 *
153 * ssl WOLFSSL struct passed in that has this function set as the send callback.
154 * buf buffer with data to write out
155 * sz size of buf buffer
156 * ctx a user set context
157 *
158 * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
159 */
160int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
161{
162 int sent = WOLFSSL_CBIO_ERR_GENERAL;
163
164 if (ssl->biowr == NULL) {
165 WOLFSSL_MSG("WOLFSSL biowr not set\n");
166 return WOLFSSL_CBIO_ERR_GENERAL;
167 }
168
169 switch (ssl->biowr->type) {
170 case WOLFSSL_BIO_MEMORY:
171 case WOLFSSL_BIO_BIO:
172 sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
173 if (sent < 0) {
174 return WOLFSSL_CBIO_ERR_GENERAL;
175 }
176 break;
177
178 default:
179 WOLFSSL_MSG("This BIO type is unknown / unsupported");
180 return WOLFSSL_CBIO_ERR_GENERAL;
181 }
182 (void)ctx;
183
184 return sent;
185}
186#endif
187
188
189#ifdef USE_WOLFSSL_IO
190
191/* The receive embedded callback
192 * return : nb bytes read, or error
193 */
194int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
195{
196 int sd = *(int*)ctx;
197 int recvd;
198
199 recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
200 if (recvd < 0) {
201 int err = wolfSSL_LastError();
202 WOLFSSL_MSG("Embed Receive error");
203
204 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
205 WOLFSSL_MSG("\tWould block");
206 return WOLFSSL_CBIO_ERR_WANT_READ;
207 }
208 else if (err == SOCKET_ECONNRESET) {
209 WOLFSSL_MSG("\tConnection reset");
210 return WOLFSSL_CBIO_ERR_CONN_RST;
211 }
212 else if (err == SOCKET_EINTR) {
213 WOLFSSL_MSG("\tSocket interrupted");
214 return WOLFSSL_CBIO_ERR_ISR;
215 }
216 else if (err == SOCKET_ECONNABORTED) {
217 WOLFSSL_MSG("\tConnection aborted");
218 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
219 }
220 else {
221 WOLFSSL_MSG("\tGeneral error");
222 return WOLFSSL_CBIO_ERR_GENERAL;
223 }
224 }
225 else if (recvd == 0) {
226 WOLFSSL_MSG("Embed receive connection closed");
227 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
228 }
229
230 return recvd;
231}
232
233/* The send embedded callback
234 * return : nb bytes sent, or error
235 */
236int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
237{
238 int sd = *(int*)ctx;
239 int sent;
240
241 sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
242 if (sent < 0) {
243 int err = wolfSSL_LastError();
244 WOLFSSL_MSG("Embed Send error");
245
246 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
247 WOLFSSL_MSG("\tWould Block");
248 return WOLFSSL_CBIO_ERR_WANT_WRITE;
249 }
250 else if (err == SOCKET_ECONNRESET) {
251 WOLFSSL_MSG("\tConnection reset");
252 return WOLFSSL_CBIO_ERR_CONN_RST;
253 }
254 else if (err == SOCKET_EINTR) {
255 WOLFSSL_MSG("\tSocket interrupted");
256 return WOLFSSL_CBIO_ERR_ISR;
257 }
258 else if (err == SOCKET_EPIPE) {
259 WOLFSSL_MSG("\tSocket EPIPE");
260 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
261 }
262 else {
263 WOLFSSL_MSG("\tGeneral error");
264 return WOLFSSL_CBIO_ERR_GENERAL;
265 }
266 }
267
268 return sent;
269}
270
271
272#ifdef WOLFSSL_DTLS
273
274#include <wolfssl/wolfcrypt/sha.h>
275
276#define SENDTO_FUNCTION sendto
277#define RECVFROM_FUNCTION recvfrom
278
279
280/* The receive embedded callback
281 * return : nb bytes read, or error
282 */
283int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
284{
285 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
286 int recvd;
287 int err;
288 int sd = dtlsCtx->rfd;
289 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
290 SOCKADDR_S peer;
291 XSOCKLENT peerSz = sizeof(peer);
292
293 WOLFSSL_ENTER("EmbedReceiveFrom()");
294
295 if (ssl->options.handShakeDone)
296 dtls_timeout = 0;
297
298 if (!wolfSSL_get_using_nonblock(ssl)) {
299 #ifdef USE_WINDOWS_API
300 DWORD timeout = dtls_timeout * 1000;
301 #else
302 struct timeval timeout;
303 XMEMSET(&timeout, 0, sizeof(timeout));
304 timeout.tv_sec = dtls_timeout;
305 #endif
306 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
307 sizeof(timeout)) != 0) {
308 WOLFSSL_MSG("setsockopt rcvtimeo failed");
309 }
310 }
311
312 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
313 (SOCKADDR*)&peer, &peerSz);
314
315 recvd = TranslateReturnCode(recvd, sd);
316
317 if (recvd < 0) {
318 err = wolfSSL_LastError();
319 WOLFSSL_MSG("Embed Receive From error");
320
321 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
322 if (wolfSSL_dtls_get_using_nonblock(ssl)) {
323 WOLFSSL_MSG("\tWould block");
324 return WOLFSSL_CBIO_ERR_WANT_READ;
325 }
326 else {
327 WOLFSSL_MSG("\tSocket timeout");
328 return WOLFSSL_CBIO_ERR_TIMEOUT;
329 }
330 }
331 else if (err == SOCKET_ECONNRESET) {
332 WOLFSSL_MSG("\tConnection reset");
333 return WOLFSSL_CBIO_ERR_CONN_RST;
334 }
335 else if (err == SOCKET_EINTR) {
336 WOLFSSL_MSG("\tSocket interrupted");
337 return WOLFSSL_CBIO_ERR_ISR;
338 }
339 else if (err == SOCKET_ECONNREFUSED) {
340 WOLFSSL_MSG("\tConnection refused");
341 return WOLFSSL_CBIO_ERR_WANT_READ;
342 }
343 else {
344 WOLFSSL_MSG("\tGeneral error");
345 return WOLFSSL_CBIO_ERR_GENERAL;
346 }
347 }
348 else {
349 if (dtlsCtx->peer.sz > 0
350 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
351 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
352 WOLFSSL_MSG(" Ignored packet from invalid peer");
353 return WOLFSSL_CBIO_ERR_WANT_READ;
354 }
355 }
356
357 return recvd;
358}
359
360
361/* The send embedded callback
362 * return : nb bytes sent, or error
363 */
364int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
365{
366 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
367 int sd = dtlsCtx->wfd;
368 int sent;
369 int len = sz;
370 int err;
371
372 WOLFSSL_ENTER("EmbedSendTo()");
373
374 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
375 (const SOCKADDR*)dtlsCtx->peer.sa,
376 dtlsCtx->peer.sz);
377
378 sent = TranslateReturnCode(sent, sd);
379
380 if (sent < 0) {
381 err = wolfSSL_LastError();
382 WOLFSSL_MSG("Embed Send To error");
383
384 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
385 WOLFSSL_MSG("\tWould Block");
386 return WOLFSSL_CBIO_ERR_WANT_WRITE;
387 }
388 else if (err == SOCKET_ECONNRESET) {
389 WOLFSSL_MSG("\tConnection reset");
390 return WOLFSSL_CBIO_ERR_CONN_RST;
391 }
392 else if (err == SOCKET_EINTR) {
393 WOLFSSL_MSG("\tSocket interrupted");
394 return WOLFSSL_CBIO_ERR_ISR;
395 }
396 else if (err == SOCKET_EPIPE) {
397 WOLFSSL_MSG("\tSocket EPIPE");
398 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
399 }
400 else {
401 WOLFSSL_MSG("\tGeneral error");
402 return WOLFSSL_CBIO_ERR_GENERAL;
403 }
404 }
405
406 return sent;
407}
408
409
410#ifdef WOLFSSL_MULTICAST
411
412/* The alternate receive embedded callback for Multicast
413 * return : nb bytes read, or error
414 */
415int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
416{
417 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
418 int recvd;
419 int err;
420 int sd = dtlsCtx->rfd;
421
422 WOLFSSL_ENTER("EmbedReceiveFromMcast()");
423
424 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
425
426 recvd = TranslateReturnCode(recvd, sd);
427
428 if (recvd < 0) {
429 err = wolfSSL_LastError();
430 WOLFSSL_MSG("Embed Receive From error");
431
432 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
433 if (wolfSSL_dtls_get_using_nonblock(ssl)) {
434 WOLFSSL_MSG("\tWould block");
435 return WOLFSSL_CBIO_ERR_WANT_READ;
436 }
437 else {
438 WOLFSSL_MSG("\tSocket timeout");
439 return WOLFSSL_CBIO_ERR_TIMEOUT;
440 }
441 }
442 else if (err == SOCKET_ECONNRESET) {
443 WOLFSSL_MSG("\tConnection reset");
444 return WOLFSSL_CBIO_ERR_CONN_RST;
445 }
446 else if (err == SOCKET_EINTR) {
447 WOLFSSL_MSG("\tSocket interrupted");
448 return WOLFSSL_CBIO_ERR_ISR;
449 }
450 else if (err == SOCKET_ECONNREFUSED) {
451 WOLFSSL_MSG("\tConnection refused");
452 return WOLFSSL_CBIO_ERR_WANT_READ;
453 }
454 else {
455 WOLFSSL_MSG("\tGeneral error");
456 return WOLFSSL_CBIO_ERR_GENERAL;
457 }
458 }
459
460 return recvd;
461}
462#endif /* WOLFSSL_MULTICAST */
463
464
465/* The DTLS Generate Cookie callback
466 * return : number of bytes copied into buf, or error
467 */
468int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
469{
470 int sd = ssl->wfd;
471 SOCKADDR_S peer;
472 XSOCKLENT peerSz = sizeof(peer);
473 byte digest[WC_SHA256_DIGEST_SIZE];
474 int ret = 0;
475
476 (void)ctx;
477
478 XMEMSET(&peer, 0, sizeof(peer));
479 if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
480 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
481 return GEN_COOKIE_E;
482 }
483
484 ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
485 if (ret != 0)
486 return ret;
487
488 if (sz > WC_SHA256_DIGEST_SIZE)
489 sz = WC_SHA256_DIGEST_SIZE;
490 XMEMCPY(buf, digest, sz);
491
492 return sz;
493}
494
495#ifdef WOLFSSL_SESSION_EXPORT
496
497 /* get the peer information in human readable form (ip, port, family)
498 * default function assumes BSD sockets
499 * can be overriden with wolfSSL_CTX_SetIOGetPeer
500 */
501 int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
502 unsigned short* port, int* fam)
503 {
504 SOCKADDR_S peer;
505 word32 peerSz;
506 int ret;
507
508 if (ssl == NULL || ip == NULL || ipSz == NULL ||
509 port == NULL || fam == NULL) {
510 return BAD_FUNC_ARG;
511 }
512
513 /* get peer information stored in ssl struct */
514 peerSz = sizeof(SOCKADDR_S);
515 if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
516 != WOLFSSL_SUCCESS) {
517 return ret;
518 }
519
520 /* extract family, ip, and port */
521 *fam = ((SOCKADDR_S*)&peer)->ss_family;
522 switch (*fam) {
523 case WOLFSSL_IP4:
524 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
525 ip, *ipSz) == NULL) {
526 WOLFSSL_MSG("XINET_NTOP error");
527 return SOCKET_ERROR_E;
528 }
529 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
530 break;
531
532 case WOLFSSL_IP6:
533 #ifdef WOLFSSL_IPV6
534 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
535 ip, *ipSz) == NULL) {
536 WOLFSSL_MSG("XINET_NTOP error");
537 return SOCKET_ERROR_E;
538 }
539 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
540 #endif /* WOLFSSL_IPV6 */
541 break;
542
543 default:
544 WOLFSSL_MSG("Unknown family type");
545 return SOCKET_ERROR_E;
546 }
547 ip[*ipSz - 1] = '\0'; /* make sure has terminator */
548 *ipSz = (word16)XSTRLEN(ip);
549
550 return WOLFSSL_SUCCESS;
551 }
552
553 /* set the peer information in human readable form (ip, port, family)
554 * default function assumes BSD sockets
555 * can be overriden with wolfSSL_CTX_SetIOSetPeer
556 */
557 int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
558 unsigned short port, int fam)
559 {
560 int ret;
561 SOCKADDR_S addr;
562
563 /* sanity checks on arguments */
564 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
565 return BAD_FUNC_ARG;
566 }
567
568 addr.ss_family = fam;
569 switch (addr.ss_family) {
570 case WOLFSSL_IP4:
571 if (XINET_PTON(addr.ss_family, ip,
572 &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
573 WOLFSSL_MSG("XINET_PTON error");
574 return SOCKET_ERROR_E;
575 }
576 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
577
578 /* peer sa is free'd in SSL_ResourceFree */
579 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
580 sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
581 WOLFSSL_MSG("Import DTLS peer info error");
582 return ret;
583 }
584 break;
585
586 case WOLFSSL_IP6:
587 #ifdef WOLFSSL_IPV6
588 if (XINET_PTON(addr.ss_family, ip,
589 &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
590 WOLFSSL_MSG("XINET_PTON error");
591 return SOCKET_ERROR_E;
592 }
593 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
594
595 /* peer sa is free'd in SSL_ResourceFree */
596 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
597 sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
598 WOLFSSL_MSG("Import DTLS peer info error");
599 return ret;
600 }
601 #endif /* WOLFSSL_IPV6 */
602 break;
603
604 default:
605 WOLFSSL_MSG("Unknown address family");
606 return BUFFER_E;
607 }
608
609 return WOLFSSL_SUCCESS;
610 }
611#endif /* WOLFSSL_SESSION_EXPORT */
612#endif /* WOLFSSL_DTLS */
613
614
615int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
616{
617 int recvd;
618
619 recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
620 recvd = TranslateReturnCode(recvd, sd);
621
622 return recvd;
623}
624
625int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
626{
627 int sent;
628
629 sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
630 sent = TranslateReturnCode(sent, sd);
631
632 return sent;
633}
634
635#endif /* USE_WOLFSSL_IO */
636
637
638#ifdef HAVE_HTTP_CLIENT
639
640#ifndef HAVE_IO_TIMEOUT
641 #define io_timeout_sec 0
642#else
643
644 #ifndef DEFAULT_TIMEOUT_SEC
645 #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
646 #endif
647
648 static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
649
650 void wolfIO_SetTimeout(int to_sec)
651 {
652 io_timeout_sec = to_sec;
653 }
654
655 int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
656 {
657 int ret = 0;
658
659 #ifdef USE_WINDOWS_API
660 unsigned long blocking = non_blocking;
661 ret = ioctlsocket(sockfd, FIONBIO, &blocking);
662 if (ret == SOCKET_ERROR)
663 ret = -1;
664 #else
665 ret = fcntl(sockfd, F_GETFL, 0);
666 if (ret >= 0) {
667 if (non_blocking)
668 ret |= O_NONBLOCK;
669 else
670 ret &= ~O_NONBLOCK;
671 ret = fcntl(sockfd, F_SETFL, ret);
672 }
673 #endif
674 if (ret < 0) {
675 WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
676 }
677
678 return ret;
679 }
680
681 int wolfIO_Select(SOCKET_T sockfd, int to_sec)
682 {
683 fd_set rfds, wfds;
684 int nfds = 0;
685 struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
686 int ret;
687
688 #ifndef USE_WINDOWS_API
689 nfds = (int)sockfd + 1;
690 #endif
691
692 FD_ZERO(&rfds);
693 FD_SET(sockfd, &rfds);
694 wfds = rfds;
695
696 ret = select(nfds, &rfds, &wfds, NULL, &timeout);
697 if (ret == 0) {
698 #ifdef DEBUG_HTTP
699 printf("Timeout: %d\n", ret);
700 #endif
701 return HTTP_TIMEOUT;
702 }
703 else if (ret > 0) {
704 if (FD_ISSET(sockfd, &wfds)) {
705 if (!FD_ISSET(sockfd, &rfds)) {
706 return 0;
707 }
708 }
709 }
710 return SOCKET_ERROR_E;
711 }
712#endif /* HAVE_IO_TIMEOUT */
713
714static int wolfIO_Word16ToString(char* d, word16 number)
715{
716 int i = 0;
717 word16 order = 10000;
718 word16 digit;
719
720 if (d == NULL)
721 return i;
722
723 if (number == 0)
724 d[i++] = '0';
725 else {
726 while (order) {
727 digit = number / order;
728 if (i > 0 || digit != 0)
729 d[i++] = (char)digit + '0';
730 if (digit != 0)
731 number %= digit * order;
732
733 order = (order > 1) ? order / 10 : 0;
734 }
735 }
736 d[i] = 0; /* null terminate */
737
738 return i;
739}
740
741int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
742{
743#ifdef HAVE_SOCKADDR
744 int ret = 0;
745 SOCKADDR_S addr;
746 int sockaddr_len = sizeof(SOCKADDR_IN);
747#ifdef HAVE_GETADDRINFO
748 ADDRINFO hints;
749 ADDRINFO* answer = NULL;
750 char strPort[6];
751#else
752 HOSTENT* entry;
753 SOCKADDR_IN *sin;
754#endif
755
756 XMEMSET(&addr, 0, sizeof(addr));
757
758#ifdef WOLFIO_DEBUG
759 printf("TCP Connect: %s:%d\n", ip, port);
760#endif
761
762#ifdef HAVE_GETADDRINFO
763 XMEMSET(&hints, 0, sizeof(hints));
764 hints.ai_family = AF_UNSPEC;
765 hints.ai_socktype = SOCK_STREAM;
766 hints.ai_protocol = IPPROTO_TCP;
767
768 if (wolfIO_Word16ToString(strPort, port) == 0) {
769 WOLFSSL_MSG("invalid port number for responder");
770 return -1;
771 }
772
773 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
774 WOLFSSL_MSG("no addr info for responder");
775 return -1;
776 }
777
778 sockaddr_len = answer->ai_addrlen;
779 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
780 freeaddrinfo(answer);
781#else
782 entry = gethostbyname(ip);
783 sin = (SOCKADDR_IN *)&addr;
784
785 if (entry) {
786 sin->sin_family = AF_INET;
787 sin->sin_port = XHTONS(port);
788 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
789 }
790 else {
791 WOLFSSL_MSG("no addr info for responder");
792 return -1;
793 }
794#endif
795
796 *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
797
798#ifdef USE_WINDOWS_API
799 if (*sockfd == INVALID_SOCKET) {
800 WOLFSSL_MSG("bad socket fd, out of fds?");
801 return -1;
802 }
803#else
804 if (*sockfd < 0) {
805 WOLFSSL_MSG("bad socket fd, out of fds?");
806 return -1;
807 }
808#endif
809
810#ifdef HAVE_IO_TIMEOUT
811 /* if timeout value provided then set socket non-blocking */
812 if (to_sec > 0) {
813 wolfIO_SetBlockingMode(*sockfd, 1);
814 }
815#else
816 (void)to_sec;
817#endif
818
819 ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
820#ifdef HAVE_IO_TIMEOUT
821 if (ret != 0) {
822 if ((errno == EINPROGRESS) && (to_sec > 0)) {
823 /* wait for connect to complete */
824 ret = wolfIO_Select(*sockfd, to_sec);
825
826 /* restore blocking mode */
827 wolfIO_SetBlockingMode(*sockfd, 0);
828 }
829 }
830#endif
831 if (ret != 0) {
832 WOLFSSL_MSG("Responder tcp connect failed");
833 return -1;
834 }
835 return ret;
836#else
837 (void)sockfd;
838 (void)ip;
839 (void)port;
840 (void)to_sec;
841 return -1;
842#endif /* HAVE_SOCKADDR */
843}
844
845#ifndef HTTP_SCRATCH_BUFFER_SIZE
846 #define HTTP_SCRATCH_BUFFER_SIZE 512
847#endif
848#ifndef MAX_URL_ITEM_SIZE
849 #define MAX_URL_ITEM_SIZE 80
850#endif
851
852int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
853 word16* outPort)
854{
855 int result = -1;
856
857 if (url == NULL || urlSz == 0) {
858 if (outName)
859 *outName = 0;
860 if (outPath)
861 *outPath = 0;
862 if (outPort)
863 *outPort = 0;
864 }
865 else {
866 int i, cur;
867
868 /* need to break the url down into scheme, address, and port */
869 /* "http://example.com:8080/" */
870 /* "http://[::1]:443/" */
871 if (XSTRNCMP(url, "http://", 7) == 0) {
872 cur = 7;
873 } else cur = 0;
874
875 i = 0;
876 if (url[cur] == '[') {
877 cur++;
878 /* copy until ']' */
879 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
880 if (outName)
881 outName[i] = url[cur];
882 i++; cur++;
883 }
884 cur++; /* skip ']' */
885 }
886 else {
887 while (url[cur] != 0 && url[cur] != ':' &&
888 url[cur] != '/' && cur < urlSz) {
889 if (outName)
890 outName[i] = url[cur];
891 i++; cur++;
892 }
893 }
894 if (outName)
895 outName[i] = 0;
896 /* Need to pick out the path after the domain name */
897
898 if (cur < urlSz && url[cur] == ':') {
899 char port[6];
900 int j;
901 word32 bigPort = 0;
902 i = 0;
903 cur++;
904 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
905 i < 6) {
906 port[i++] = url[cur++];
907 }
908
909 for (j = 0; j < i; j++) {
910 if (port[j] < '0' || port[j] > '9') return -1;
911 bigPort = (bigPort * 10) + (port[j] - '0');
912 }
913 if (outPort)
914 *outPort = (word16)bigPort;
915 }
916 else if (outPort)
917 *outPort = 80;
918
919
920 if (cur < urlSz && url[cur] == '/') {
921 i = 0;
922 while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
923 if (outPath)
924 outPath[i] = url[cur];
925 i++; cur++;
926 }
927 if (outPath)
928 outPath[i] = 0;
929 }
930 else if (outPath) {
931 outPath[0] = '/';
932 outPath[1] = 0;
933 }
934
935 result = 0;
936 }
937
938 return result;
939}
940
941static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
942 int chunkSz, char* start, int len, int dynType, void* heap)
943{
944 byte* newRecvBuf = NULL;
945 int newRecvSz = *recvBufSz + chunkSz;
946 int pos = 0;
947
948 WOLFSSL_MSG("Processing HTTP response");
949#ifdef WOLFIO_DEBUG
950 printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
951#endif
952
953 newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
954 if (newRecvBuf == NULL) {
955 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
956 return MEMORY_E;
957 }
958
959 /* if buffer already exists, then we are growing it */
960 if (*recvBuf) {
961 XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
962 XFREE(*recvBuf, heap, dynType);
963 pos += *recvBufSz;
964 *recvBuf = NULL;
965 }
966
967 /* copy the remainder of the httpBuf into the respBuf */
968 if (len != 0) {
969 XMEMCPY(&newRecvBuf[pos], start, len);
970 pos += len;
971 }
972
973 /* receive the remainder of chunk */
974 while (len < chunkSz) {
975 int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
976 if (rxSz > 0) {
977 len += rxSz;
978 pos += rxSz;
979 }
980 else {
981 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
982 XFREE(newRecvBuf, heap, dynType);
983 return -1;
984 }
985 }
986
987 *recvBuf = newRecvBuf;
988 *recvBufSz = newRecvSz;
989
990 return 0;
991}
992
993int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
994 byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
995{
996 int result = 0;
997 int len = 0;
998 char *start, *end;
999 int respBufSz = 0;
1000 int isChunked = 0, chunkSz = 0;
1001 enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
1002 phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
1003 phr_http_end
1004 } state = phr_init;
1005
1006 *respBuf = NULL;
1007 start = end = NULL;
1008 do {
1009 if (state == phr_get_chunk_data) {
1010 /* get chunk of data */
1011 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
1012 chunkSz, start, len, dynType, heap);
1013
1014 state = (result != 0) ? phr_http_end : phr_get_chunk_len;
1015 end = NULL;
1016 len = 0;
1017 }
1018
1019 /* read data if no \r\n or first time */
1020 if (end == NULL) {
1021 result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
1022 if (result > 0) {
1023 len += result;
1024 start = (char*)httpBuf;
1025 start[len] = 0;
1026 }
1027 else {
1028 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
1029 return -1;
1030 }
1031 }
1032 end = XSTRSTR(start, "\r\n"); /* locate end */
1033
1034 /* handle incomplete rx */
1035 if (end == NULL) {
1036 if (len != 0)
1037 XMEMMOVE(httpBuf, start, len);
1038 start = end = NULL;
1039 }
1040 /* when start is "\r\n" */
1041 else if (end == start) {
1042 /* if waiting for end or need chunk len */
1043 if (state == phr_wait_end || state == phr_get_chunk_len) {
1044 state = (isChunked) ? phr_get_chunk_len : phr_http_end;
1045 len -= 2; start += 2; /* skip \r\n */
1046 }
1047 else {
1048 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
1049 return -1;
1050 }
1051 }
1052 else {
1053 *end = 0; /* null terminate */
1054 len -= (int)(end - start) + 2;
1055 /* adjust len to remove the first line including the /r/n */
1056
1057 #ifdef WOLFIO_DEBUG
1058 printf("HTTP Resp: %s\n", start);
1059 #endif
1060
1061 switch (state) {
1062 case phr_init:
1063 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
1064 start += 9;
1065 if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
1066 WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
1067 return -1;
1068 }
1069 state = phr_http_start;
1070 }
1071 break;
1072 case phr_http_start:
1073 case phr_have_length:
1074 case phr_have_type:
1075 if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
1076 int i;
1077
1078 start += 13;
1079 while (*start == ' ' && *start != '\0') start++;
1080
1081 /* try and match against appStrList */
1082 i = 0;
1083 while (appStrList[i] != NULL) {
1084 if (XSTRNCASECMP(start, appStrList[i],
1085 XSTRLEN(appStrList[i])) == 0) {
1086 break;
1087 }
1088 i++;
1089 }
1090 if (appStrList[i] == NULL) {
1091 WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
1092 return -1;
1093 }
1094 state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
1095 }
1096 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
1097 start += 15;
1098 while (*start == ' ' && *start != '\0') start++;
1099 chunkSz = atoi(start);
1100 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1101 }
1102 else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
1103 start += 18;
1104 while (*start == ' ' && *start != '\0') start++;
1105 if (XSTRNCASECMP(start, "chunked", 7) == 0) {
1106 isChunked = 1;
1107 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1108 }
1109 }
1110 break;
1111 case phr_get_chunk_len:
1112 chunkSz = (int)strtol(start, NULL, 16); /* hex format */
1113 state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
1114 break;
1115 case phr_get_chunk_data:
1116 /* processing for chunk data done above, since \r\n isn't required */
1117 case phr_wait_end:
1118 case phr_http_end:
1119 /* do nothing */
1120 break;
1121 } /* switch (state) */
1122
1123 /* skip to end plus \r\n */
1124 start = end + 2;
1125 }
1126 } while (state != phr_http_end);
1127
1128 if (!isChunked) {
1129 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
1130 start, len, dynType, heap);
1131 }
1132
1133 if (result >= 0) {
1134 result = respBufSz;
1135 }
1136 else {
1137 WOLFSSL_ERROR(result);
1138 }
1139
1140 return result;
1141}
1142
1143int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
1144 const char* path, int pathLen, int reqSz, const char* contentType,
1145 byte* buf, int bufSize)
1146{
1147 word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
1148 char reqSzStr[6];
1149 char* req = (char*)buf;
1150 const char* blankStr = " ";
1151 const char* http11Str = " HTTP/1.1";
1152 const char* hostStr = "\r\nHost: ";
1153 const char* contentLenStr = "\r\nContent-Length: ";
1154 const char* contentTypeStr = "\r\nContent-Type: ";
1155 const char* doubleCrLfStr = "\r\n\r\n";
1156 word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
1157 contentTypeStrLen, doubleCrLfStrLen;
1158
1159 reqTypeLen = (word32)XSTRLEN(reqType);
1160 domainNameLen = (word32)XSTRLEN(domainName);
1161 reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
1162 contentTypeLen = (word32)XSTRLEN(contentType);
1163
1164 blankStrLen = (word32)XSTRLEN(blankStr);
1165 http11StrLen = (word32)XSTRLEN(http11Str);
1166 hostStrLen = (word32)XSTRLEN(hostStr);
1167 contentLenStrLen = (word32)XSTRLEN(contentLenStr);
1168 contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
1169 doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
1170
1171 /* determine max length and check it */
1172 maxLen =
1173 reqTypeLen +
1174 blankStrLen +
1175 pathLen +
1176 http11StrLen +
1177 hostStrLen +
1178 domainNameLen +
1179 contentLenStrLen +
1180 reqSzStrLen +
1181 contentTypeStrLen +
1182 contentTypeLen +
1183 doubleCrLfStrLen +
1184 1 /* null term */;
1185 if (maxLen > (word32)bufSize)
1186 return 0;
1187
1188 XSTRNCPY((char*)buf, reqType, bufSize);
1189 buf += reqTypeLen; bufSize -= reqTypeLen;
1190 XSTRNCPY((char*)buf, blankStr, bufSize);
1191 buf += blankStrLen; bufSize -= blankStrLen;
1192 XSTRNCPY((char*)buf, path, bufSize);
1193 buf += pathLen; bufSize -= pathLen;
1194 XSTRNCPY((char*)buf, http11Str, bufSize);
1195 buf += http11StrLen; bufSize -= http11StrLen;
1196 if (domainNameLen > 0) {
1197 XSTRNCPY((char*)buf, hostStr, bufSize);
1198 buf += hostStrLen; bufSize -= hostStrLen;
1199 XSTRNCPY((char*)buf, domainName, bufSize);
1200 buf += domainNameLen; bufSize -= domainNameLen;
1201 }
1202 if (reqSz > 0 && reqSzStrLen > 0) {
1203 XSTRNCPY((char*)buf, contentLenStr, bufSize);
1204 buf += contentLenStrLen; bufSize -= contentLenStrLen;
1205 XSTRNCPY((char*)buf, reqSzStr, bufSize);
1206 buf += reqSzStrLen; bufSize -= reqSzStrLen;
1207 }
1208 if (contentTypeLen > 0) {
1209 XSTRNCPY((char*)buf, contentTypeStr, bufSize);
1210 buf += contentTypeStrLen; bufSize -= contentTypeStrLen;
1211 XSTRNCPY((char*)buf, contentType, bufSize);
1212 buf += contentTypeLen; bufSize -= contentTypeLen;
1213 }
1214 XSTRNCPY((char*)buf, doubleCrLfStr, bufSize);
1215 buf += doubleCrLfStrLen;
1216
1217#ifdef WOLFIO_DEBUG
1218 printf("HTTP %s: %s", reqType, req);
1219#endif
1220
1221 /* calculate actual length based on original and new pointer */
1222 return (int)((char*)buf - req);
1223}
1224
1225
1226#ifdef HAVE_OCSP
1227
1228int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
1229 int ocspReqSz, byte* buf, int bufSize)
1230{
1231 return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
1232 ocspReqSz, "application/ocsp-request", buf, bufSize);
1233}
1234
1235/* return: >0 OCSP Response Size
1236 * -1 error */
1237int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
1238 byte* httpBuf, int httpBufSz, void* heap)
1239{
1240 const char* appStrList[] = {
1241 "application/ocsp-response",
1242 NULL
1243 };
1244
1245 return wolfIO_HttpProcessResponse(sfd, appStrList,
1246 respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
1247}
1248
1249/* in default wolfSSL callback ctx is the heap pointer */
1250int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
1251 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
1252{
1253 SOCKET_T sfd = 0;
1254 word16 port;
1255 int ret = -1;
1256#ifdef WOLFSSL_SMALL_STACK
1257 char* path;
1258 char* domainName;
1259#else
1260 char path[MAX_URL_ITEM_SIZE];
1261 char domainName[MAX_URL_ITEM_SIZE];
1262#endif
1263
1264#ifdef WOLFSSL_SMALL_STACK
1265 path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1266 if (path == NULL)
1267 return MEMORY_E;
1268
1269 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1270 if (domainName == NULL) {
1271 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1272 return MEMORY_E;
1273 }
1274#endif
1275
1276 if (ocspReqBuf == NULL || ocspReqSz == 0) {
1277 WOLFSSL_MSG("OCSP request is required for lookup");
1278 }
1279 else if (ocspRespBuf == NULL) {
1280 WOLFSSL_MSG("Cannot save OCSP response");
1281 }
1282 else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
1283 WOLFSSL_MSG("Unable to decode OCSP URL");
1284 }
1285 else {
1286 /* Note, the library uses the EmbedOcspRespFree() callback to
1287 * free this buffer. */
1288 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1289 byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
1290
1291 if (httpBuf == NULL) {
1292 WOLFSSL_MSG("Unable to create OCSP response buffer");
1293 }
1294 else {
1295 httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
1296 httpBuf, httpBufSz);
1297
1298 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1299 if ((ret != 0) || ((int)sfd < 0)) {
1300 WOLFSSL_MSG("OCSP Responder connection failed");
1301 }
1302 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
1303 httpBufSz) {
1304 WOLFSSL_MSG("OCSP http request failed");
1305 }
1306 else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
1307 ocspReqSz) {
1308 WOLFSSL_MSG("OCSP ocsp request failed");
1309 }
1310 else {
1311 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
1312 HTTP_SCRATCH_BUFFER_SIZE, ctx);
1313 }
1314
1315 CloseSocket(sfd);
1316 XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
1317 }
1318 }
1319
1320#ifdef WOLFSSL_SMALL_STACK
1321 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1322 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1323#endif
1324
1325 return ret;
1326}
1327
1328/* in default callback ctx is heap hint */
1329void EmbedOcspRespFree(void* ctx, byte *resp)
1330{
1331 if (resp)
1332 XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
1333
1334 (void)ctx;
1335}
1336#endif /* HAVE_OCSP */
1337
1338
1339#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
1340
1341int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
1342 const char* domainName, byte* buf, int bufSize)
1343{
1344 return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
1345 buf, bufSize);
1346}
1347
1348int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
1349 int httpBufSz)
1350{
1351 int result;
1352 byte *respBuf = NULL;
1353
1354 const char* appStrList[] = {
1355 "application/pkix-crl",
1356 "application/x-pkcs7-crl",
1357 NULL
1358 };
1359
1360 result = wolfIO_HttpProcessResponse(sfd, appStrList,
1361 &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
1362 if (result >= 0) {
1363 result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
1364 }
1365 XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
1366
1367 return result;
1368}
1369
1370int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
1371{
1372 SOCKET_T sfd = 0;
1373 word16 port;
1374 int ret = -1;
1375#ifdef WOLFSSL_SMALL_STACK
1376 char* domainName;
1377#else
1378 char domainName[MAX_URL_ITEM_SIZE];
1379#endif
1380
1381#ifdef WOLFSSL_SMALL_STACK
1382 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
1383 DYNAMIC_TYPE_TMP_BUFFER);
1384 if (domainName == NULL) {
1385 return MEMORY_E;
1386 }
1387#endif
1388
1389 if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
1390 WOLFSSL_MSG("Unable to decode CRL URL");
1391 }
1392 else {
1393 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1394 byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap,
1395 DYNAMIC_TYPE_CRL);
1396 if (httpBuf == NULL) {
1397 WOLFSSL_MSG("Unable to create CRL response buffer");
1398 }
1399 else {
1400 httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
1401 httpBuf, httpBufSz);
1402
1403 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1404 if ((ret != 0) || (sfd < 0)) {
1405 WOLFSSL_MSG("CRL connection failed");
1406 }
1407 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
1408 != httpBufSz) {
1409 WOLFSSL_MSG("CRL http get failed");
1410 }
1411 else {
1412 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
1413 HTTP_SCRATCH_BUFFER_SIZE);
1414 }
1415
1416 CloseSocket(sfd);
1417 XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
1418 }
1419 }
1420
1421#ifdef WOLFSSL_SMALL_STACK
1422 XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1423#endif
1424
1425 return ret;
1426}
1427#endif /* HAVE_CRL && HAVE_CRL_IO */
1428
1429#endif /* HAVE_HTTP_CLIENT */
1430
1431
1432
1433WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
1434{
1435 if (ctx != NULL) {
1436 ctx->CBIORecv = CBIORecv;
1437 #ifdef OPENSSL_EXTRA
1438 ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
1439 #endif
1440 }
1441}
1442
1443
1444WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
1445{
1446 if (ctx != NULL) {
1447 ctx->CBIOSend = CBIOSend;
1448 #ifdef OPENSSL_EXTRA
1449 ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
1450 #endif
1451 }
1452}
1453
1454
1455WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
1456{
1457 ssl->IOCB_ReadCtx = rctx;
1458}
1459
1460
1461WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
1462{
1463 ssl->IOCB_WriteCtx = wctx;
1464}
1465
1466
1467WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
1468{
1469 if (ssl)
1470 return ssl->IOCB_ReadCtx;
1471
1472 return NULL;
1473}
1474
1475
1476WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
1477{
1478 if (ssl)
1479 return ssl->IOCB_WriteCtx;
1480
1481 return NULL;
1482}
1483
1484
1485WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
1486{
1487 ssl->rflags = flags;
1488}
1489
1490
1491WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1492{
1493 ssl->wflags = flags;
1494}
1495
1496
1497#ifdef WOLFSSL_DTLS
1498
1499WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1500{
1501 ctx->CBIOCookie = cb;
1502}
1503
1504
1505WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1506{
1507 ssl->IOCB_CookieCtx = ctx;
1508}
1509
1510
1511WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1512{
1513 if (ssl)
1514 return ssl->IOCB_CookieCtx;
1515
1516 return NULL;
1517}
1518
1519#ifdef WOLFSSL_SESSION_EXPORT
1520
1521WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
1522{
1523 ctx->CBGetPeer = cb;
1524}
1525
1526
1527WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
1528{
1529 ctx->CBSetPeer = cb;
1530}
1531
1532#endif /* WOLFSSL_SESSION_EXPORT */
1533#endif /* WOLFSSL_DTLS */
1534
1535
1536#ifdef HAVE_NETX
1537
1538/* The NetX receive callback
1539 * return : bytes read, or error
1540 */
1541int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1542{
1543 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1544 ULONG left;
1545 ULONG total;
1546 ULONG copied = 0;
1547 UINT status;
1548
1549 (void)ssl;
1550
1551 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1552 WOLFSSL_MSG("NetX Recv NULL parameters");
1553 return WOLFSSL_CBIO_ERR_GENERAL;
1554 }
1555
1556 if (nxCtx->nxPacket == NULL) {
1557 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1558 nxCtx->nxWait);
1559 if (status != NX_SUCCESS) {
1560 WOLFSSL_MSG("NetX Recv receive error");
1561 return WOLFSSL_CBIO_ERR_GENERAL;
1562 }
1563 }
1564
1565 if (nxCtx->nxPacket) {
1566 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1567 if (status != NX_SUCCESS) {
1568 WOLFSSL_MSG("NetX Recv length get error");
1569 return WOLFSSL_CBIO_ERR_GENERAL;
1570 }
1571
1572 left = total - nxCtx->nxOffset;
1573 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1574 buf, sz, &copied);
1575 if (status != NX_SUCCESS) {
1576 WOLFSSL_MSG("NetX Recv data extract offset error");
1577 return WOLFSSL_CBIO_ERR_GENERAL;
1578 }
1579
1580 nxCtx->nxOffset += copied;
1581
1582 if (copied == left) {
1583 WOLFSSL_MSG("NetX Recv Drained packet");
1584 nx_packet_release(nxCtx->nxPacket);
1585 nxCtx->nxPacket = NULL;
1586 nxCtx->nxOffset = 0;
1587 }
1588 }
1589
1590 return copied;
1591}
1592
1593
1594/* The NetX send callback
1595 * return : bytes sent, or error
1596 */
1597int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1598{
1599 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1600 NX_PACKET* packet;
1601 NX_PACKET_POOL* pool; /* shorthand */
1602 UINT status;
1603
1604 (void)ssl;
1605
1606 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1607 WOLFSSL_MSG("NetX Send NULL parameters");
1608 return WOLFSSL_CBIO_ERR_GENERAL;
1609 }
1610
1611 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1612 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1613 nxCtx->nxWait);
1614 if (status != NX_SUCCESS) {
1615 WOLFSSL_MSG("NetX Send packet alloc error");
1616 return WOLFSSL_CBIO_ERR_GENERAL;
1617 }
1618
1619 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1620 if (status != NX_SUCCESS) {
1621 nx_packet_release(packet);
1622 WOLFSSL_MSG("NetX Send data append error");
1623 return WOLFSSL_CBIO_ERR_GENERAL;
1624 }
1625
1626 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1627 if (status != NX_SUCCESS) {
1628 nx_packet_release(packet);
1629 WOLFSSL_MSG("NetX Send socket send error");
1630 return WOLFSSL_CBIO_ERR_GENERAL;
1631 }
1632
1633 return sz;
1634}
1635
1636
1637/* like set_fd, but for default NetX context */
1638void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1639{
1640 if (ssl) {
1641 ssl->nxCtx.nxSocket = nxSocket;
1642 ssl->nxCtx.nxWait = waitOption;
1643 }
1644}
1645
1646#endif /* HAVE_NETX */
1647
1648
1649#ifdef MICRIUM
1650
1651/* Micrium uTCP/IP port, using the NetSock API
1652 * TCP and UDP are currently supported with the callbacks below.
1653 *
1654 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
1655 * and EmbedSetPeer() callbacks implemented.
1656 *
1657 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
1658 * callback implemented.
1659 *
1660 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
1661 * callback implemented.
1662 */
1663
1664/* The Micrium uTCP/IP send callback
1665 * return : bytes sent, or error
1666 */
1667int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
1668{
1669 NET_SOCK_ID sd = *(int*)ctx;
1670 NET_SOCK_RTN_CODE ret;
1671 NET_ERR err;
1672
1673 ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
1674 if (ret < 0) {
1675 WOLFSSL_MSG("Embed Send error");
1676
1677 if (err == NET_ERR_TX) {
1678 WOLFSSL_MSG("\tWould block");
1679 return WOLFSSL_CBIO_ERR_WANT_WRITE;
1680
1681 } else {
1682 WOLFSSL_MSG("\tGeneral error");
1683 return WOLFSSL_CBIO_ERR_GENERAL;
1684 }
1685 }
1686
1687 return ret;
1688}
1689
1690/* The Micrium uTCP/IP receive callback
1691 * return : nb bytes read, or error
1692 */
1693int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1694{
1695 NET_SOCK_ID sd = *(int*)ctx;
1696 NET_SOCK_RTN_CODE ret;
1697 NET_ERR err;
1698
1699#ifdef WOLFSSL_DTLS
1700 {
1701 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
1702 if (wolfSSL_dtls(ssl)
1703 && !wolfSSL_dtls_get_using_nonblock(ssl)
1704 && dtls_timeout != 0) {
1705 /* needs timeout in milliseconds */
1706 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
1707 if (err != NET_SOCK_ERR_NONE) {
1708 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
1709 }
1710 }
1711 }
1712#endif
1713
1714 ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
1715 if (ret < 0) {
1716 WOLFSSL_MSG("Embed Receive error");
1717
1718 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
1719 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
1720 if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
1721 WOLFSSL_MSG("\tWould block");
1722 return WOLFSSL_CBIO_ERR_WANT_READ;
1723 }
1724 else {
1725 WOLFSSL_MSG("\tSocket timeout");
1726 return WOLFSSL_CBIO_ERR_TIMEOUT;
1727 }
1728
1729 } else if (err == NET_SOCK_ERR_CLOSED) {
1730 WOLFSSL_MSG("Embed receive connection closed");
1731 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
1732
1733 } else {
1734 WOLFSSL_MSG("\tGeneral error");
1735 return WOLFSSL_CBIO_ERR_GENERAL;
1736 }
1737 }
1738
1739 return ret;
1740}
1741
1742/* The Micrium uTCP/IP receivefrom callback
1743 * return : nb bytes read, or error
1744 */
1745int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1746{
1747 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
1748 NET_SOCK_ID sd = dtlsCtx->rfd;
1749 NET_SOCK_ADDR peer;
1750 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
1751 NET_SOCK_RTN_CODE ret;
1752 NET_ERR err;
1753 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
1754
1755 WOLFSSL_ENTER("MicriumReceiveFrom()");
1756
1757 if (ssl->options.handShakeDone)
1758 dtls_timeout = 0;
1759
1760 if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
1761 /* needs timeout in milliseconds */
1762 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
1763 if (err != NET_SOCK_ERR_NONE) {
1764 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
1765 }
1766 }
1767
1768 ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
1769 0, 0, 0, &err);
1770 if (ret < 0) {
1771 WOLFSSL_MSG("Embed Receive From error");
1772
1773 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
1774 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
1775 if (wolfSSL_dtls_get_using_nonblock(ssl)) {
1776 WOLFSSL_MSG("\tWould block");
1777 return WOLFSSL_CBIO_ERR_WANT_READ;
1778 }
1779 else {
1780 WOLFSSL_MSG("\tSocket timeout");
1781 return WOLFSSL_CBIO_ERR_TIMEOUT;
1782 }
1783 } else {
1784 WOLFSSL_MSG("\tGeneral error");
1785 return WOLFSSL_CBIO_ERR_GENERAL;
1786 }
1787 }
1788 else {
1789 if (dtlsCtx->peer.sz > 0
1790 && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
1791 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
1792 WOLFSSL_MSG("\tIgnored packet from invalid peer");
1793 return WOLFSSL_CBIO_ERR_WANT_READ;
1794 }
1795 }
1796
1797 return ret;
1798}
1799
1800/* The Micrium uTCP/IP sendto callback
1801 * return : nb bytes sent, or error
1802 */
1803int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1804{
1805 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
1806 NET_SOCK_ID sd = dtlsCtx->wfd;
1807 NET_SOCK_RTN_CODE ret;
1808 int len = sz;
1809 NET_ERR err;
1810
1811 WOLFSSL_ENTER("MicriumSendTo()");
1812
1813 ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags,
1814 (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
1815 (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
1816 &err);
1817 if (err < 0) {
1818 WOLFSSL_MSG("Embed Send To error");
1819
1820 if (err == NET_ERR_TX) {
1821 WOLFSSL_MSG("\tWould block");
1822 return WOLFSSL_CBIO_ERR_WANT_WRITE;
1823
1824 } else {
1825 WOLFSSL_MSG("\tGeneral error");
1826 return WOLFSSL_CBIO_ERR_GENERAL;
1827 }
1828 }
1829
1830 return ret;
1831}
1832
1833/* Micrium DTLS Generate Cookie callback
1834 * return : number of bytes copied into buf, or error
1835 */
1836int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
1837{
1838 NET_SOCK_ADDR peer;
1839 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
1840 byte digest[WC_SHA_DIGEST_SIZE];
1841 int ret = 0;
1842
1843 (void)ctx;
1844
1845 XMEMSET(&peer, 0, sizeof(peer));
1846 if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
1847 (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
1848 WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
1849 return GEN_COOKIE_E;
1850 }
1851
1852 ret = wc_ShaHash((byte*)&peer, peerSz, digest);
1853 if (ret != 0)
1854 return ret;
1855
1856 if (sz > WC_SHA_DIGEST_SIZE)
1857 sz = WC_SHA_DIGEST_SIZE;
1858 XMEMCPY(buf, digest, sz);
1859
1860 return sz;
1861}
1862
1863#endif /* MICRIUM */
1864
1865#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP)
1866
1867#include <os/os_error.h>
1868#include <os/os_mbuf.h>
1869#include <os/os_mempool.h>
1870
1871#define MB_NAME "wolfssl_mb"
1872
1873typedef struct Mynewt_Ctx {
1874 struct mn_socket *mnSocket; /* send/recv socket handler */
1875 struct mn_sockaddr_in mnSockAddrIn; /* socket address */
1876 struct os_mbuf *mnPacket; /* incoming packet handle
1877 for short reads */
1878 int reading; /* reading flag */
1879
1880 /* private */
1881 void *mnMemBuffer; /* memory buffer for mempool */
1882 struct os_mempool mnMempool; /* mempool */
1883 struct os_mbuf_pool mnMbufpool; /* mbuf pool */
1884} Mynewt_Ctx;
1885
1886void mynewt_ctx_clear(void *ctx) {
1887 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
1888 if(!mynewt_ctx) return;
1889
1890 if(mynewt_ctx->mnPacket) {
1891 os_mbuf_free_chain(mynewt_ctx->mnPacket);
1892 mynewt_ctx->mnPacket = NULL;
1893 }
1894 os_mempool_clear(&mynewt_ctx->mnMempool);
1895 XFREE(mynewt_ctx->mnMemBuffer, 0, 0);
1896 XFREE(mynewt_ctx, 0, 0);
1897}
1898
1899/* return Mynewt_Ctx instance */
1900void* mynewt_ctx_new() {
1901 int rc = 0;
1902 Mynewt_Ctx *mynewt_ctx = NULL;
1903 int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT);
1904 int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE);
1905 int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size);
1906
1907 mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx),
1908 NULL, DYNAMIC_TYPE_TMP_BUFFER);
1909 if(!mynewt_ctx) return NULL;
1910
1911 XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx));
1912 mynewt_ctx->mnMemBuffer = XMALLOC(mempool_bytes, 0, 0);
1913 if(!mynewt_ctx->mnMemBuffer) {
1914 mynewt_ctx_clear((void*)mynewt_ctx);
1915 return NULL;
1916 }
1917
1918 rc = os_mempool_init(&mynewt_ctx->mnMempool,
1919 mem_buf_count, mem_buf_size,
1920 mynewt_ctx->mnMemBuffer, MB_NAME);
1921 if(rc != 0) {
1922 mynewt_ctx_clear((void*)mynewt_ctx);
1923 return NULL;
1924 }
1925 rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool,
1926 mem_buf_count, mem_buf_size);
1927 if(rc != 0) {
1928 mynewt_ctx_clear((void*)mynewt_ctx);
1929 return NULL;
1930 }
1931
1932 return mynewt_ctx;
1933}
1934
1935static void mynewt_sock_writable(void *arg, int err);
1936static void mynewt_sock_readable(void *arg, int err);
1937static const union mn_socket_cb mynewt_sock_cbs = {
1938 .socket.writable = mynewt_sock_writable,
1939 .socket.readable = mynewt_sock_readable,
1940};
1941static void mynewt_sock_writable(void *arg, int err)
1942{
1943 /* do nothing */
1944}
1945static void mynewt_sock_readable(void *arg, int err)
1946{
1947 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg;
1948 if (err && mynewt_ctx->reading) {
1949 mynewt_ctx->reading = 0;
1950 }
1951}
1952
1953/* The Mynewt receive callback
1954 * return : bytes read, or error
1955 */
1956int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1957{
1958 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
1959 int rc = 0;
1960 struct mn_sockaddr_in from;
1961 struct os_mbuf *m;
1962 int read_sz = 0;
1963 uint16_t total;
1964
1965 if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) {
1966 WOLFSSL_MSG("Mynewt Recv NULL parameters");
1967 return WOLFSSL_CBIO_ERR_GENERAL;
1968 }
1969
1970 if(mynewt_ctx->mnPacket == NULL) {
1971 mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0);
1972 if(mynewt_ctx->mnPacket == NULL) {
1973 return MEMORY_E;
1974 }
1975
1976 mynewt_ctx->reading = 1;
1977 while(mynewt_ctx->reading && rc == 0) {
1978 rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from);
1979 if(rc == MN_ECONNABORTED) {
1980 rc = 0;
1981 mynewt_ctx->reading = 0;
1982 break;
1983 }
1984 if (!(rc == 0 || rc == MN_EAGAIN)) {
1985 WOLFSSL_MSG("Mynewt Recv receive error");
1986 mynewt_ctx->reading = 0;
1987 break;
1988 }
1989 if(rc == 0) {
1990 int len = OS_MBUF_PKTLEN(m);
1991 if(len == 0) {
1992 break;
1993 }
1994 rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len);
1995 if(rc != 0) {
1996 WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error");
1997 break;
1998 }
1999 os_mbuf_free_chain(m);
2000 m = NULL;
2001 } else if(rc == MN_EAGAIN) {
2002 /* continue to until reading all of packet data. */
2003 rc = 0;
2004 break;
2005 }
2006 }
2007 if(rc != 0) {
2008 mynewt_ctx->reading = 0;
2009 os_mbuf_free_chain(mynewt_ctx->mnPacket);
2010 mynewt_ctx->mnPacket = NULL;
2011 return rc;
2012 }
2013 }
2014
2015 if(mynewt_ctx->mnPacket) {
2016 total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket);
2017 read_sz = (total >= sz)? sz : total;
2018
2019 os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf);
2020 os_mbuf_adj(mynewt_ctx->mnPacket, read_sz);
2021
2022 if (read_sz == total) {
2023 WOLFSSL_MSG("Mynewt Recv Drained packet");
2024 os_mbuf_free_chain(mynewt_ctx->mnPacket);
2025 mynewt_ctx->mnPacket = NULL;
2026 }
2027 }
2028
2029 return read_sz;
2030}
2031
2032/* The Mynewt send callback
2033 * return : bytes sent, or error
2034 */
2035int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
2036{
2037 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx;
2038 int rc = 0;
2039 struct os_mbuf *m = NULL;
2040 int write_sz = 0;
2041 m = os_msys_get_pkthdr(sz, 0);
2042 if (!m) {
2043 WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error");
2044 return WOLFSSL_CBIO_ERR_GENERAL;
2045 }
2046 rc = os_mbuf_copyinto(m, 0, buf, sz);
2047 if (rc != 0) {
2048 WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error");
2049 os_mbuf_free_chain(m);
2050 return rc;
2051 }
2052 rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn);
2053 if(rc != 0) {
2054 WOLFSSL_MSG("Mynewt Send mn_sendto error");
2055 os_mbuf_free_chain(m);
2056 return rc;
2057 }
2058 write_sz = sz;
2059 return write_sz;
2060}
2061
2062/* like set_fd, but for default NetX context */
2063void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn)
2064{
2065 if (ssl && ssl->mnCtx) {
2066 Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx;
2067 mynewt_ctx->mnSocket = mnSocket;
2068 memcpy(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in));
2069 mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs);
2070 }
2071}
2072
2073#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */
2074
2075#ifdef WOLFSSL_UIP
2076#include <uip.h>
2077#include <stdio.h>
2078
2079/* uIP TCP/IP port, using the native tcp/udp socket api.
2080 * TCP and UDP are currently supported with the callbacks below.
2081 *
2082 */
2083/* The uIP tcp send callback
2084 * return : bytes sent, or error
2085 */
2086int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
2087{
2088 uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
2089 int ret;
2090 unsigned int max_sendlen;
2091 int total_written = 0;
2092 (void)ssl;
2093 do {
2094 unsigned int bytes_left = sz - total_written;
2095 max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp);
2096 if (bytes_left > max_sendlen) {
2097 printf("Send limited by buffer\r\n");
2098 bytes_left = max_sendlen;
2099 }
2100 if (bytes_left == 0) {
2101 printf("Buffer full!\r\n");
2102 break;
2103 }
2104 ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left);
2105 if (ret <= 0)
2106 break;
2107 total_written += ret;
2108 } while(total_written < sz);
2109 return total_written;
2110}
2111
2112int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx)
2113{
2114 uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx;
2115 int ret = 0;
2116 (void)ssl;
2117 ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port );
2118 if (ret <= 0)
2119 return 0;
2120 return ret;
2121}
2122
2123/* The uIP uTCP/IP receive callback
2124 * return : nb bytes read, or error
2125 */
2126int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx)
2127{
2128 uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx;
2129 if (!ctx || !ctx->ssl_rx_databuf)
2130 return -1;
2131 (void)ssl;
2132 if (ctx->ssl_rb_len > 0) {
2133 if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off)
2134 sz = ctx->ssl_rb_len - ctx->ssl_rb_off;
2135 XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz);
2136 ctx->ssl_rb_off += sz;
2137 if (ctx->ssl_rb_off >= ctx->ssl_rb_len) {
2138 ctx->ssl_rb_len = 0;
2139 ctx->ssl_rb_off = 0;
2140 }
2141 return sz;
2142 } else {
2143 return WOLFSSL_CBIO_ERR_WANT_READ;
2144 }
2145}
2146
2147/* uIP DTLS Generate Cookie callback
2148 * return : number of bytes copied into buf, or error
2149 */
2150int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx)
2151{
2152 uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)ctx;
2153 byte token[32];
2154 byte digest[WC_SHA_DIGEST_SIZE];
2155 int ret = 0;
2156 XMEMSET(token, 0, sizeof(token));
2157 XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t));
2158 XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16));
2159 ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest);
2160 if (ret != 0)
2161 return ret;
2162 if (sz > WC_SHA_DIGEST_SIZE)
2163 sz = WC_SHA_DIGEST_SIZE;
2164 XMEMCPY(buf, digest, sz);
2165 return sz;
2166}
2167
2168#endif /* WOLFSSL_UIP */
2169
2170#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.