source: asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/src/wolfio.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 50.0 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_SetIORecv and wolfSSL_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 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 INLINE int 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 USE_WOLFSSL_IO
106
107/* The receive embedded callback
108 * return : nb bytes read, or error
109 */
110int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
111{
112 int sd = *(int*)ctx;
113 int recvd;
114
115#ifdef WOLFSSL_DTLS
116 {
117 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
118 if (wolfSSL_dtls(ssl)
119 && !wolfSSL_get_using_nonblock(ssl)
120 && dtls_timeout != 0) {
121 #ifdef USE_WINDOWS_API
122 DWORD timeout = dtls_timeout * 1000;
123 #else
124 struct timeval timeout;
125 XMEMSET(&timeout, 0, sizeof(timeout));
126 timeout.tv_sec = dtls_timeout;
127 #endif
128 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
129 sizeof(timeout)) != 0) {
130 WOLFSSL_MSG("setsockopt rcvtimeo failed");
131 }
132 }
133 }
134#endif
135
136 recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
137 if (recvd < 0) {
138 int err = LastError();
139 WOLFSSL_MSG("Embed Receive error");
140
141 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
142 if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) {
143 WOLFSSL_MSG("\tWould block");
144 return WOLFSSL_CBIO_ERR_WANT_READ;
145 }
146 else {
147 WOLFSSL_MSG("\tSocket timeout");
148 return WOLFSSL_CBIO_ERR_TIMEOUT;
149 }
150 }
151 else if (err == SOCKET_ECONNRESET) {
152 WOLFSSL_MSG("\tConnection reset");
153 return WOLFSSL_CBIO_ERR_CONN_RST;
154 }
155 else if (err == SOCKET_EINTR) {
156 WOLFSSL_MSG("\tSocket interrupted");
157 return WOLFSSL_CBIO_ERR_ISR;
158 }
159 else if (err == SOCKET_ECONNREFUSED) {
160 WOLFSSL_MSG("\tConnection refused");
161 return WOLFSSL_CBIO_ERR_WANT_READ;
162 }
163 else if (err == SOCKET_ECONNABORTED) {
164 WOLFSSL_MSG("\tConnection aborted");
165 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
166 }
167 else {
168 WOLFSSL_MSG("\tGeneral error");
169 return WOLFSSL_CBIO_ERR_GENERAL;
170 }
171 }
172 else if (recvd == 0) {
173 WOLFSSL_MSG("Embed receive connection closed");
174 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
175 }
176
177 return recvd;
178}
179
180/* The send embedded callback
181 * return : nb bytes sent, or error
182 */
183int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
184{
185 int sd = *(int*)ctx;
186 int sent;
187
188 sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
189 if (sent < 0) {
190 int err = LastError();
191 WOLFSSL_MSG("Embed Send error");
192
193 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
194 WOLFSSL_MSG("\tWould Block");
195 return WOLFSSL_CBIO_ERR_WANT_WRITE;
196 }
197 else if (err == SOCKET_ECONNRESET) {
198 WOLFSSL_MSG("\tConnection reset");
199 return WOLFSSL_CBIO_ERR_CONN_RST;
200 }
201 else if (err == SOCKET_EINTR) {
202 WOLFSSL_MSG("\tSocket interrupted");
203 return WOLFSSL_CBIO_ERR_ISR;
204 }
205 else if (err == SOCKET_EPIPE) {
206 WOLFSSL_MSG("\tSocket EPIPE");
207 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
208 }
209 else {
210 WOLFSSL_MSG("\tGeneral error");
211 return WOLFSSL_CBIO_ERR_GENERAL;
212 }
213 }
214
215 return sent;
216}
217
218
219#ifdef WOLFSSL_DTLS
220
221#include <wolfssl/wolfcrypt/sha.h>
222
223#define SENDTO_FUNCTION sendto
224#define RECVFROM_FUNCTION recvfrom
225
226
227/* The receive embedded callback
228 * return : nb bytes read, or error
229 */
230int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
231{
232 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
233 int recvd;
234 int err;
235 int sd = dtlsCtx->rfd;
236 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
237 SOCKADDR_S peer;
238 XSOCKLENT peerSz = sizeof(peer);
239
240 WOLFSSL_ENTER("EmbedReceiveFrom()");
241
242 if (ssl->options.handShakeDone)
243 dtls_timeout = 0;
244
245 if (!wolfSSL_get_using_nonblock(ssl)) {
246 #ifdef USE_WINDOWS_API
247 DWORD timeout = dtls_timeout * 1000;
248 #else
249 struct timeval timeout;
250 XMEMSET(&timeout, 0, sizeof(timeout));
251 timeout.tv_sec = dtls_timeout;
252 #endif
253 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
254 sizeof(timeout)) != 0) {
255 WOLFSSL_MSG("setsockopt rcvtimeo failed");
256 }
257 }
258
259 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
260 (SOCKADDR*)&peer, &peerSz);
261
262 recvd = TranslateReturnCode(recvd, sd);
263
264 if (recvd < 0) {
265 err = LastError();
266 WOLFSSL_MSG("Embed Receive From error");
267
268 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
269 if (wolfSSL_get_using_nonblock(ssl)) {
270 WOLFSSL_MSG("\tWould block");
271 return WOLFSSL_CBIO_ERR_WANT_READ;
272 }
273 else {
274 WOLFSSL_MSG("\tSocket timeout");
275 return WOLFSSL_CBIO_ERR_TIMEOUT;
276 }
277 }
278 else if (err == SOCKET_ECONNRESET) {
279 WOLFSSL_MSG("\tConnection reset");
280 return WOLFSSL_CBIO_ERR_CONN_RST;
281 }
282 else if (err == SOCKET_EINTR) {
283 WOLFSSL_MSG("\tSocket interrupted");
284 return WOLFSSL_CBIO_ERR_ISR;
285 }
286 else if (err == SOCKET_ECONNREFUSED) {
287 WOLFSSL_MSG("\tConnection refused");
288 return WOLFSSL_CBIO_ERR_WANT_READ;
289 }
290 else {
291 WOLFSSL_MSG("\tGeneral error");
292 return WOLFSSL_CBIO_ERR_GENERAL;
293 }
294 }
295 else {
296 if (dtlsCtx->peer.sz > 0
297 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
298 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
299 WOLFSSL_MSG(" Ignored packet from invalid peer");
300 return WOLFSSL_CBIO_ERR_WANT_READ;
301 }
302 }
303
304 return recvd;
305}
306
307
308/* The send embedded callback
309 * return : nb bytes sent, or error
310 */
311int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
312{
313 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
314 int sd = dtlsCtx->wfd;
315 int sent;
316 int len = sz;
317 int err;
318
319 WOLFSSL_ENTER("EmbedSendTo()");
320
321 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
322 (const SOCKADDR*)dtlsCtx->peer.sa,
323 dtlsCtx->peer.sz);
324
325 sent = TranslateReturnCode(sent, sd);
326
327 if (sent < 0) {
328 err = LastError();
329 WOLFSSL_MSG("Embed Send To error");
330
331 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
332 WOLFSSL_MSG("\tWould Block");
333 return WOLFSSL_CBIO_ERR_WANT_WRITE;
334 }
335 else if (err == SOCKET_ECONNRESET) {
336 WOLFSSL_MSG("\tConnection reset");
337 return WOLFSSL_CBIO_ERR_CONN_RST;
338 }
339 else if (err == SOCKET_EINTR) {
340 WOLFSSL_MSG("\tSocket interrupted");
341 return WOLFSSL_CBIO_ERR_ISR;
342 }
343 else if (err == SOCKET_EPIPE) {
344 WOLFSSL_MSG("\tSocket EPIPE");
345 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
346 }
347 else {
348 WOLFSSL_MSG("\tGeneral error");
349 return WOLFSSL_CBIO_ERR_GENERAL;
350 }
351 }
352
353 return sent;
354}
355
356
357#ifdef WOLFSSL_MULTICAST
358
359/* The alternate receive embedded callback for Multicast
360 * return : nb bytes read, or error
361 */
362int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
363{
364 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
365 int recvd;
366 int err;
367 int sd = dtlsCtx->rfd;
368
369 WOLFSSL_ENTER("EmbedReceiveFromMcast()");
370
371 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
372
373 recvd = TranslateReturnCode(recvd, sd);
374
375 if (recvd < 0) {
376 err = LastError();
377 WOLFSSL_MSG("Embed Receive From error");
378
379 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
380 if (wolfSSL_get_using_nonblock(ssl)) {
381 WOLFSSL_MSG("\tWould block");
382 return WOLFSSL_CBIO_ERR_WANT_READ;
383 }
384 else {
385 WOLFSSL_MSG("\tSocket timeout");
386 return WOLFSSL_CBIO_ERR_TIMEOUT;
387 }
388 }
389 else if (err == SOCKET_ECONNRESET) {
390 WOLFSSL_MSG("\tConnection reset");
391 return WOLFSSL_CBIO_ERR_CONN_RST;
392 }
393 else if (err == SOCKET_EINTR) {
394 WOLFSSL_MSG("\tSocket interrupted");
395 return WOLFSSL_CBIO_ERR_ISR;
396 }
397 else if (err == SOCKET_ECONNREFUSED) {
398 WOLFSSL_MSG("\tConnection refused");
399 return WOLFSSL_CBIO_ERR_WANT_READ;
400 }
401 else {
402 WOLFSSL_MSG("\tGeneral error");
403 return WOLFSSL_CBIO_ERR_GENERAL;
404 }
405 }
406
407 return recvd;
408}
409#endif /* WOLFSSL_MULTICAST */
410
411
412/* The DTLS Generate Cookie callback
413 * return : number of bytes copied into buf, or error
414 */
415int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
416{
417 int sd = ssl->wfd;
418 SOCKADDR_S peer;
419 XSOCKLENT peerSz = sizeof(peer);
420 byte digest[WC_SHA256_DIGEST_SIZE];
421 int ret = 0;
422
423 (void)ctx;
424
425 XMEMSET(&peer, 0, sizeof(peer));
426 if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
427 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
428 return GEN_COOKIE_E;
429 }
430
431 ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
432 if (ret != 0)
433 return ret;
434
435 if (sz > WC_SHA256_DIGEST_SIZE)
436 sz = WC_SHA256_DIGEST_SIZE;
437 XMEMCPY(buf, digest, sz);
438
439 return sz;
440}
441
442#ifdef WOLFSSL_SESSION_EXPORT
443
444 /* get the peer information in human readable form (ip, port, family)
445 * default function assumes BSD sockets
446 * can be overriden with wolfSSL_CTX_SetIOGetPeer
447 */
448 int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
449 unsigned short* port, int* fam)
450 {
451 SOCKADDR_S peer;
452 word32 peerSz;
453 int ret;
454
455 if (ssl == NULL || ip == NULL || ipSz == NULL ||
456 port == NULL || fam == NULL) {
457 return BAD_FUNC_ARG;
458 }
459
460 /* get peer information stored in ssl struct */
461 peerSz = sizeof(SOCKADDR_S);
462 if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
463 != WOLFSSL_SUCCESS) {
464 return ret;
465 }
466
467 /* extract family, ip, and port */
468 *fam = ((SOCKADDR_S*)&peer)->ss_family;
469 switch (*fam) {
470 case WOLFSSL_IP4:
471 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
472 ip, *ipSz) == NULL) {
473 WOLFSSL_MSG("XINET_NTOP error");
474 return SOCKET_ERROR_E;
475 }
476 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
477 break;
478
479 case WOLFSSL_IP6:
480 #ifdef WOLFSSL_IPV6
481 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
482 ip, *ipSz) == NULL) {
483 WOLFSSL_MSG("XINET_NTOP error");
484 return SOCKET_ERROR_E;
485 }
486 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
487 #endif /* WOLFSSL_IPV6 */
488 break;
489
490 default:
491 WOLFSSL_MSG("Unknown family type");
492 return SOCKET_ERROR_E;
493 }
494 ip[*ipSz - 1] = '\0'; /* make sure has terminator */
495 *ipSz = (word16)XSTRLEN(ip);
496
497 return WOLFSSL_SUCCESS;
498 }
499
500 /* set the peer information in human readable form (ip, port, family)
501 * default function assumes BSD sockets
502 * can be overriden with wolfSSL_CTX_SetIOSetPeer
503 */
504 int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
505 unsigned short port, int fam)
506 {
507 int ret;
508 SOCKADDR_S addr;
509
510 /* sanity checks on arguments */
511 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
512 return BAD_FUNC_ARG;
513 }
514
515 addr.ss_family = fam;
516 switch (addr.ss_family) {
517 case WOLFSSL_IP4:
518 if (XINET_PTON(addr.ss_family, ip,
519 &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
520 WOLFSSL_MSG("XINET_PTON error");
521 return SOCKET_ERROR_E;
522 }
523 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
524
525 /* peer sa is free'd in SSL_ResourceFree */
526 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
527 sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
528 WOLFSSL_MSG("Import DTLS peer info error");
529 return ret;
530 }
531 break;
532
533 case WOLFSSL_IP6:
534 #ifdef WOLFSSL_IPV6
535 if (XINET_PTON(addr.ss_family, ip,
536 &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
537 WOLFSSL_MSG("XINET_PTON error");
538 return SOCKET_ERROR_E;
539 }
540 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
541
542 /* peer sa is free'd in SSL_ResourceFree */
543 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
544 sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
545 WOLFSSL_MSG("Import DTLS peer info error");
546 return ret;
547 }
548 #endif /* WOLFSSL_IPV6 */
549 break;
550
551 default:
552 WOLFSSL_MSG("Unknown address family");
553 return BUFFER_E;
554 }
555
556 return WOLFSSL_SUCCESS;
557 }
558#endif /* WOLFSSL_SESSION_EXPORT */
559#endif /* WOLFSSL_DTLS */
560
561
562int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
563{
564 int recvd;
565
566 recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
567 recvd = TranslateReturnCode(recvd, sd);
568
569 return recvd;
570}
571
572int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
573{
574 int sent;
575
576 sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
577 sent = TranslateReturnCode(sent, sd);
578
579 return sent;
580}
581
582#endif /* USE_WOLFSSL_IO */
583
584
585#ifdef HAVE_HTTP_CLIENT
586
587#ifndef HAVE_IO_TIMEOUT
588 #define io_timeout_sec 0
589#else
590
591 #ifndef DEFAULT_TIMEOUT_SEC
592 #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
593 #endif
594
595 static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
596
597 void wolfIO_SetTimeout(int to_sec)
598 {
599 io_timeout_sec = to_sec;
600 }
601
602 int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
603 {
604 int ret = 0;
605
606 #ifdef USE_WINDOWS_API
607 unsigned long blocking = non_blocking;
608 ret = ioctlsocket(sockfd, FIONBIO, &blocking);
609 if (ret == SOCKET_ERROR)
610 ret = -1;
611 #else
612 ret = fcntl(sockfd, F_GETFL, 0);
613 if (ret >= 0) {
614 if (non_blocking)
615 ret |= O_NONBLOCK;
616 else
617 ret &= ~O_NONBLOCK;
618 ret = fcntl(sockfd, F_SETFL, ret);
619 }
620 #endif
621 if (ret < 0) {
622 WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
623 }
624
625 return ret;
626 }
627
628 #ifdef _MSC_VER
629 /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */
630 #pragma warning(disable: 4204)
631 #endif
632 int wolfIO_Select(SOCKET_T sockfd, int to_sec)
633 {
634 fd_set fds;
635 SOCKET_T nfds = sockfd + 1;
636 struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
637 int ret;
638
639 FD_ZERO(&fds);
640 FD_SET(sockfd, &fds);
641
642 ret = select(nfds, &fds, &fds, NULL, &timeout);
643 if (ret == 0) {
644 #ifdef DEBUG_HTTP
645 printf("Timeout: %d\n", ret);
646 #endif
647 return HTTP_TIMEOUT;
648 }
649 else if (ret > 0) {
650 if (FD_ISSET(sockfd, &fds))
651 return 0;
652 }
653 return SOCKET_ERROR_E;
654 }
655#endif /* HAVE_IO_TIMEOUT */
656
657static int wolfIO_Word16ToString(char* d, word16 number)
658{
659 int i = 0;
660 word16 order = 10000;
661 word16 digit;
662
663 if (d == NULL)
664 return i;
665
666 if (number == 0)
667 d[i++] = '0';
668 else {
669 while (order) {
670 digit = number / order;
671 if (i > 0 || digit != 0)
672 d[i++] = (char)digit + '0';
673 if (digit != 0)
674 number %= digit * order;
675
676 order = (order > 1) ? order / 10 : 0;
677 }
678 }
679 d[i] = 0; /* null terminate */
680
681 return i;
682}
683
684int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
685{
686#ifdef HAVE_SOCKADDR
687 int ret = 0;
688 SOCKADDR_S addr;
689 int sockaddr_len = sizeof(SOCKADDR_IN);
690#ifdef HAVE_GETADDRINFO
691 ADDRINFO hints;
692 ADDRINFO* answer = NULL;
693 char strPort[6];
694#else
695 HOSTENT* entry;
696 SOCKADDR_IN *sin;
697#endif
698
699 XMEMSET(&addr, 0, sizeof(addr));
700
701#ifdef WOLFIO_DEBUG
702 printf("TCP Connect: %s:%d\n", ip, port);
703#endif
704
705#ifdef HAVE_GETADDRINFO
706 XMEMSET(&hints, 0, sizeof(hints));
707 hints.ai_family = AF_UNSPEC;
708 hints.ai_socktype = SOCK_STREAM;
709 hints.ai_protocol = IPPROTO_TCP;
710
711 if (wolfIO_Word16ToString(strPort, port) == 0) {
712 WOLFSSL_MSG("invalid port number for responder");
713 return -1;
714 }
715
716 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
717 WOLFSSL_MSG("no addr info for responder");
718 return -1;
719 }
720
721 sockaddr_len = answer->ai_addrlen;
722 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
723 freeaddrinfo(answer);
724#else
725 entry = gethostbyname(ip);
726 sin = (SOCKADDR_IN *)&addr;
727
728 if (entry) {
729 sin->sin_family = AF_INET;
730 sin->sin_port = XHTONS(port);
731 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
732 }
733 else {
734 WOLFSSL_MSG("no addr info for responder");
735 return -1;
736 }
737#endif
738
739 *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
740
741#ifdef USE_WINDOWS_API
742 if (*sockfd == INVALID_SOCKET) {
743 WOLFSSL_MSG("bad socket fd, out of fds?");
744 return -1;
745 }
746#else
747 if (*sockfd < 0) {
748 WOLFSSL_MSG("bad socket fd, out of fds?");
749 return -1;
750 }
751#endif
752
753#ifdef HAVE_IO_TIMEOUT
754 /* if timeout value provided then set socket non-blocking */
755 if (to_sec > 0) {
756 wolfIO_SetBlockingMode(*sockfd, 1);
757 }
758#else
759 (void)to_sec;
760#endif
761
762 ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
763#ifdef HAVE_IO_TIMEOUT
764 if (ret != 0) {
765 if ((errno == EINPROGRESS) && (to_sec > 0)) {
766 /* wait for connect to complete */
767 ret = wolfIO_Select(*sockfd, to_sec);
768
769 /* restore blocking mode */
770 wolfIO_SetBlockingMode(*sockfd, 0);
771 }
772 }
773#endif
774 if (ret != 0) {
775 WOLFSSL_MSG("Responder tcp connect failed");
776 return -1;
777 }
778 return ret;
779#else
780 (void)sockfd;
781 (void)ip;
782 (void)port;
783 (void)to_sec;
784 return -1;
785#endif /* HAVE_SOCKADDR */
786}
787
788#ifndef HTTP_SCRATCH_BUFFER_SIZE
789 #define HTTP_SCRATCH_BUFFER_SIZE 512
790#endif
791#ifndef MAX_URL_ITEM_SIZE
792 #define MAX_URL_ITEM_SIZE 80
793#endif
794
795int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
796 word16* outPort)
797{
798 int result = -1;
799
800 if (url == NULL || urlSz == 0) {
801 if (outName)
802 *outName = 0;
803 if (outPath)
804 *outPath = 0;
805 if (outPort)
806 *outPort = 0;
807 }
808 else {
809 int i, cur;
810
811 /* need to break the url down into scheme, address, and port */
812 /* "http://example.com:8080/" */
813 /* "http://[::1]:443/" */
814 if (XSTRNCMP(url, "http://", 7) == 0) {
815 cur = 7;
816 } else cur = 0;
817
818 i = 0;
819 if (url[cur] == '[') {
820 cur++;
821 /* copy until ']' */
822 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
823 if (outName)
824 outName[i] = url[cur];
825 i++; cur++;
826 }
827 cur++; /* skip ']' */
828 }
829 else {
830 while (url[cur] != 0 && url[cur] != ':' &&
831 url[cur] != '/' && cur < urlSz) {
832 if (outName)
833 outName[i] = url[cur];
834 i++; cur++;
835 }
836 }
837 if (outName)
838 outName[i] = 0;
839 /* Need to pick out the path after the domain name */
840
841 if (cur < urlSz && url[cur] == ':') {
842 char port[6];
843 int j;
844 word32 bigPort = 0;
845 i = 0;
846 cur++;
847 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
848 i < 6) {
849 port[i++] = url[cur++];
850 }
851
852 for (j = 0; j < i; j++) {
853 if (port[j] < '0' || port[j] > '9') return -1;
854 bigPort = (bigPort * 10) + (port[j] - '0');
855 }
856 if (outPort)
857 *outPort = (word16)bigPort;
858 }
859 else if (outPort)
860 *outPort = 80;
861
862
863 if (cur < urlSz && url[cur] == '/') {
864 i = 0;
865 while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
866 if (outPath)
867 outPath[i] = url[cur];
868 i++; cur++;
869 }
870 if (outPath)
871 outPath[i] = 0;
872 }
873 else if (outPath) {
874 outPath[0] = '/';
875 outPath[1] = 0;
876 }
877
878 result = 0;
879 }
880
881 return result;
882}
883
884static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
885 int chunkSz, char* start, int len, int dynType, void* heap)
886{
887 byte* newRecvBuf = NULL;
888 int newRecvSz = *recvBufSz + chunkSz;
889 int pos = 0;
890
891 WOLFSSL_MSG("Processing HTTP response");
892#ifdef WOLFIO_DEBUG
893 printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
894#endif
895
896 newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
897 if (newRecvBuf == NULL) {
898 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
899 return MEMORY_E;
900 }
901
902 /* if buffer already exists, then we are growing it */
903 if (*recvBuf) {
904 XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
905 XFREE(*recvBuf, heap, dynType);
906 pos += *recvBufSz;
907 *recvBuf = NULL;
908 }
909
910 /* copy the remainder of the httpBuf into the respBuf */
911 if (len != 0) {
912 XMEMCPY(&newRecvBuf[pos], start, len);
913 pos += len;
914 }
915
916 /* receive the remainder of chunk */
917 while (len < chunkSz) {
918 int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
919 if (rxSz > 0) {
920 len += rxSz;
921 pos += rxSz;
922 }
923 else {
924 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
925 XFREE(newRecvBuf, heap, dynType);
926 return -1;
927 }
928 }
929
930 *recvBuf = newRecvBuf;
931 *recvBufSz = newRecvSz;
932
933 return 0;
934}
935
936int wolfIO_HttpProcessResponse(int sfd, const char* appStr,
937 byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
938{
939 int result = 0;
940 int len = 0;
941 char *start, *end;
942 int respBufSz = 0;
943 int isChunked = 0, chunkSz = 0;
944 enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
945 phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
946 phr_http_end
947 } state = phr_init;
948
949 *respBuf = NULL;
950 start = end = NULL;
951 do {
952 if (state == phr_get_chunk_data) {
953 /* get chunk of data */
954 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
955 chunkSz, start, len, dynType, heap);
956
957 state = (result != 0) ? phr_http_end : phr_get_chunk_len;
958 end = NULL;
959 len = 0;
960 }
961
962 /* read data if no \r\n or first time */
963 if (end == NULL) {
964 result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
965 if (result > 0) {
966 len += result;
967 start = (char*)httpBuf;
968 start[len] = 0;
969 }
970 else {
971 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
972 return -1;
973 }
974 }
975 end = XSTRSTR(start, "\r\n"); /* locate end */
976
977 /* handle incomplete rx */
978 if (end == NULL) {
979 if (len != 0)
980 XMEMMOVE(httpBuf, start, len);
981 start = end = NULL;
982 }
983 /* when start is "\r\n" */
984 else if (end == start) {
985 /* if waiting for end or need chunk len */
986 if (state == phr_wait_end || state == phr_get_chunk_len) {
987 state = (isChunked) ? phr_get_chunk_len : phr_http_end;
988 len -= 2; start += 2; /* skip \r\n */
989 }
990 else {
991 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
992 return -1;
993 }
994 }
995 else {
996 *end = 0; /* null terminate */
997 len -= (int)(end - start) + 2;
998 /* adjust len to remove the first line including the /r/n */
999
1000 #ifdef WOLFIO_DEBUG
1001 printf("HTTP Resp: %s\n", start);
1002 #endif
1003
1004 switch (state) {
1005 case phr_init:
1006 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
1007 start += 9;
1008 if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
1009 WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
1010 return -1;
1011 }
1012 state = phr_http_start;
1013 }
1014 break;
1015 case phr_http_start:
1016 case phr_have_length:
1017 case phr_have_type:
1018 if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
1019 start += 13;
1020 while (*start == ' ' && *start != '\0') start++;
1021 if (XSTRNCASECMP(start, appStr, XSTRLEN(appStr)) != 0) {
1022 WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
1023 return -1;
1024 }
1025 state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
1026 }
1027 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
1028 start += 15;
1029 while (*start == ' ' && *start != '\0') start++;
1030 chunkSz = atoi(start);
1031 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1032 }
1033 else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
1034 start += 18;
1035 while (*start == ' ' && *start != '\0') start++;
1036 if (XSTRNCASECMP(start, "chunked", 7) == 0) {
1037 isChunked = 1;
1038 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
1039 }
1040 }
1041 break;
1042 case phr_get_chunk_len:
1043 chunkSz = (int)strtol(start, NULL, 16); /* hex format */
1044 state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
1045 break;
1046 case phr_get_chunk_data:
1047 /* processing for chunk data done above, since \r\n isn't required */
1048 case phr_wait_end:
1049 case phr_http_end:
1050 /* do nothing */
1051 break;
1052 } /* switch (state) */
1053
1054 /* skip to end plus \r\n */
1055 start = end + 2;
1056 }
1057 } while (state != phr_http_end);
1058
1059 if (!isChunked) {
1060 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
1061 start, len, dynType, heap);
1062 }
1063
1064 if (result >= 0) {
1065 result = respBufSz;
1066 }
1067 else {
1068 WOLFSSL_ERROR(result);
1069 }
1070
1071 return result;
1072}
1073
1074int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
1075 const char* path, int pathLen, int reqSz, const char* contentType,
1076 byte* buf, int bufSize)
1077{
1078 word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
1079 char reqSzStr[6];
1080 char* req = (char*)buf;
1081 const char* blankStr = " ";
1082 const char* http11Str = " HTTP/1.1";
1083 const char* hostStr = "\r\nHost: ";
1084 const char* contentLenStr = "\r\nContent-Length: ";
1085 const char* contentTypeStr = "\r\nContent-Type: ";
1086 const char* doubleCrLfStr = "\r\n\r\n";
1087 word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
1088 contentTypeStrLen, doubleCrLfStrLen;
1089
1090 reqTypeLen = (word32)XSTRLEN(reqType);
1091 domainNameLen = (word32)XSTRLEN(domainName);
1092 reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
1093 contentTypeLen = (word32)XSTRLEN(contentType);
1094
1095 blankStrLen = (word32)XSTRLEN(blankStr);
1096 http11StrLen = (word32)XSTRLEN(http11Str);
1097 hostStrLen = (word32)XSTRLEN(hostStr);
1098 contentLenStrLen = (word32)XSTRLEN(contentLenStr);
1099 contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
1100 doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
1101
1102 /* determine max length and check it */
1103 maxLen =
1104 reqTypeLen +
1105 blankStrLen +
1106 pathLen +
1107 http11StrLen +
1108 hostStrLen +
1109 domainNameLen +
1110 contentLenStrLen +
1111 reqSzStrLen +
1112 contentTypeStrLen +
1113 contentTypeLen +
1114 doubleCrLfStrLen +
1115 1 /* null term */;
1116 if (maxLen > (word32)bufSize)
1117 return 0;
1118
1119 XSTRNCPY((char*)buf, reqType, reqTypeLen);
1120 buf += reqTypeLen;
1121 XSTRNCPY((char*)buf, blankStr, blankStrLen+1);
1122 buf += blankStrLen;
1123 XSTRNCPY((char*)buf, path, pathLen);
1124 buf += pathLen;
1125 XSTRNCPY((char*)buf, http11Str, http11StrLen+1);
1126 buf += http11StrLen;
1127 if (domainNameLen > 0) {
1128 XSTRNCPY((char*)buf, hostStr, hostStrLen+1);
1129 buf += hostStrLen;
1130 XSTRNCPY((char*)buf, domainName, domainNameLen);
1131 buf += domainNameLen;
1132 }
1133 if (reqSz > 0 && reqSzStrLen > 0) {
1134 XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1);
1135 buf += contentLenStrLen;
1136 XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen);
1137 buf += reqSzStrLen;
1138 }
1139 if (contentTypeLen > 0) {
1140 XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1);
1141 buf += contentTypeStrLen;
1142 XSTRNCPY((char*)buf, contentType, contentTypeLen);
1143 buf += contentTypeLen;
1144 }
1145 XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1);
1146 buf += doubleCrLfStrLen;
1147
1148#ifdef WOLFIO_DEBUG
1149 printf("HTTP %s: %s", reqType, req);
1150#endif
1151
1152 /* calculate actual length based on original and new pointer */
1153 return (int)((char*)buf - req);
1154}
1155
1156
1157#ifdef HAVE_OCSP
1158
1159int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
1160 int ocspReqSz, byte* buf, int bufSize)
1161{
1162 return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
1163 ocspReqSz, "application/ocsp-request", buf, bufSize);
1164}
1165
1166/* return: >0 OCSP Response Size
1167 * -1 error */
1168int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
1169 byte* httpBuf, int httpBufSz, void* heap)
1170{
1171 return wolfIO_HttpProcessResponse(sfd, "application/ocsp-response",
1172 respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
1173}
1174
1175/* in default wolfSSL callback ctx is the heap pointer */
1176int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
1177 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
1178{
1179 SOCKET_T sfd = 0;
1180 word16 port;
1181 int ret = -1;
1182#ifdef WOLFSSL_SMALL_STACK
1183 char* path;
1184 char* domainName;
1185#else
1186 char path[MAX_URL_ITEM_SIZE];
1187 char domainName[MAX_URL_ITEM_SIZE];
1188#endif
1189
1190#ifdef WOLFSSL_SMALL_STACK
1191 path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1192 if (path == NULL)
1193 return MEMORY_E;
1194
1195 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1196 if (domainName == NULL) {
1197 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1198 return MEMORY_E;
1199 }
1200#endif
1201
1202 if (ocspReqBuf == NULL || ocspReqSz == 0) {
1203 WOLFSSL_MSG("OCSP request is required for lookup");
1204 }
1205 else if (ocspRespBuf == NULL) {
1206 WOLFSSL_MSG("Cannot save OCSP response");
1207 }
1208 else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
1209 WOLFSSL_MSG("Unable to decode OCSP URL");
1210 }
1211 else {
1212 /* Note, the library uses the EmbedOcspRespFree() callback to
1213 * free this buffer. */
1214 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1215 byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
1216
1217 if (httpBuf == NULL) {
1218 WOLFSSL_MSG("Unable to create OCSP response buffer");
1219 }
1220 else {
1221 httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
1222 httpBuf, httpBufSz);
1223
1224 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1225 if ((ret != 0) || (sfd < 0)) {
1226 WOLFSSL_MSG("OCSP Responder connection failed");
1227 }
1228 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
1229 httpBufSz) {
1230 WOLFSSL_MSG("OCSP http request failed");
1231 }
1232 else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
1233 ocspReqSz) {
1234 WOLFSSL_MSG("OCSP ocsp request failed");
1235 }
1236 else {
1237 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
1238 HTTP_SCRATCH_BUFFER_SIZE, ctx);
1239 }
1240
1241 close(sfd);
1242 XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
1243 }
1244 }
1245
1246#ifdef WOLFSSL_SMALL_STACK
1247 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1248 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1249#endif
1250
1251 return ret;
1252}
1253
1254/* in default callback ctx is heap hint */
1255void EmbedOcspRespFree(void* ctx, byte *resp)
1256{
1257 if (resp)
1258 XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
1259
1260 (void)ctx;
1261}
1262#endif /* HAVE_OCSP */
1263
1264
1265#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
1266
1267int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
1268 const char* domainName, byte* buf, int bufSize)
1269{
1270 return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
1271 buf, bufSize);
1272}
1273
1274int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
1275 int httpBufSz)
1276{
1277 int result;
1278 byte *respBuf = NULL;
1279
1280 result = wolfIO_HttpProcessResponse(sfd, "application/pkix-crl",
1281 &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
1282 if (result >= 0) {
1283 result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
1284 }
1285 XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
1286
1287 return result;
1288}
1289
1290int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
1291{
1292 SOCKET_T sfd = 0;
1293 word16 port;
1294 int ret = -1;
1295#ifdef WOLFSSL_SMALL_STACK
1296 char* domainName;
1297#else
1298 char domainName[MAX_URL_ITEM_SIZE];
1299#endif
1300
1301#ifdef WOLFSSL_SMALL_STACK
1302 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
1303 DYNAMIC_TYPE_TMP_BUFFER);
1304 if (domainName == NULL) {
1305 return MEMORY_E;
1306 }
1307#endif
1308
1309 if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
1310 WOLFSSL_MSG("Unable to decode CRL URL");
1311 }
1312 else {
1313 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1314 byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap,
1315 DYNAMIC_TYPE_CRL);
1316 if (httpBuf == NULL) {
1317 WOLFSSL_MSG("Unable to create CRL response buffer");
1318 }
1319 else {
1320 httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
1321 httpBuf, httpBufSz);
1322
1323 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1324 if ((ret != 0) || (sfd < 0)) {
1325 WOLFSSL_MSG("CRL connection failed");
1326 }
1327 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
1328 != httpBufSz) {
1329 WOLFSSL_MSG("CRL http get failed");
1330 }
1331 else {
1332 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
1333 HTTP_SCRATCH_BUFFER_SIZE);
1334 }
1335
1336 close(sfd);
1337 XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
1338 }
1339 }
1340
1341#ifdef WOLFSSL_SMALL_STACK
1342 XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1343#endif
1344
1345 return ret;
1346}
1347#endif /* HAVE_CRL && HAVE_CRL_IO */
1348
1349#endif /* HAVE_HTTP_CLIENT */
1350
1351
1352
1353WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
1354{
1355 ctx->CBIORecv = CBIORecv;
1356}
1357
1358
1359WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
1360{
1361 ctx->CBIOSend = CBIOSend;
1362}
1363
1364
1365WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
1366{
1367 ssl->IOCB_ReadCtx = rctx;
1368}
1369
1370
1371WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
1372{
1373 ssl->IOCB_WriteCtx = wctx;
1374}
1375
1376
1377WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
1378{
1379 if (ssl)
1380 return ssl->IOCB_ReadCtx;
1381
1382 return NULL;
1383}
1384
1385
1386WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
1387{
1388 if (ssl)
1389 return ssl->IOCB_WriteCtx;
1390
1391 return NULL;
1392}
1393
1394
1395WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
1396{
1397 ssl->rflags = flags;
1398}
1399
1400
1401WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1402{
1403 ssl->wflags = flags;
1404}
1405
1406
1407#ifdef WOLFSSL_DTLS
1408
1409WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1410{
1411 ctx->CBIOCookie = cb;
1412}
1413
1414
1415WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1416{
1417 ssl->IOCB_CookieCtx = ctx;
1418}
1419
1420
1421WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1422{
1423 if (ssl)
1424 return ssl->IOCB_CookieCtx;
1425
1426 return NULL;
1427}
1428
1429#ifdef WOLFSSL_SESSION_EXPORT
1430
1431WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
1432{
1433 ctx->CBGetPeer = cb;
1434}
1435
1436
1437WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
1438{
1439 ctx->CBSetPeer = cb;
1440}
1441
1442#endif /* WOLFSSL_SESSION_EXPORT */
1443#endif /* WOLFSSL_DTLS */
1444
1445
1446#ifdef HAVE_NETX
1447
1448/* The NetX receive callback
1449 * return : bytes read, or error
1450 */
1451int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1452{
1453 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1454 ULONG left;
1455 ULONG total;
1456 ULONG copied = 0;
1457 UINT status;
1458
1459 (void)ssl;
1460
1461 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1462 WOLFSSL_MSG("NetX Recv NULL parameters");
1463 return WOLFSSL_CBIO_ERR_GENERAL;
1464 }
1465
1466 if (nxCtx->nxPacket == NULL) {
1467 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1468 nxCtx->nxWait);
1469 if (status != NX_SUCCESS) {
1470 WOLFSSL_MSG("NetX Recv receive error");
1471 return WOLFSSL_CBIO_ERR_GENERAL;
1472 }
1473 }
1474
1475 if (nxCtx->nxPacket) {
1476 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1477 if (status != NX_SUCCESS) {
1478 WOLFSSL_MSG("NetX Recv length get error");
1479 return WOLFSSL_CBIO_ERR_GENERAL;
1480 }
1481
1482 left = total - nxCtx->nxOffset;
1483 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1484 buf, sz, &copied);
1485 if (status != NX_SUCCESS) {
1486 WOLFSSL_MSG("NetX Recv data extract offset error");
1487 return WOLFSSL_CBIO_ERR_GENERAL;
1488 }
1489
1490 nxCtx->nxOffset += copied;
1491
1492 if (copied == left) {
1493 WOLFSSL_MSG("NetX Recv Drained packet");
1494 nx_packet_release(nxCtx->nxPacket);
1495 nxCtx->nxPacket = NULL;
1496 nxCtx->nxOffset = 0;
1497 }
1498 }
1499
1500 return copied;
1501}
1502
1503
1504/* The NetX send callback
1505 * return : bytes sent, or error
1506 */
1507int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1508{
1509 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1510 NX_PACKET* packet;
1511 NX_PACKET_POOL* pool; /* shorthand */
1512 UINT status;
1513
1514 (void)ssl;
1515
1516 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1517 WOLFSSL_MSG("NetX Send NULL parameters");
1518 return WOLFSSL_CBIO_ERR_GENERAL;
1519 }
1520
1521 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1522 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1523 nxCtx->nxWait);
1524 if (status != NX_SUCCESS) {
1525 WOLFSSL_MSG("NetX Send packet alloc error");
1526 return WOLFSSL_CBIO_ERR_GENERAL;
1527 }
1528
1529 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1530 if (status != NX_SUCCESS) {
1531 nx_packet_release(packet);
1532 WOLFSSL_MSG("NetX Send data append error");
1533 return WOLFSSL_CBIO_ERR_GENERAL;
1534 }
1535
1536 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1537 if (status != NX_SUCCESS) {
1538 nx_packet_release(packet);
1539 WOLFSSL_MSG("NetX Send socket send error");
1540 return WOLFSSL_CBIO_ERR_GENERAL;
1541 }
1542
1543 return sz;
1544}
1545
1546
1547/* like set_fd, but for default NetX context */
1548void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1549{
1550 if (ssl) {
1551 ssl->nxCtx.nxSocket = nxSocket;
1552 ssl->nxCtx.nxWait = waitOption;
1553 }
1554}
1555
1556#endif /* HAVE_NETX */
1557
1558
1559#ifdef MICRIUM
1560
1561/* Micrium uTCP/IP port, using the NetSock API
1562 * TCP and UDP are currently supported with the callbacks below.
1563 *
1564 * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
1565 * and EmbedSetPeer() callbacks implemented.
1566 *
1567 * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
1568 * callback implemented.
1569 *
1570 * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
1571 * callback implemented.
1572 */
1573
1574/* The Micrium uTCP/IP send callback
1575 * return : bytes sent, or error
1576 */
1577int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
1578{
1579 NET_SOCK_ID sd = *(int*)ctx;
1580 NET_SOCK_RTN_CODE ret;
1581 NET_ERR err;
1582
1583 ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
1584 if (ret < 0) {
1585 WOLFSSL_MSG("Embed Send error");
1586
1587 if (err == NET_ERR_TX) {
1588 WOLFSSL_MSG("\tWould block");
1589 return WOLFSSL_CBIO_ERR_WANT_WRITE;
1590
1591 } else {
1592 WOLFSSL_MSG("\tGeneral error");
1593 return WOLFSSL_CBIO_ERR_GENERAL;
1594 }
1595 }
1596
1597 return ret;
1598}
1599
1600/* The Micrium uTCP/IP receive callback
1601 * return : nb bytes read, or error
1602 */
1603int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1604{
1605 NET_SOCK_ID sd = *(int*)ctx;
1606 NET_SOCK_RTN_CODE ret;
1607 NET_ERR err;
1608
1609#ifdef WOLFSSL_DTLS
1610 {
1611 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
1612 if (wolfSSL_dtls(ssl)
1613 && !wolfSSL_get_using_nonblock(ssl)
1614 && dtls_timeout != 0) {
1615 /* needs timeout in milliseconds */
1616 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
1617 if (err != NET_SOCK_ERR_NONE) {
1618 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
1619 }
1620 }
1621 }
1622#endif
1623
1624 ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
1625 if (ret < 0) {
1626 WOLFSSL_MSG("Embed Receive error");
1627
1628 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
1629 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
1630 if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) {
1631 WOLFSSL_MSG("\tWould block");
1632 return WOLFSSL_CBIO_ERR_WANT_READ;
1633 }
1634 else {
1635 WOLFSSL_MSG("\tSocket timeout");
1636 return WOLFSSL_CBIO_ERR_TIMEOUT;
1637 }
1638
1639 } else if (err == NET_SOCK_ERR_CLOSED) {
1640 WOLFSSL_MSG("Embed receive connection closed");
1641 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
1642
1643 } else {
1644 WOLFSSL_MSG("\tGeneral error");
1645 return WOLFSSL_CBIO_ERR_GENERAL;
1646 }
1647 }
1648
1649 return ret;
1650}
1651
1652/* The Micrium uTCP/IP receivefrom callback
1653 * return : nb bytes read, or error
1654 */
1655int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1656{
1657 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
1658 NET_SOCK_ID sd = dtlsCtx->rfd;
1659 NET_SOCK_ADDR peer;
1660 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
1661 NET_SOCK_RTN_CODE ret;
1662 NET_ERR err;
1663 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
1664
1665 WOLFSSL_ENTER("MicriumReceiveFrom()");
1666
1667 if (ssl->options.handShakeDone)
1668 dtls_timeout = 0;
1669
1670 if (!wolfSSL_get_using_nonblock(ssl)) {
1671 /* needs timeout in milliseconds */
1672 NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
1673 if (err != NET_SOCK_ERR_NONE) {
1674 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
1675 }
1676 }
1677
1678 ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
1679 0, 0, 0, &err);
1680 if (ret < 0) {
1681 WOLFSSL_MSG("Embed Receive From error");
1682
1683 if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
1684 err == NET_ERR_FAULT_LOCK_ACQUIRE) {
1685 if (wolfSSL_get_using_nonblock(ssl)) {
1686 WOLFSSL_MSG("\tWould block");
1687 return WOLFSSL_CBIO_ERR_WANT_READ;
1688 }
1689 else {
1690 WOLFSSL_MSG("\tSocket timeout");
1691 return WOLFSSL_CBIO_ERR_TIMEOUT;
1692 }
1693 } else {
1694 WOLFSSL_MSG("\tGeneral error");
1695 return WOLFSSL_CBIO_ERR_GENERAL;
1696 }
1697 }
1698 else {
1699 if (dtlsCtx->peer.sz > 0
1700 && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
1701 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
1702 WOLFSSL_MSG("\tIgnored packet from invalid peer");
1703 return WOLFSSL_CBIO_ERR_WANT_READ;
1704 }
1705 }
1706
1707 return ret;
1708}
1709
1710/* The Micrium uTCP/IP sendto callback
1711 * return : nb bytes sent, or error
1712 */
1713int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1714{
1715 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
1716 NET_SOCK_ID sd = dtlsCtx->wfd;
1717 NET_SOCK_RTN_CODE ret;
1718 int len = sz;
1719 NET_ERR err;
1720
1721 WOLFSSL_ENTER("MicriumSendTo()");
1722
1723 ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags,
1724 (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
1725 (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
1726 &err);
1727 if (err < 0) {
1728 WOLFSSL_MSG("Embed Send To error");
1729
1730 if (err == NET_ERR_TX) {
1731 WOLFSSL_MSG("\tWould block");
1732 return WOLFSSL_CBIO_ERR_WANT_WRITE;
1733
1734 } else {
1735 WOLFSSL_MSG("\tGeneral error");
1736 return WOLFSSL_CBIO_ERR_GENERAL;
1737 }
1738 }
1739
1740 return ret;
1741}
1742
1743/* Micrium DTLS Generate Cookie callback
1744 * return : number of bytes copied into buf, or error
1745 */
1746int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
1747{
1748 NET_SOCK_ADDR peer;
1749 NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
1750 byte digest[WC_SHA_DIGEST_SIZE];
1751 int ret = 0;
1752
1753 (void)ctx;
1754
1755 XMEMSET(&peer, 0, sizeof(peer));
1756 if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
1757 (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
1758 WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
1759 return GEN_COOKIE_E;
1760 }
1761
1762 ret = wc_ShaHash((byte*)&peer, peerSz, digest);
1763 if (ret != 0)
1764 return ret;
1765
1766 if (sz > WC_SHA_DIGEST_SIZE)
1767 sz = WC_SHA_DIGEST_SIZE;
1768 XMEMCPY(buf, digest, sz);
1769
1770 return sz;
1771}
1772
1773#endif /* MICRIUM */
1774
1775#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.