3 * Copyright (C) 2006-2015 wolfSSL Inc.
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
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.
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.
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-1301, USA
27 #include <wolfssl/wolfcrypt/settings.h>
30 /* On WinCE winsock2.h must be included before windows.h for socket stuff */
34 #include <wolfssl/internal.h>
35 #include <wolfssl/error-ssl.h>
38 /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
39 automatic setting of default I/O functions EmbedSend() and EmbedReceive()
40 but they'll still need SetCallback xxx() at end of file
42 #ifndef WOLFSSL_USER_IO
48 #ifndef USE_WINDOWS_API
50 /* lwIP needs to be configured to use sockets API in this mode */
51 /* LWIP_SOCKET 1 in lwip/opt.h or in build */
52 #include "lwip/sockets.h"
54 #ifndef LWIP_PROVIDE_ERRNO
55 #define LWIP_PROVIDE_ERRNO 1
57 #elif defined(FREESCALE_MQX)
60 #elif defined(WOLFSSL_MDK_ARM)
61 #if defined(WOLFSSL_MDK5)
69 #include "WOLFSSL_MDK_ARM.h"
71 #define RNG wolfSSL_RNG
72 /* for avoiding name conflict in "stm32f2xx.h" */
74 #elif defined(WOLFSSL_TIRTOS)
75 #include <sys/socket.h>
76 #elif defined(WOLFSSL_IAR_ARM)
79 #include <sys/types.h>
85 #if !(defined(DEVKITPRO) || defined(HAVE_RTP_SYS) || defined(EBSNET)) \
86 && !(defined(WOLFSSL_PICOTCP))
87 #include <sys/socket.h>
88 #include <arpa/inet.h>
89 #include <netinet/in.h>
92 #include <netex/errno.h>
94 #include <sys/ioctl.h>
101 #include "rtipapi.h" /* errno */
105 #endif /* USE_WINDOWS_API */
108 #include <sys/filio.h>
111 #ifdef USE_WINDOWS_API
114 #define WSAEPIPE -12345
116 #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
117 #define SOCKET_EAGAIN WSAETIMEDOUT
118 #define SOCKET_ECONNRESET WSAECONNRESET
119 #define SOCKET_EINTR WSAEINTR
120 #define SOCKET_EPIPE WSAEPIPE
121 #define SOCKET_ECONNREFUSED WSAENOTCONN
122 #define SOCKET_ECONNABORTED WSAECONNABORTED
123 #define close(s) closesocket(s)
125 #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
126 #define SOCKET_EAGAIN SYS_NET_EAGAIN
127 #define SOCKET_ECONNRESET SYS_NET_ECONNRESET
128 #define SOCKET_EINTR SYS_NET_EINTR
129 #define SOCKET_EPIPE SYS_NET_EPIPE
130 #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED
131 #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED
132 #elif defined(FREESCALE_MQX)
133 /* RTCS doesn't have an EWOULDBLOCK error */
134 #define SOCKET_EWOULDBLOCK EAGAIN
135 #define SOCKET_EAGAIN EAGAIN
136 #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET
137 #define SOCKET_EINTR EINTR
138 #define SOCKET_EPIPE EPIPE
139 #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED
140 #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED
141 #elif defined(WOLFSSL_MDK_ARM)
142 #if defined(WOLFSSL_MDK5)
143 #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK
144 #define SOCKET_EAGAIN BSD_ERROR_LOCKED
145 #define SOCKET_ECONNRESET BSD_ERROR_CLOSED
146 #define SOCKET_EINTR BSD_ERROR
147 #define SOCKET_EPIPE BSD_ERROR
148 #define SOCKET_ECONNREFUSED BSD_ERROR
149 #define SOCKET_ECONNABORTED BSD_ERROR
151 #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK
152 #define SOCKET_EAGAIN SCK_ELOCKED
153 #define SOCKET_ECONNRESET SCK_ECLOSED
154 #define SOCKET_EINTR SCK_ERROR
155 #define SOCKET_EPIPE SCK_ERROR
156 #define SOCKET_ECONNREFUSED SCK_ERROR
157 #define SOCKET_ECONNABORTED SCK_ERROR
159 #elif defined(WOLFSSL_PICOTCP)
160 #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN
161 #define SOCKET_EAGAIN PICO_ERR_EAGAIN
162 #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET
163 #define SOCKET_EINTR PICO_ERR_EINTR
164 #define SOCKET_EPIPE PICO_ERR_EIO
165 #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED
166 #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN
168 #define SOCKET_EWOULDBLOCK EWOULDBLOCK
169 #define SOCKET_EAGAIN EAGAIN
170 #define SOCKET_ECONNRESET ECONNRESET
171 #define SOCKET_EINTR EINTR
172 #define SOCKET_EPIPE EPIPE
173 #define SOCKET_ECONNREFUSED ECONNREFUSED
174 #define SOCKET_ECONNABORTED ECONNABORTED
175 #endif /* USE_WINDOWS_API */
180 int net_send(int, const void*, int, unsigned int);
181 int net_recv(int, void*, int, unsigned int);
182 #define SEND_FUNCTION net_send
183 #define RECV_FUNCTION net_recv
184 #elif defined(WOLFSSL_LWIP)
185 #define SEND_FUNCTION lwip_send
186 #define RECV_FUNCTION lwip_recv
187 #elif defined(WOLFSSL_PICOTCP)
188 #define SEND_FUNCTION pico_send
189 #define RECV_FUNCTION pico_recv
191 #define SEND_FUNCTION send
192 #define RECV_FUNCTION recv
196 /* Translates return codes returned from
197 * send() and recv() if need be.
199 static INLINE int TranslateReturnCode(int old, int sd)
205 errno = SOCKET_EWOULDBLOCK;
206 return -1; /* convert to BSD style wouldblock as error */
210 errno = RTCS_geterror(sd);
211 if (errno == RTCSERR_TCP_CONN_CLOSING)
212 return 0; /* convert to BSD style closing */
219 static INLINE int LastError(void)
221 #ifdef USE_WINDOWS_API
222 return WSAGetLastError();
223 #elif defined(EBSNET)
224 return xn_getlasterror();
230 /* The receive embedded callback
231 * return : nb bytes read, or error
233 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
241 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
242 if (wolfSSL_dtls(ssl)
243 && !wolfSSL_get_using_nonblock(ssl)
244 && dtls_timeout != 0) {
245 #ifdef USE_WINDOWS_API
246 DWORD timeout = dtls_timeout * 1000;
248 struct timeval timeout;
249 XMEMSET(&timeout, 0, sizeof(timeout));
250 timeout.tv_sec = dtls_timeout;
252 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
253 sizeof(timeout)) != 0) {
254 WOLFSSL_MSG("setsockopt rcvtimeo failed");
260 recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags);
262 recvd = TranslateReturnCode(recvd, sd);
266 WOLFSSL_MSG("Embed Receive error");
268 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
269 if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) {
270 WOLFSSL_MSG(" Would block");
271 return WOLFSSL_CBIO_ERR_WANT_READ;
274 WOLFSSL_MSG(" Socket timeout");
275 return WOLFSSL_CBIO_ERR_TIMEOUT;
278 else if (err == SOCKET_ECONNRESET) {
279 WOLFSSL_MSG(" Connection reset");
280 return WOLFSSL_CBIO_ERR_CONN_RST;
282 else if (err == SOCKET_EINTR) {
283 WOLFSSL_MSG(" Socket interrupted");
284 return WOLFSSL_CBIO_ERR_ISR;
286 else if (err == SOCKET_ECONNREFUSED) {
287 WOLFSSL_MSG(" Connection refused");
288 return WOLFSSL_CBIO_ERR_WANT_READ;
290 else if (err == SOCKET_ECONNABORTED) {
291 WOLFSSL_MSG(" Connection aborted");
292 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
295 WOLFSSL_MSG(" General error");
296 return WOLFSSL_CBIO_ERR_GENERAL;
299 else if (recvd == 0) {
300 WOLFSSL_MSG("Embed receive connection closed");
301 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
307 /* The send embedded callback
308 * return : nb bytes sent, or error
310 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
317 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags);
321 WOLFSSL_MSG("Embed Send error");
323 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
324 WOLFSSL_MSG(" Would Block");
325 return WOLFSSL_CBIO_ERR_WANT_WRITE;
327 else if (err == SOCKET_ECONNRESET) {
328 WOLFSSL_MSG(" Connection reset");
329 return WOLFSSL_CBIO_ERR_CONN_RST;
331 else if (err == SOCKET_EINTR) {
332 WOLFSSL_MSG(" Socket interrupted");
333 return WOLFSSL_CBIO_ERR_ISR;
335 else if (err == SOCKET_EPIPE) {
336 WOLFSSL_MSG(" Socket EPIPE");
337 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
340 WOLFSSL_MSG(" General error");
341 return WOLFSSL_CBIO_ERR_GENERAL;
351 #include <wolfssl/wolfcrypt/sha.h>
353 #ifdef USE_WINDOWS_API
354 #define XSOCKLENT int
356 #define XSOCKLENT socklen_t
359 #define SENDTO_FUNCTION sendto
360 #define RECVFROM_FUNCTION recvfrom
363 /* The receive embedded callback
364 * return : nb bytes read, or error
366 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
368 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
371 int sd = dtlsCtx->fd;
372 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
373 struct sockaddr_storage peer;
374 XSOCKLENT peerSz = sizeof(peer);
376 WOLFSSL_ENTER("EmbedReceiveFrom()");
378 if (!wolfSSL_get_using_nonblock(ssl) && dtls_timeout != 0) {
379 #ifdef USE_WINDOWS_API
380 DWORD timeout = dtls_timeout * 1000;
382 struct timeval timeout;
383 XMEMSET(&timeout, 0, sizeof(timeout));
384 timeout.tv_sec = dtls_timeout;
386 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
387 sizeof(timeout)) != 0) {
388 WOLFSSL_MSG("setsockopt rcvtimeo failed");
392 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
393 (struct sockaddr*)&peer, &peerSz);
395 recvd = TranslateReturnCode(recvd, sd);
399 WOLFSSL_MSG("Embed Receive From error");
401 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
402 if (wolfSSL_get_using_nonblock(ssl)) {
403 WOLFSSL_MSG(" Would block");
404 return WOLFSSL_CBIO_ERR_WANT_READ;
407 WOLFSSL_MSG(" Socket timeout");
408 return WOLFSSL_CBIO_ERR_TIMEOUT;
411 else if (err == SOCKET_ECONNRESET) {
412 WOLFSSL_MSG(" Connection reset");
413 return WOLFSSL_CBIO_ERR_CONN_RST;
415 else if (err == SOCKET_EINTR) {
416 WOLFSSL_MSG(" Socket interrupted");
417 return WOLFSSL_CBIO_ERR_ISR;
419 else if (err == SOCKET_ECONNREFUSED) {
420 WOLFSSL_MSG(" Connection refused");
421 return WOLFSSL_CBIO_ERR_WANT_READ;
424 WOLFSSL_MSG(" General error");
425 return WOLFSSL_CBIO_ERR_GENERAL;
429 if (dtlsCtx->peer.sz > 0
430 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
431 && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
432 WOLFSSL_MSG(" Ignored packet from invalid peer");
433 return WOLFSSL_CBIO_ERR_WANT_READ;
441 /* The send embedded callback
442 * return : nb bytes sent, or error
444 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
446 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
447 int sd = dtlsCtx->fd;
452 WOLFSSL_ENTER("EmbedSendTo()");
454 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
455 (const struct sockaddr*)dtlsCtx->peer.sa,
459 WOLFSSL_MSG("Embed Send To error");
461 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
462 WOLFSSL_MSG(" Would Block");
463 return WOLFSSL_CBIO_ERR_WANT_WRITE;
465 else if (err == SOCKET_ECONNRESET) {
466 WOLFSSL_MSG(" Connection reset");
467 return WOLFSSL_CBIO_ERR_CONN_RST;
469 else if (err == SOCKET_EINTR) {
470 WOLFSSL_MSG(" Socket interrupted");
471 return WOLFSSL_CBIO_ERR_ISR;
473 else if (err == SOCKET_EPIPE) {
474 WOLFSSL_MSG(" Socket EPIPE");
475 return WOLFSSL_CBIO_ERR_CONN_CLOSE;
478 WOLFSSL_MSG(" General error");
479 return WOLFSSL_CBIO_ERR_GENERAL;
487 /* The DTLS Generate Cookie callback
488 * return : number of bytes copied into buf, or error
490 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
493 struct sockaddr_storage peer;
494 XSOCKLENT peerSz = sizeof(peer);
495 byte digest[SHA_DIGEST_SIZE];
500 XMEMSET(&peer, 0, sizeof(peer));
501 if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) {
502 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
506 ret = wc_ShaHash((byte*)&peer, peerSz, digest);
510 if (sz > SHA_DIGEST_SIZE)
511 sz = SHA_DIGEST_SIZE;
512 XMEMCPY(buf, digest, sz);
517 #endif /* WOLFSSL_DTLS */
522 static int Word16ToString(char* d, word16 number)
527 word16 order = 10000;
535 digit = number / order;
536 if (i > 0 || digit != 0) {
537 d[i++] = (char)digit + '0';
540 number %= digit * order;
554 static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
556 struct sockaddr_storage addr;
557 int sockaddr_len = sizeof(struct sockaddr_in);
558 XMEMSET(&addr, 0, sizeof(addr));
560 #ifdef HAVE_GETADDRINFO
562 struct addrinfo hints;
563 struct addrinfo* answer = NULL;
566 XMEMSET(&hints, 0, sizeof(hints));
567 hints.ai_family = AF_UNSPEC;
568 hints.ai_socktype = SOCK_STREAM;
569 hints.ai_protocol = IPPROTO_TCP;
571 if (Word16ToString(strPort, port) == 0) {
572 WOLFSSL_MSG("invalid port number for OCSP responder");
576 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
577 WOLFSSL_MSG("no addr info for OCSP responder");
581 sockaddr_len = answer->ai_addrlen;
582 XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
583 freeaddrinfo(answer);
586 #else /* HAVE_GETADDRINFO */
588 struct hostent* entry = gethostbyname(ip);
589 struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
592 sin->sin_family = AF_INET;
593 sin->sin_port = htons(port);
594 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
598 WOLFSSL_MSG("no addr info for OCSP responder");
602 #endif /* HAVE_GETADDRINFO */
604 *sockfd = socket(addr.ss_family, SOCK_STREAM, 0);
606 #ifdef USE_WINDOWS_API
607 if (*sockfd == INVALID_SOCKET) {
608 WOLFSSL_MSG("bad socket fd, out of fds?");
613 WOLFSSL_MSG("bad socket fd, out of fds?");
618 if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) {
619 WOLFSSL_MSG("OCSP responder tcp connect failed");
627 static int build_http_request(const char* domainName, const char* path,
628 int ocspReqSz, byte* buf, int bufSize)
630 word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen;
631 char ocspReqSzStr[6];
633 domainNameLen = (word32)XSTRLEN(domainName);
634 pathLen = (word32)XSTRLEN(path);
635 ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz);
637 completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84;
638 if (completeLen > (word32)bufSize)
641 XSTRNCPY((char*)buf, "POST ", 5);
643 XSTRNCPY((char*)buf, path, pathLen);
645 XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17);
647 XSTRNCPY((char*)buf, domainName, domainNameLen);
648 buf += domainNameLen;
649 XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18);
651 XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen);
652 buf += ocspReqSzStrLen;
654 "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44);
660 static int decode_url(const char* url, int urlSz,
661 char* outName, char* outPath, word16* outPort)
665 if (outName != NULL && outPath != NULL && outPort != NULL)
667 if (url == NULL || urlSz == 0)
677 /* need to break the url down into scheme, address, and port */
678 /* "http://example.com:8080/" */
679 /* "http://[::1]:443/" */
680 if (XSTRNCMP(url, "http://", 7) == 0) {
685 if (url[cur] == '[') {
688 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
689 outName[i++] = url[cur++];
691 cur++; /* skip ']' */
694 while (url[cur] != 0 && url[cur] != ':' &&
695 url[cur] != '/' && cur < urlSz) {
696 outName[i++] = url[cur++];
700 /* Need to pick out the path after the domain name */
702 if (cur < urlSz && url[cur] == ':') {
708 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
710 port[i++] = url[cur++];
713 for (j = 0; j < i; j++) {
714 if (port[j] < '0' || port[j] > '9') return -1;
715 bigPort = (bigPort * 10) + (port[j] - '0');
717 *outPort = (word16)bigPort;
722 if (cur < urlSz && url[cur] == '/') {
724 while (cur < urlSz && url[cur] != 0 && i < 80) {
725 outPath[i++] = url[cur++];
741 /* return: >0 OCSP Response Size
743 static int process_http_response(int sfd, byte** respBuf,
744 byte* httpBuf, int httpBufSz)
749 byte *recvBuf = NULL;
751 enum phr_state { phr_init, phr_http_start, phr_have_length,
752 phr_have_type, phr_wait_end, phr_http_end
758 result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
761 start = (char*)httpBuf;
765 WOLFSSL_MSG("process_http_response recv http from peer failed");
769 end = XSTRSTR(start, "\r\n");
773 XMEMMOVE(httpBuf, start, len);
776 else if (end == start) {
777 if (state == phr_wait_end) {
778 state = phr_http_end;
783 WOLFSSL_MSG("process_http_response header ended early");
789 len -= (int)(end - start) + 2;
790 /* adjust len to remove the first line including the /r/n */
792 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
794 if (XSTRNCASECMP(start, "200 OK", 6) != 0 ||
796 WOLFSSL_MSG("process_http_response not OK");
799 state = phr_http_start;
801 else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
803 while (*start == ' ' && *start != '\0') start++;
804 if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) {
805 WOLFSSL_MSG("process_http_response not ocsp-response");
809 if (state == phr_http_start) state = phr_have_type;
810 else if (state == phr_have_length) state = phr_wait_end;
812 WOLFSSL_MSG("process_http_response type invalid state");
816 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
818 while (*start == ' ' && *start != '\0') start++;
819 recvBufSz = atoi(start);
821 if (state == phr_http_start) state = phr_have_length;
822 else if (state == phr_have_type) state = phr_wait_end;
824 WOLFSSL_MSG("process_http_response length invalid state");
831 } while (state != phr_http_end);
833 recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
834 if (recvBuf == NULL) {
835 WOLFSSL_MSG("process_http_response couldn't create response buffer");
839 /* copy the remainder of the httpBuf into the respBuf */
841 XMEMCPY(recvBuf, start, len);
843 /* receive the OCSP response data */
845 result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0);
849 WOLFSSL_MSG("process_http_response recv ocsp from peer failed");
852 } while (len != recvBufSz);
859 #define SCRATCH_BUFFER_SIZE 512
861 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
862 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
867 #ifdef WOLFSSL_SMALL_STACK
875 #ifdef WOLFSSL_SMALL_STACK
876 path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
880 domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
881 if (domainName == NULL) {
882 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
889 if (ocspReqBuf == NULL || ocspReqSz == 0) {
890 WOLFSSL_MSG("OCSP request is required for lookup");
892 else if (ocspRespBuf == NULL) {
893 WOLFSSL_MSG("Cannot save OCSP response");
895 else if (decode_url(url, urlSz, domainName, path, &port) < 0) {
896 WOLFSSL_MSG("Unable to decode OCSP URL");
899 /* Note, the library uses the EmbedOcspRespFree() callback to
900 * free this buffer. */
901 int httpBufSz = SCRATCH_BUFFER_SIZE;
902 byte* httpBuf = (byte*)XMALLOC(httpBufSz, NULL,
903 DYNAMIC_TYPE_IN_BUFFER);
905 if (httpBuf == NULL) {
906 WOLFSSL_MSG("Unable to create OCSP response buffer");
909 httpBufSz = build_http_request(domainName, path, ocspReqSz,
912 if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) {
913 WOLFSSL_MSG("OCSP Responder connection failed");
915 else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) !=
917 WOLFSSL_MSG("OCSP http request failed");
919 else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
921 WOLFSSL_MSG("OCSP ocsp request failed");
924 ret = process_http_response(sfd, ocspRespBuf, httpBuf,
925 SCRATCH_BUFFER_SIZE);
929 XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
933 #ifdef WOLFSSL_SMALL_STACK
934 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
935 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
942 void EmbedOcspRespFree(void* ctx, byte *resp)
947 XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER);
953 #endif /* WOLFSSL_USER_IO */
955 WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
957 ctx->CBIORecv = CBIORecv;
961 WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
963 ctx->CBIOSend = CBIOSend;
967 WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
969 ssl->IOCB_ReadCtx = rctx;
973 WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
975 ssl->IOCB_WriteCtx = wctx;
979 WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
982 return ssl->IOCB_ReadCtx;
988 WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
991 return ssl->IOCB_WriteCtx;
997 WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
1003 WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1005 ssl->wflags = flags;
1011 WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1013 ctx->CBIOCookie = cb;
1017 WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1019 ssl->IOCB_CookieCtx = ctx;
1023 WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1026 return ssl->IOCB_CookieCtx;
1031 #endif /* WOLFSSL_DTLS */
1036 /* The NetX receive callback
1037 * return : bytes read, or error
1039 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1041 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1047 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1048 WOLFSSL_MSG("NetX Recv NULL parameters");
1049 return WOLFSSL_CBIO_ERR_GENERAL;
1052 if (nxCtx->nxPacket == NULL) {
1053 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1055 if (status != NX_SUCCESS) {
1056 WOLFSSL_MSG("NetX Recv receive error");
1057 return WOLFSSL_CBIO_ERR_GENERAL;
1061 if (nxCtx->nxPacket) {
1062 status = nx_packet_length_get(nxCtx->nxPacket, &total);
1063 if (status != NX_SUCCESS) {
1064 WOLFSSL_MSG("NetX Recv length get error");
1065 return WOLFSSL_CBIO_ERR_GENERAL;
1068 left = total - nxCtx->nxOffset;
1069 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1071 if (status != NX_SUCCESS) {
1072 WOLFSSL_MSG("NetX Recv data extract offset error");
1073 return WOLFSSL_CBIO_ERR_GENERAL;
1076 nxCtx->nxOffset += copied;
1078 if (copied == left) {
1079 WOLFSSL_MSG("NetX Recv Drained packet");
1080 nx_packet_release(nxCtx->nxPacket);
1081 nxCtx->nxPacket = NULL;
1082 nxCtx->nxOffset = 0;
1090 /* The NetX send callback
1091 * return : bytes sent, or error
1093 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1095 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1097 NX_PACKET_POOL* pool; /* shorthand */
1100 if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1101 WOLFSSL_MSG("NetX Send NULL parameters");
1102 return WOLFSSL_CBIO_ERR_GENERAL;
1105 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1106 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1108 if (status != NX_SUCCESS) {
1109 WOLFSSL_MSG("NetX Send packet alloc error");
1110 return WOLFSSL_CBIO_ERR_GENERAL;
1113 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
1114 if (status != NX_SUCCESS) {
1115 nx_packet_release(packet);
1116 WOLFSSL_MSG("NetX Send data append error");
1117 return WOLFSSL_CBIO_ERR_GENERAL;
1120 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
1121 if (status != NX_SUCCESS) {
1122 nx_packet_release(packet);
1123 WOLFSSL_MSG("NetX Send socket send error");
1124 return WOLFSSL_CBIO_ERR_GENERAL;
1131 /* like set_fd, but for default NetX context */
1132 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1135 ssl->nxCtx.nxSocket = nxSocket;
1136 ssl->nxCtx.nxWait = waitOption;
1140 #endif /* HAVE_NETX */