source: azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/src/wolfio.c@ 457

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

ファイルを追加

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