source: asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/src/io.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: 42.4 KB
Line 
1/* io.c
2 *
3 * Copyright (C) 2006-2016 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/io.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("\tIgnored 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/* The DTLS Generate Cookie callback
358 * return : number of bytes copied into buf, or error
359 */
360int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
361{
362 int sd = ssl->wfd;
363 SOCKADDR_S peer;
364 XSOCKLENT peerSz = sizeof(peer);
365 byte digest[SHA_DIGEST_SIZE];
366 int ret = 0;
367
368 (void)ctx;
369
370 XMEMSET(&peer, 0, sizeof(peer));
371 if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
372 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
373 return GEN_COOKIE_E;
374 }
375
376 ret = wc_ShaHash((byte*)&peer, peerSz, digest);
377 if (ret != 0)
378 return ret;
379
380 if (sz > SHA_DIGEST_SIZE)
381 sz = SHA_DIGEST_SIZE;
382 XMEMCPY(buf, digest, sz);
383
384 return sz;
385}
386
387#ifdef WOLFSSL_SESSION_EXPORT
388
389 /* get the peer information in human readable form (ip, port, family)
390 * default function assumes BSD sockets
391 * can be overriden with wolfSSL_CTX_SetIOGetPeer
392 */
393 int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
394 unsigned short* port, int* fam)
395 {
396 SOCKADDR_S peer;
397 word32 peerSz;
398 int ret;
399
400 if (ssl == NULL || ip == NULL || ipSz == NULL ||
401 port == NULL || fam == NULL) {
402 return BAD_FUNC_ARG;
403 }
404
405 /* get peer information stored in ssl struct */
406 peerSz = sizeof(SOCKADDR_S);
407 if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
408 != SSL_SUCCESS) {
409 return ret;
410 }
411
412 /* extract family, ip, and port */
413 *fam = ((SOCKADDR_S*)&peer)->ss_family;
414 switch (*fam) {
415 case WOLFSSL_IP4:
416 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
417 ip, *ipSz) == NULL) {
418 WOLFSSL_MSG("XINET_NTOP error");
419 return SOCKET_ERROR_E;
420 }
421 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
422 break;
423
424 case WOLFSSL_IP6:
425 #ifdef WOLFSSL_IPV6
426 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
427 ip, *ipSz) == NULL) {
428 WOLFSSL_MSG("XINET_NTOP error");
429 return SOCKET_ERROR_E;
430 }
431 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
432 #endif /* WOLFSSL_IPV6 */
433 break;
434
435 default:
436 WOLFSSL_MSG("Unknown family type");
437 return SOCKET_ERROR_E;
438 }
439 ip[*ipSz - 1] = '\0'; /* make sure has terminator */
440 *ipSz = (word16)XSTRLEN(ip);
441
442 return SSL_SUCCESS;
443 }
444
445 /* set the peer information in human readable form (ip, port, family)
446 * default function assumes BSD sockets
447 * can be overriden with wolfSSL_CTX_SetIOSetPeer
448 */
449 int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
450 unsigned short port, int fam)
451 {
452 int ret;
453 SOCKADDR_S addr;
454
455 /* sanity checks on arguments */
456 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
457 return BAD_FUNC_ARG;
458 }
459
460 addr.ss_family = fam;
461 switch (addr.ss_family) {
462 case WOLFSSL_IP4:
463 if (XINET_PTON(addr.ss_family, ip,
464 &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
465 WOLFSSL_MSG("XINET_PTON error");
466 return SOCKET_ERROR_E;
467 }
468 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
469
470 /* peer sa is free'd in SSL_ResourceFree */
471 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
472 sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) {
473 WOLFSSL_MSG("Import DTLS peer info error");
474 return ret;
475 }
476 break;
477
478 case WOLFSSL_IP6:
479 #ifdef WOLFSSL_IPV6
480 if (XINET_PTON(addr.ss_family, ip,
481 &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
482 WOLFSSL_MSG("XINET_PTON error");
483 return SOCKET_ERROR_E;
484 }
485 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
486
487 /* peer sa is free'd in SSL_ResourceFree */
488 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
489 sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) {
490 WOLFSSL_MSG("Import DTLS peer info error");
491 return ret;
492 }
493 #endif /* WOLFSSL_IPV6 */
494 break;
495
496 default:
497 WOLFSSL_MSG("Unknown address family");
498 return BUFFER_E;
499 }
500
501 return SSL_SUCCESS;
502 }
503#endif /* WOLFSSL_SESSION_EXPORT */
504#endif /* WOLFSSL_DTLS */
505
506
507int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
508{
509 int recvd;
510
511 recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
512 recvd = TranslateReturnCode(recvd, sd);
513
514 return recvd;
515}
516
517int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
518{
519 int sent;
520 int len = sz;
521
522 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, wrFlags);
523 sent = TranslateReturnCode(sent, sd);
524
525 return sent;
526}
527
528#endif /* USE_WOLFSSL_IO */
529
530
531#ifdef HAVE_HTTP_CLIENT
532
533#ifndef HAVE_IO_TIMEOUT
534 #define io_timeout_sec 0
535#else
536
537 #ifndef DEFAULT_TIMEOUT_SEC
538 #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
539 #endif
540
541 static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
542
543 void wolfIO_SetTimeout(int to_sec)
544 {
545 io_timeout_sec = to_sec;
546 }
547
548 int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
549 {
550 int ret = 0;
551
552 #ifdef USE_WINDOWS_API
553 unsigned long blocking = non_blocking;
554 ret = ioctlsocket(sockfd, FIONBIO, &blocking);
555 if (ret == SOCKET_ERROR)
556 ret = -1;
557 #else
558 ret = fcntl(sockfd, F_GETFL, 0);
559 if (ret >= 0) {
560 if (non_blocking)
561 ret |= O_NONBLOCK;
562 else
563 ret &= ~O_NONBLOCK;
564 ret = fcntl(sockfd, F_SETFL, ret);
565 }
566 #endif
567 if (ret < 0) {
568 WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
569 }
570
571 return ret;
572 }
573
574 #ifdef _MSC_VER
575 /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */
576 #pragma warning(disable: 4204)
577 #endif
578 int wolfIO_Select(SOCKET_T sockfd, int to_sec)
579 {
580 fd_set fds;
581 SOCKET_T nfds = sockfd + 1;
582 struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
583 int ret;
584
585 FD_ZERO(&fds);
586 FD_SET(sockfd, &fds);
587
588 ret = select(nfds, &fds, &fds, NULL, &timeout);
589 if (ret == 0) {
590 #ifdef DEBUG_HTTP
591 printf("Timeout: %d\n", ret);
592 #endif
593 return HTTP_TIMEOUT;
594 }
595 else if (ret > 0) {
596 if (FD_ISSET(sockfd, &fds))
597 return 0;
598 }
599 return SOCKET_ERROR_E;
600 }
601#endif /* HAVE_IO_TIMEOUT */
602
603static int wolfIO_Word16ToString(char* d, word16 number)
604{
605 int i = 0;
606 word16 order = 10000;
607 word16 digit;
608
609 if (d == NULL)
610 return i;
611
612 if (number == 0)
613 d[i++] = '0';
614 else {
615 while (order) {
616 digit = number / order;
617 if (i > 0 || digit != 0)
618 d[i++] = (char)digit + '0';
619 if (digit != 0)
620 number %= digit * order;
621
622 order = (order > 1) ? order / 10 : 0;
623 }
624 }
625 d[i] = 0; /* null terminate */
626
627 return i;
628}
629
630int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
631{
632#ifdef HAVE_SOCKADDR
633 int ret = 0;
634 SOCKADDR_S addr;
635 int sockaddr_len = sizeof(SOCKADDR_IN);
636#ifdef HAVE_GETADDRINFO
637 ADDRINFO hints;
638 ADDRINFO* answer = NULL;
639 char strPort[6];
640#else
641 HOSTENT* entry;
642 SOCKADDR_IN *sin;
643#endif
644
645 XMEMSET(&addr, 0, sizeof(addr));
646
647#ifdef WOLFIO_DEBUG
648 printf("TCP Connect: %s:%d\n", ip, port);
649#endif
650
651#ifdef HAVE_GETADDRINFO
652 XMEMSET(&hints, 0, sizeof(hints));
653 hints.ai_family = AF_UNSPEC;
654 hints.ai_socktype = SOCK_STREAM;
655 hints.ai_protocol = IPPROTO_TCP;
656
657 if (wolfIO_Word16ToString(strPort, port) == 0) {
658 WOLFSSL_MSG("invalid port number for responder");
659 return -1;
660 }
661
662 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
663 WOLFSSL_MSG("no addr info for responder");
664 return -1;
665 }
666
667 sockaddr_len = answer->ai_addrlen;
668 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
669 freeaddrinfo(answer);
670#else
671 entry = gethostbyname(ip);
672 sin = (SOCKADDR_IN *)&addr;
673
674 if (entry) {
675 sin->sin_family = AF_INET;
676 sin->sin_port = XHTONS(port);
677 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
678 }
679 else {
680 WOLFSSL_MSG("no addr info for responder");
681 return -1;
682 }
683#endif
684
685 *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
686
687#ifdef USE_WINDOWS_API
688 if (*sockfd == INVALID_SOCKET) {
689 WOLFSSL_MSG("bad socket fd, out of fds?");
690 return -1;
691 }
692#else
693 if (*sockfd < 0) {
694 WOLFSSL_MSG("bad socket fd, out of fds?");
695 return -1;
696 }
697#endif
698
699#ifdef HAVE_IO_TIMEOUT
700 /* if timeout value provided then set socket non-blocking */
701 if (to_sec > 0) {
702 wolfIO_SetBlockingMode(*sockfd, 1);
703 }
704#else
705 (void)to_sec;
706#endif
707
708 ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
709#ifdef HAVE_IO_TIMEOUT
710 if (ret != 0) {
711 if ((errno == EINPROGRESS) && (to_sec > 0)) {
712 /* wait for connect to complete */
713 ret = wolfIO_Select(*sockfd, to_sec);
714
715 /* restore blocking mode */
716 wolfIO_SetBlockingMode(*sockfd, 0);
717 }
718 }
719#endif
720 if (ret != 0) {
721 WOLFSSL_MSG("Responder tcp connect failed");
722 return -1;
723 }
724 return ret;
725#else
726 (void)sockfd;
727 (void)ip;
728 (void)port;
729 (void)to_sec;
730 return -1;
731#endif /* HAVE_SOCKADDR */
732}
733
734#ifndef HTTP_SCRATCH_BUFFER_SIZE
735 #define HTTP_SCRATCH_BUFFER_SIZE 512
736#endif
737#ifndef MAX_URL_ITEM_SIZE
738 #define MAX_URL_ITEM_SIZE 80
739#endif
740
741int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
742 word16* outPort)
743{
744 int result = -1;
745
746 if (url == NULL || urlSz == 0) {
747 if (outName)
748 *outName = 0;
749 if (outPath)
750 *outPath = 0;
751 if (outPort)
752 *outPort = 0;
753 }
754 else {
755 int i, cur;
756
757 /* need to break the url down into scheme, address, and port */
758 /* "http://example.com:8080/" */
759 /* "http://[::1]:443/" */
760 if (XSTRNCMP(url, "http://", 7) == 0) {
761 cur = 7;
762 } else cur = 0;
763
764 i = 0;
765 if (url[cur] == '[') {
766 cur++;
767 /* copy until ']' */
768 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
769 if (outName)
770 outName[i] = url[cur];
771 i++; cur++;
772 }
773 cur++; /* skip ']' */
774 }
775 else {
776 while (url[cur] != 0 && url[cur] != ':' &&
777 url[cur] != '/' && cur < urlSz) {
778 if (outName)
779 outName[i] = url[cur];
780 i++; cur++;
781 }
782 }
783 if (outName)
784 outName[i] = 0;
785 /* Need to pick out the path after the domain name */
786
787 if (cur < urlSz && url[cur] == ':') {
788 char port[6];
789 int j;
790 word32 bigPort = 0;
791 i = 0;
792 cur++;
793 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
794 i < 6) {
795 port[i++] = url[cur++];
796 }
797
798 for (j = 0; j < i; j++) {
799 if (port[j] < '0' || port[j] > '9') return -1;
800 bigPort = (bigPort * 10) + (port[j] - '0');
801 }
802 if (outPort)
803 *outPort = (word16)bigPort;
804 }
805 else if (outPort)
806 *outPort = 80;
807
808
809 if (cur < urlSz && url[cur] == '/') {
810 i = 0;
811 while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
812 if (outPath)
813 outPath[i] = url[cur];
814 i++; cur++;
815 }
816 if (outPath)
817 outPath[i] = 0;
818 }
819 else if (outPath) {
820 outPath[0] = '/';
821 outPath[1] = 0;
822 }
823
824 result = 0;
825 }
826
827 return result;
828}
829
830static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
831 int chunkSz, char* start, int len, int dynType, void* heap)
832{
833 byte* newRecvBuf = NULL;
834 int newRecvSz = *recvBufSz + chunkSz;
835 int pos = 0;
836
837 WOLFSSL_MSG("Processing HTTP response");
838#ifdef WOLFIO_DEBUG
839 printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
840#endif
841
842 newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
843 if (newRecvBuf == NULL) {
844 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
845 return MEMORY_E;
846 }
847
848 /* if buffer already exists, then we are growing it */
849 if (*recvBuf) {
850 XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
851 XFREE(*recvBuf, heap, dynType);
852 pos += *recvBufSz;
853 *recvBuf = NULL;
854 }
855
856 /* copy the remainder of the httpBuf into the respBuf */
857 if (len != 0) {
858 XMEMCPY(&newRecvBuf[pos], start, len);
859 pos += len;
860 }
861
862 /* receive the remainder of chunk */
863 while (len < chunkSz) {
864 int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
865 if (rxSz > 0) {
866 len += rxSz;
867 pos += rxSz;
868 }
869 else {
870 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
871 XFREE(newRecvBuf, heap, dynType);
872 return -1;
873 }
874 }
875
876 *recvBuf = newRecvBuf;
877 *recvBufSz = newRecvSz;
878
879 return 0;
880}
881
882int wolfIO_HttpProcessResponse(int sfd, const char* appStr,
883 byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
884{
885 int result = 0;
886 int len = 0;
887 char *start, *end;
888 int respBufSz = 0;
889 int isChunked = 0, chunkSz = 0;
890 enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
891 phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
892 phr_http_end
893 } state = phr_init;
894
895 *respBuf = NULL;
896 start = end = NULL;
897 do {
898 if (state == phr_get_chunk_data) {
899 /* get chunk of data */
900 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
901 chunkSz, start, len, dynType, heap);
902
903 state = (result != 0) ? phr_http_end : phr_get_chunk_len;
904 end = NULL;
905 len = 0;
906 }
907
908 /* read data if no \r\n or first time */
909 if (end == NULL) {
910 result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
911 if (result > 0) {
912 len += result;
913 start = (char*)httpBuf;
914 start[len] = 0;
915 }
916 else {
917 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
918 return -1;
919 }
920 }
921 end = XSTRSTR(start, "\r\n"); /* locate end */
922
923 /* handle incomplete rx */
924 if (end == NULL) {
925 if (len != 0)
926 XMEMMOVE(httpBuf, start, len);
927 start = end = NULL;
928 }
929 /* when start is "\r\n" */
930 else if (end == start) {
931 /* if waiting for end or need chunk len */
932 if (state == phr_wait_end || state == phr_get_chunk_len) {
933 state = (isChunked) ? phr_get_chunk_len : phr_http_end;
934 len -= 2; start += 2; /* skip \r\n */
935 }
936 else {
937 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
938 return -1;
939 }
940 }
941 else {
942 *end = 0; /* null terminate */
943 len -= (int)(end - start) + 2;
944 /* adjust len to remove the first line including the /r/n */
945
946 #ifdef WOLFIO_DEBUG
947 printf("HTTP Resp: %s\n", start);
948 #endif
949
950 switch (state) {
951 case phr_init:
952 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
953 start += 9;
954 if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
955 WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
956 return -1;
957 }
958 state = phr_http_start;
959 }
960 break;
961 case phr_http_start:
962 case phr_have_length:
963 case phr_have_type:
964 if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
965 start += 13;
966 while (*start == ' ' && *start != '\0') start++;
967 if (XSTRNCASECMP(start, appStr, XSTRLEN(appStr)) != 0) {
968 WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
969 return -1;
970 }
971 state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
972 }
973 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
974 start += 15;
975 while (*start == ' ' && *start != '\0') start++;
976 chunkSz = atoi(start);
977 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
978 }
979 else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
980 start += 18;
981 while (*start == ' ' && *start != '\0') start++;
982 if (XSTRNCASECMP(start, "chunked", 7) == 0) {
983 isChunked = 1;
984 state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
985 }
986 }
987 break;
988 case phr_get_chunk_len:
989 chunkSz = (int)strtol(start, NULL, 16); /* hex format */
990 state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
991 break;
992 case phr_get_chunk_data:
993 /* processing for chunk data done above, since \r\n isn't required */
994 case phr_wait_end:
995 case phr_http_end:
996 /* do nothing */
997 break;
998 } /* switch (state) */
999
1000 /* skip to end plus \r\n */
1001 start = end + 2;
1002 }
1003 } while (state != phr_http_end);
1004
1005 if (!isChunked) {
1006 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
1007 start, len, dynType, heap);
1008 }
1009
1010 if (result >= 0) {
1011 result = respBufSz;
1012 }
1013 else {
1014 WOLFSSL_ERROR(result);
1015 }
1016
1017 return result;
1018}
1019
1020int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
1021 const char* path, int pathLen, int reqSz, const char* contentType,
1022 byte* buf, int bufSize)
1023{
1024 word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
1025 char reqSzStr[6];
1026 char* req = (char*)buf;
1027 const char* blankStr = " ";
1028 const char* http11Str = " HTTP/1.1";
1029 const char* hostStr = "\r\nHost: ";
1030 const char* contentLenStr = "\r\nContent-Length: ";
1031 const char* contentTypeStr = "\r\nContent-Type: ";
1032 const char* doubleCrLfStr = "\r\n\r\n";
1033 word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
1034 contentTypeStrLen, doubleCrLfStrLen;
1035
1036 reqTypeLen = (word32)XSTRLEN(reqType);
1037 domainNameLen = (word32)XSTRLEN(domainName);
1038 reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
1039 contentTypeLen = (word32)XSTRLEN(contentType);
1040
1041 blankStrLen = (word32)XSTRLEN(blankStr);
1042 http11StrLen = (word32)XSTRLEN(http11Str);
1043 hostStrLen = (word32)XSTRLEN(hostStr);
1044 contentLenStrLen = (word32)XSTRLEN(contentLenStr);
1045 contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
1046 doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
1047
1048 /* determine max length and check it */
1049 maxLen =
1050 reqTypeLen +
1051 blankStrLen +
1052 pathLen +
1053 http11StrLen +
1054 hostStrLen +
1055 domainNameLen +
1056 contentLenStrLen +
1057 reqSzStrLen +
1058 contentTypeStrLen +
1059 contentTypeLen +
1060 doubleCrLfStrLen +
1061 1 /* null term */;
1062 if (maxLen > (word32)bufSize)
1063 return 0;
1064
1065 XSTRNCPY((char*)buf, reqType, reqTypeLen);
1066 buf += reqTypeLen;
1067 XSTRNCPY((char*)buf, blankStr, blankStrLen+1);
1068 buf += blankStrLen;
1069 XSTRNCPY((char*)buf, path, pathLen);
1070 buf += pathLen;
1071 XSTRNCPY((char*)buf, http11Str, http11StrLen+1);
1072 buf += http11StrLen;
1073 if (domainNameLen > 0) {
1074 XSTRNCPY((char*)buf, hostStr, hostStrLen+1);
1075 buf += hostStrLen;
1076 XSTRNCPY((char*)buf, domainName, domainNameLen);
1077 buf += domainNameLen;
1078 }
1079 if (reqSz > 0 && reqSzStrLen > 0) {
1080 XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1);
1081 buf += contentLenStrLen;
1082 XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen);
1083 buf += reqSzStrLen;
1084 }
1085 if (contentTypeLen > 0) {
1086 XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1);
1087 buf += contentTypeStrLen;
1088 XSTRNCPY((char*)buf, contentType, contentTypeLen);
1089 buf += contentTypeLen;
1090 }
1091 XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1);
1092 buf += doubleCrLfStrLen;
1093
1094#ifdef WOLFIO_DEBUG
1095 printf("HTTP %s: %s", reqType, req);
1096#endif
1097
1098 /* calculate actual length based on original and new pointer */
1099 return (int)((char*)buf - req);
1100}
1101
1102
1103#ifdef HAVE_OCSP
1104
1105int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
1106 int ocspReqSz, byte* buf, int bufSize)
1107{
1108 return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
1109 ocspReqSz, "application/ocsp-request", buf, bufSize);
1110}
1111
1112/* return: >0 OCSP Response Size
1113 * -1 error */
1114int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
1115 byte* httpBuf, int httpBufSz, void* heap)
1116{
1117 return wolfIO_HttpProcessResponse(sfd, "application/ocsp-response",
1118 respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
1119}
1120
1121/* in default wolfSSL callback ctx is the heap pointer */
1122int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
1123 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
1124{
1125 SOCKET_T sfd = 0;
1126 word16 port;
1127 int ret = -1;
1128#ifdef WOLFSSL_SMALL_STACK
1129 char* path;
1130 char* domainName;
1131#else
1132 char path[MAX_URL_ITEM_SIZE];
1133 char domainName[MAX_URL_ITEM_SIZE];
1134#endif
1135
1136#ifdef WOLFSSL_SMALL_STACK
1137 path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1138 if (path == NULL)
1139 return MEMORY_E;
1140
1141 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1142 if (domainName == NULL) {
1143 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1144 return MEMORY_E;
1145 }
1146#endif
1147
1148 if (ocspReqBuf == NULL || ocspReqSz == 0) {
1149 WOLFSSL_MSG("OCSP request is required for lookup");
1150 }
1151 else if (ocspRespBuf == NULL) {
1152 WOLFSSL_MSG("Cannot save OCSP response");
1153 }
1154 else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
1155 WOLFSSL_MSG("Unable to decode OCSP URL");
1156 }
1157 else {
1158 /* Note, the library uses the EmbedOcspRespFree() callback to
1159 * free this buffer. */
1160 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1161 byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
1162
1163 if (httpBuf == NULL) {
1164 WOLFSSL_MSG("Unable to create OCSP response buffer");
1165 }
1166 else {
1167 httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
1168 httpBuf, httpBufSz);
1169
1170 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1171 if ((ret != 0) || (sfd <= 0)) {
1172 WOLFSSL_MSG("OCSP Responder connection failed");
1173 }
1174 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
1175 httpBufSz) {
1176 WOLFSSL_MSG("OCSP http request failed");
1177 }
1178 else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
1179 ocspReqSz) {
1180 WOLFSSL_MSG("OCSP ocsp request failed");
1181 }
1182 else {
1183 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
1184 HTTP_SCRATCH_BUFFER_SIZE, ctx);
1185 }
1186
1187 close(sfd);
1188 XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
1189 }
1190 }
1191
1192#ifdef WOLFSSL_SMALL_STACK
1193 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1194 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1195#endif
1196
1197 return ret;
1198}
1199
1200/* in default callback ctx is heap hint */
1201void EmbedOcspRespFree(void* ctx, byte *resp)
1202{
1203 if (resp)
1204 XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
1205
1206 (void)ctx;
1207}
1208#endif /* HAVE_OCSP */
1209
1210
1211#if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
1212
1213int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
1214 const char* domainName, byte* buf, int bufSize)
1215{
1216 return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
1217 buf, bufSize);
1218}
1219
1220int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
1221 int httpBufSz)
1222{
1223 int result;
1224 byte *respBuf = NULL;
1225
1226 result = wolfIO_HttpProcessResponse(sfd, "application/pkix-crl",
1227 &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
1228 if (result >= 0) {
1229 result = BufferLoadCRL(crl, respBuf, result, SSL_FILETYPE_ASN1);
1230 }
1231 XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
1232
1233 return result;
1234}
1235
1236int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
1237{
1238 SOCKET_T sfd = 0;
1239 word16 port;
1240 int ret = -1;
1241#ifdef WOLFSSL_SMALL_STACK
1242 char* domainName;
1243#else
1244 char domainName[MAX_URL_ITEM_SIZE];
1245#endif
1246
1247#ifdef WOLFSSL_SMALL_STACK
1248 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
1249 DYNAMIC_TYPE_TMP_BUFFER);
1250 if (domainName == NULL) {
1251 return MEMORY_E;
1252 }
1253#endif
1254
1255 if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
1256 WOLFSSL_MSG("Unable to decode CRL URL");
1257 }
1258 else {
1259 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
1260 byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap,
1261 DYNAMIC_TYPE_CRL);
1262 if (httpBuf == NULL) {
1263 WOLFSSL_MSG("Unable to create CRL response buffer");
1264 }
1265 else {
1266 httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
1267 httpBuf, httpBufSz);
1268
1269 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
1270 if ((ret != 0) || (sfd <= 0)) {
1271 WOLFSSL_MSG("CRL connection failed");
1272 }
1273 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
1274 != httpBufSz) {
1275 WOLFSSL_MSG("CRL http get failed");
1276 }
1277 else {
1278 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
1279 HTTP_SCRATCH_BUFFER_SIZE);
1280 }
1281
1282 close(sfd);
1283 XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
1284 }
1285 }
1286
1287#ifdef WOLFSSL_SMALL_STACK
1288 XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
1289#endif
1290
1291 return ret;
1292}
1293#endif /* HAVE_CRL && HAVE_CRL_IO */
1294
1295#endif /* HAVE_HTTP_CLIENT */
1296
1297
1298
1299WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
1300{
1301 ctx->CBIORecv = CBIORecv;
1302}
1303
1304
1305WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
1306{
1307 ctx->CBIOSend = CBIOSend;
1308}
1309
1310
1311WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
1312{
1313 ssl->IOCB_ReadCtx = rctx;
1314}
1315
1316
1317WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
1318{
1319 ssl->IOCB_WriteCtx = wctx;
1320}
1321
1322
1323WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
1324{
1325 if (ssl)
1326 return ssl->IOCB_ReadCtx;
1327
1328 return NULL;
1329}
1330
1331
1332WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
1333{
1334 if (ssl)
1335 return ssl->IOCB_WriteCtx;
1336
1337 return NULL;
1338}
1339
1340
1341WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
1342{
1343 ssl->rflags = flags;
1344}
1345
1346
1347WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1348{
1349 ssl->wflags = flags;
1350}
1351
1352
1353#ifdef WOLFSSL_DTLS
1354
1355WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1356{
1357 ctx->CBIOCookie = cb;
1358}
1359
1360
1361WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1362{
1363 ssl->IOCB_CookieCtx = ctx;
1364}
1365
1366
1367WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1368{
1369 if (ssl)
1370 return ssl->IOCB_CookieCtx;
1371
1372 return NULL;
1373}
1374
1375#ifdef WOLFSSL_SESSION_EXPORT
1376
1377WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
1378{
1379 ctx->CBGetPeer = cb;
1380}
1381
1382
1383WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
1384{
1385 ctx->CBSetPeer = cb;
1386}
1387
1388#endif /* WOLFSSL_SESSION_EXPORT */
1389#endif /* WOLFSSL_DTLS */
1390
1391
1392#ifdef HAVE_NETX
1393
1394/* The NetX receive callback
1395 * return : bytes read, or error
1396 */
1397int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1398{
1399 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1400 ULONG left;
1401 ULONG total;
1402 ULONG copied = 0;
1403 UINT status;
1404
1405 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1406 WOLFSSL_MSG("NetX Recv NULL parameters");
1407 return WOLFSSL_CBIO_ERR_GENERAL;
1408 }
1409
1410 if (nxCtx->nxPacket == NULL) {
1411 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1412 nxCtx->nxWait);
1413 if (status != NX_SUCCESS) {
1414 WOLFSSL_MSG("NetX Recv receive error");
1415 return WOLFSSL_CBIO_ERR_GENERAL;
1416 }
1417 }
1418
1419 if (nxCtx->nxPacket) {
1420 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1421 if (status != NX_SUCCESS) {
1422 WOLFSSL_MSG("NetX Recv length get error");
1423 return WOLFSSL_CBIO_ERR_GENERAL;
1424 }
1425
1426 left = total - nxCtx->nxOffset;
1427 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1428 buf, sz, &copied);
1429 if (status != NX_SUCCESS) {
1430 WOLFSSL_MSG("NetX Recv data extract offset error");
1431 return WOLFSSL_CBIO_ERR_GENERAL;
1432 }
1433
1434 nxCtx->nxOffset += copied;
1435
1436 if (copied == left) {
1437 WOLFSSL_MSG("NetX Recv Drained packet");
1438 nx_packet_release(nxCtx->nxPacket);
1439 nxCtx->nxPacket = NULL;
1440 nxCtx->nxOffset = 0;
1441 }
1442 }
1443
1444 return copied;
1445}
1446
1447
1448/* The NetX send callback
1449 * return : bytes sent, or error
1450 */
1451int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1452{
1453 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1454 NX_PACKET* packet;
1455 NX_PACKET_POOL* pool; /* shorthand */
1456 UINT status;
1457
1458 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1459 WOLFSSL_MSG("NetX Send NULL parameters");
1460 return WOLFSSL_CBIO_ERR_GENERAL;
1461 }
1462
1463 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1464 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1465 nxCtx->nxWait);
1466 if (status != NX_SUCCESS) {
1467 WOLFSSL_MSG("NetX Send packet alloc error");
1468 return WOLFSSL_CBIO_ERR_GENERAL;
1469 }
1470
1471 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1472 if (status != NX_SUCCESS) {
1473 nx_packet_release(packet);
1474 WOLFSSL_MSG("NetX Send data append error");
1475 return WOLFSSL_CBIO_ERR_GENERAL;
1476 }
1477
1478 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1479 if (status != NX_SUCCESS) {
1480 nx_packet_release(packet);
1481 WOLFSSL_MSG("NetX Send socket send error");
1482 return WOLFSSL_CBIO_ERR_GENERAL;
1483 }
1484
1485 return sz;
1486}
1487
1488
1489/* like set_fd, but for default NetX context */
1490void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1491{
1492 if (ssl) {
1493 ssl->nxCtx.nxSocket = nxSocket;
1494 ssl->nxCtx.nxWait = waitOption;
1495 }
1496}
1497
1498#endif /* HAVE_NETX */
1499
1500#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.