source: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/wolfio.c@ 464

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

WolfSSLとAzure IoT SDKを更新

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