]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/src/io.c
Update WolfSSL library to the latest version.
[freertos] / FreeRTOS-Plus / Source / WolfSSL / src / io.c
1 /* io.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
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-1301, USA
20  */
21
22
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26
27 #include <wolfssl/wolfcrypt/settings.h>
28
29 #ifdef _WIN32_WCE
30     /* On WinCE winsock2.h must be included before windows.h for socket stuff */
31     #include <winsock2.h>
32 #endif
33
34 #include <wolfssl/internal.h>
35 #include <wolfssl/error-ssl.h>
36
37
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 
41 */
42 #ifndef WOLFSSL_USER_IO
43
44 #ifdef HAVE_LIBZ
45     #include "zlib.h"
46 #endif
47
48 #ifndef USE_WINDOWS_API
49     #ifdef WOLFSSL_LWIP
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"
53         #include <errno.h>
54         #ifndef LWIP_PROVIDE_ERRNO
55             #define LWIP_PROVIDE_ERRNO 1
56         #endif
57     #elif defined(FREESCALE_MQX)
58         #include <posix.h>
59         #include <rtcs.h>
60     #elif defined(WOLFSSL_MDK_ARM)
61         #if defined(WOLFSSL_MDK5)
62             #include "cmsis_os.h"
63             #include "rl_fs.h" 
64             #include "rl_net.h" 
65         #else
66             #include <rtl.h>
67         #endif
68         #undef RNG
69         #include "WOLFSSL_MDK_ARM.h"
70         #undef RNG
71         #define RNG wolfSSL_RNG 
72         /* for avoiding name conflict in "stm32f2xx.h" */
73         static int errno;
74     #elif defined(WOLFSSL_TIRTOS)
75         #include <sys/socket.h>
76     #elif defined(WOLFSSL_IAR_ARM)
77         /* nothing */
78     #else
79         #include <sys/types.h>
80         #include <errno.h>
81         #ifndef EBSNET
82             #include <unistd.h>
83         #endif
84         #include <fcntl.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>
90             #include <netdb.h>
91             #ifdef __PPU
92                 #include <netex/errno.h>
93             #else
94                 #include <sys/ioctl.h>
95             #endif
96         #endif
97         #ifdef HAVE_RTP_SYS
98             #include <socket.h>
99         #endif
100         #ifdef EBSNET
101             #include "rtipapi.h"  /* errno */
102             #include "socket.h"
103         #endif
104     #endif
105 #endif /* USE_WINDOWS_API */
106
107 #ifdef __sun
108     #include <sys/filio.h>
109 #endif
110
111 #ifdef USE_WINDOWS_API 
112     /* no epipe yet */
113     #ifndef WSAEPIPE
114         #define WSAEPIPE       -12345
115     #endif
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)
124 #elif defined(__PPU)
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
150     #else
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
158     #endif
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
167 #else
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 */
176
177
178 #ifdef DEVKITPRO
179     /* from network.h */
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
190 #else
191     #define SEND_FUNCTION send
192     #define RECV_FUNCTION recv
193 #endif
194
195
196 /* Translates return codes returned from 
197  * send() and recv() if need be. 
198  */
199 static INLINE int TranslateReturnCode(int old, int sd)
200 {
201     (void)sd;
202
203 #ifdef FREESCALE_MQX
204     if (old == 0) {
205         errno = SOCKET_EWOULDBLOCK;
206         return -1;  /* convert to BSD style wouldblock as error */
207     }
208
209     if (old < 0) {
210         errno = RTCS_geterror(sd);
211         if (errno == RTCSERR_TCP_CONN_CLOSING)
212             return 0;   /* convert to BSD style closing */
213     }
214 #endif
215
216     return old;
217 }
218
219 static INLINE int LastError(void)
220 {
221 #ifdef USE_WINDOWS_API 
222     return WSAGetLastError();
223 #elif defined(EBSNET)
224     return xn_getlasterror();
225 #else
226     return errno;
227 #endif
228 }
229
230 /* The receive embedded callback
231  *  return : nb bytes read, or error
232  */
233 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
234 {
235     int recvd;
236     int err;
237     int sd = *(int*)ctx;
238
239 #ifdef WOLFSSL_DTLS
240     {
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;
247             #else
248                 struct timeval timeout;
249                 XMEMSET(&timeout, 0, sizeof(timeout));
250                 timeout.tv_sec = dtls_timeout;
251             #endif
252             if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
253                            sizeof(timeout)) != 0) {
254                 WOLFSSL_MSG("setsockopt rcvtimeo failed");
255             }
256         }
257     }
258 #endif
259
260     recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags);
261
262     recvd = TranslateReturnCode(recvd, sd);
263
264     if (recvd < 0) {
265         err = LastError();
266         WOLFSSL_MSG("Embed Receive error");
267
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;
272             }
273             else {
274                 WOLFSSL_MSG("    Socket timeout");
275                 return WOLFSSL_CBIO_ERR_TIMEOUT;
276             }
277         }
278         else if (err == SOCKET_ECONNRESET) {
279             WOLFSSL_MSG("    Connection reset");
280             return WOLFSSL_CBIO_ERR_CONN_RST;
281         }
282         else if (err == SOCKET_EINTR) {
283             WOLFSSL_MSG("    Socket interrupted");
284             return WOLFSSL_CBIO_ERR_ISR;
285         }
286         else if (err == SOCKET_ECONNREFUSED) {
287             WOLFSSL_MSG("    Connection refused");
288             return WOLFSSL_CBIO_ERR_WANT_READ;
289         }
290         else if (err == SOCKET_ECONNABORTED) {
291             WOLFSSL_MSG("    Connection aborted");
292             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
293         }
294         else {
295             WOLFSSL_MSG("    General error");
296             return WOLFSSL_CBIO_ERR_GENERAL;
297         }
298     }
299     else if (recvd == 0) {
300         WOLFSSL_MSG("Embed receive connection closed");
301         return WOLFSSL_CBIO_ERR_CONN_CLOSE;
302     }
303
304     return recvd;
305 }
306
307 /* The send embedded callback
308  *  return : nb bytes sent, or error
309  */
310 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
311 {
312     int sd = *(int*)ctx;
313     int sent;
314     int len = sz;
315     int err;
316
317     sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags);
318
319     if (sent < 0) {
320         err = LastError();
321         WOLFSSL_MSG("Embed Send error");
322
323         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
324             WOLFSSL_MSG("    Would Block");
325             return WOLFSSL_CBIO_ERR_WANT_WRITE;
326         }
327         else if (err == SOCKET_ECONNRESET) {
328             WOLFSSL_MSG("    Connection reset");
329             return WOLFSSL_CBIO_ERR_CONN_RST;
330         }
331         else if (err == SOCKET_EINTR) {
332             WOLFSSL_MSG("    Socket interrupted");
333             return WOLFSSL_CBIO_ERR_ISR;
334         }
335         else if (err == SOCKET_EPIPE) {
336             WOLFSSL_MSG("    Socket EPIPE");
337             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
338         }
339         else {
340             WOLFSSL_MSG("    General error");
341             return WOLFSSL_CBIO_ERR_GENERAL;
342         }
343     }
344  
345     return sent;
346 }
347
348
349 #ifdef WOLFSSL_DTLS
350
351 #include <wolfssl/wolfcrypt/sha.h>
352
353 #ifdef USE_WINDOWS_API
354    #define XSOCKLENT int
355 #else
356    #define XSOCKLENT socklen_t
357 #endif
358
359 #define SENDTO_FUNCTION sendto
360 #define RECVFROM_FUNCTION recvfrom
361
362
363 /* The receive embedded callback
364  *  return : nb bytes read, or error
365  */
366 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
367 {
368     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
369     int recvd;
370     int err;
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);
375
376     WOLFSSL_ENTER("EmbedReceiveFrom()");
377
378     if (!wolfSSL_get_using_nonblock(ssl) && dtls_timeout != 0) {
379         #ifdef USE_WINDOWS_API
380             DWORD timeout = dtls_timeout * 1000;
381         #else
382             struct timeval timeout;
383             XMEMSET(&timeout, 0, sizeof(timeout));
384             timeout.tv_sec = dtls_timeout;
385         #endif
386         if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
387                        sizeof(timeout)) != 0) {
388                 WOLFSSL_MSG("setsockopt rcvtimeo failed");
389         }
390     }
391
392     recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
393                                   (struct sockaddr*)&peer, &peerSz);
394
395     recvd = TranslateReturnCode(recvd, sd);
396
397     if (recvd < 0) {
398         err = LastError();
399         WOLFSSL_MSG("Embed Receive From error");
400
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;
405             }
406             else {
407                 WOLFSSL_MSG("    Socket timeout");
408                 return WOLFSSL_CBIO_ERR_TIMEOUT;
409             }
410         }
411         else if (err == SOCKET_ECONNRESET) {
412             WOLFSSL_MSG("    Connection reset");
413             return WOLFSSL_CBIO_ERR_CONN_RST;
414         }
415         else if (err == SOCKET_EINTR) {
416             WOLFSSL_MSG("    Socket interrupted");
417             return WOLFSSL_CBIO_ERR_ISR;
418         }
419         else if (err == SOCKET_ECONNREFUSED) {
420             WOLFSSL_MSG("    Connection refused");
421             return WOLFSSL_CBIO_ERR_WANT_READ;
422         }
423         else {
424             WOLFSSL_MSG("    General error");
425             return WOLFSSL_CBIO_ERR_GENERAL;
426         }
427     }
428     else {
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;
434         }
435     }
436
437     return recvd;
438 }
439
440
441 /* The send embedded callback
442  *  return : nb bytes sent, or error
443  */
444 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
445 {
446     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
447     int sd = dtlsCtx->fd;
448     int sent;
449     int len = sz;
450     int err;
451
452     WOLFSSL_ENTER("EmbedSendTo()");
453
454     sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
455                                 (const struct sockaddr*)dtlsCtx->peer.sa,
456                                 dtlsCtx->peer.sz);
457     if (sent < 0) {
458         err = LastError();
459         WOLFSSL_MSG("Embed Send To error");
460
461         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
462             WOLFSSL_MSG("    Would Block");
463             return WOLFSSL_CBIO_ERR_WANT_WRITE;
464         }
465         else if (err == SOCKET_ECONNRESET) {
466             WOLFSSL_MSG("    Connection reset");
467             return WOLFSSL_CBIO_ERR_CONN_RST;
468         }
469         else if (err == SOCKET_EINTR) {
470             WOLFSSL_MSG("    Socket interrupted");
471             return WOLFSSL_CBIO_ERR_ISR;
472         }
473         else if (err == SOCKET_EPIPE) {
474             WOLFSSL_MSG("    Socket EPIPE");
475             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
476         }
477         else {
478             WOLFSSL_MSG("    General error");
479             return WOLFSSL_CBIO_ERR_GENERAL;
480         }
481     }
482  
483     return sent;
484 }
485
486
487 /* The DTLS Generate Cookie callback
488  *  return : number of bytes copied into buf, or error
489  */
490 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
491 {
492     int sd = ssl->wfd;
493     struct sockaddr_storage peer;
494     XSOCKLENT peerSz = sizeof(peer);
495     byte digest[SHA_DIGEST_SIZE];
496     int  ret = 0;
497
498     (void)ctx;
499
500     XMEMSET(&peer, 0, sizeof(peer));
501     if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) {
502         WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
503         return GEN_COOKIE_E;
504     }
505
506     ret = wc_ShaHash((byte*)&peer, peerSz, digest);
507     if (ret != 0)
508         return ret;
509
510     if (sz > SHA_DIGEST_SIZE)
511         sz = SHA_DIGEST_SIZE;
512     XMEMCPY(buf, digest, sz);
513
514     return sz;
515 }
516
517 #endif /* WOLFSSL_DTLS */
518
519 #ifdef HAVE_OCSP
520
521
522 static int Word16ToString(char* d, word16 number)
523 {
524     int i = 0;
525
526     if (d != NULL) {
527         word16 order = 10000;
528         word16 digit;
529
530         if (number == 0) {
531             d[i++] = '0';
532         }
533         else {
534             while (order) {
535                 digit = number / order;
536                 if (i > 0 || digit != 0) {
537                     d[i++] = (char)digit + '0';
538                 }
539                 if (digit != 0)
540                     number %= digit * order;
541                 if (order > 1)
542                     order /= 10;
543                 else
544                     order = 0;
545             }
546         }
547         d[i] = 0;
548     }
549
550     return i;
551 }
552
553
554 static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
555 {
556     struct sockaddr_storage addr;
557     int sockaddr_len = sizeof(struct sockaddr_in);
558     XMEMSET(&addr, 0, sizeof(addr));
559
560     #ifdef HAVE_GETADDRINFO
561     {
562         struct addrinfo hints;
563         struct addrinfo* answer = NULL;
564         char strPort[6];
565
566         XMEMSET(&hints, 0, sizeof(hints));
567         hints.ai_family = AF_UNSPEC;
568         hints.ai_socktype = SOCK_STREAM;
569         hints.ai_protocol = IPPROTO_TCP;
570
571         if (Word16ToString(strPort, port) == 0) {
572             WOLFSSL_MSG("invalid port number for OCSP responder");
573             return -1;
574         }
575
576         if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
577             WOLFSSL_MSG("no addr info for OCSP responder");
578             return -1;
579         }
580
581         sockaddr_len = answer->ai_addrlen;
582         XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
583         freeaddrinfo(answer);
584
585     }
586     #else /* HAVE_GETADDRINFO */
587     {
588         struct hostent* entry = gethostbyname(ip);
589         struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
590
591         if (entry) {
592             sin->sin_family = AF_INET;
593             sin->sin_port = htons(port);
594             XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
595                                                                entry->h_length);
596         }
597         else {
598             WOLFSSL_MSG("no addr info for OCSP responder");
599             return -1;
600         }
601     }
602     #endif /* HAVE_GETADDRINFO */
603
604     *sockfd = socket(addr.ss_family, SOCK_STREAM, 0);
605
606 #ifdef USE_WINDOWS_API
607     if (*sockfd == INVALID_SOCKET) {
608         WOLFSSL_MSG("bad socket fd, out of fds?");
609         return -1;
610     }
611 #else
612      if (*sockfd < 0) {
613          WOLFSSL_MSG("bad socket fd, out of fds?");
614          return -1;
615      }
616 #endif
617
618     if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) {
619         WOLFSSL_MSG("OCSP responder tcp connect failed");
620         return -1;
621     }
622
623     return 0;
624 }
625
626
627 static int build_http_request(const char* domainName, const char* path,
628                                     int ocspReqSz, byte* buf, int bufSize)
629 {
630     word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen;
631     char ocspReqSzStr[6];
632
633     domainNameLen = (word32)XSTRLEN(domainName);
634     pathLen = (word32)XSTRLEN(path);
635     ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz);
636
637     completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84;
638     if (completeLen > (word32)bufSize)
639         return 0;
640
641     XSTRNCPY((char*)buf, "POST ", 5);
642     buf += 5;
643     XSTRNCPY((char*)buf, path, pathLen);
644     buf += pathLen;
645     XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17);
646     buf += 17;
647     XSTRNCPY((char*)buf, domainName, domainNameLen);
648     buf += domainNameLen;
649     XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18);
650     buf += 18;
651     XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen);
652     buf += ocspReqSzStrLen;
653     XSTRNCPY((char*)buf,
654                       "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44);
655
656     return completeLen;
657 }
658
659
660 static int decode_url(const char* url, int urlSz,
661     char* outName, char* outPath, word16* outPort)
662 {
663     int result = -1;
664
665     if (outName != NULL && outPath != NULL && outPort != NULL)
666     {
667         if (url == NULL || urlSz == 0)
668         {
669             *outName = 0;
670             *outPath = 0;
671             *outPort = 0;
672         }
673         else
674         {
675             int i, cur;
676     
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) {
681                 cur = 7;
682             } else cur = 0;
683     
684             i = 0;
685             if (url[cur] == '[') {
686                 cur++;
687                 /* copy until ']' */
688                 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
689                     outName[i++] = url[cur++];
690                 }
691                 cur++; /* skip ']' */
692             }
693             else {
694                 while (url[cur] != 0 && url[cur] != ':' &&
695                                                url[cur] != '/' && cur < urlSz) {
696                     outName[i++] = url[cur++];
697                 }
698             }
699             outName[i] = 0;
700             /* Need to pick out the path after the domain name */
701     
702             if (cur < urlSz && url[cur] == ':') {
703                 char port[6];
704                 int j;
705                 word32 bigPort = 0;
706                 i = 0;
707                 cur++;
708                 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
709                         i < 6) {
710                     port[i++] = url[cur++];
711                 }
712     
713                 for (j = 0; j < i; j++) {
714                     if (port[j] < '0' || port[j] > '9') return -1;
715                     bigPort = (bigPort * 10) + (port[j] - '0');
716                 }
717                 *outPort = (word16)bigPort;
718             }
719             else
720                 *outPort = 80;
721     
722             if (cur < urlSz && url[cur] == '/') {
723                 i = 0;
724                 while (cur < urlSz && url[cur] != 0 && i < 80) {
725                     outPath[i++] = url[cur++];
726                 }
727                 outPath[i] = 0;
728             }
729             else {
730                 outPath[0] = '/';
731                 outPath[1] = 0;
732             }
733             result = 0;
734         }
735     }
736
737     return result;
738 }
739
740
741 /* return: >0 OCSP Response Size
742  *         -1 error */
743 static int process_http_response(int sfd, byte** respBuf,
744                                                   byte* httpBuf, int httpBufSz)
745 {
746     int result;
747     int len = 0;
748     char *start, *end;
749     byte *recvBuf = NULL;
750     int recvBufSz = 0;
751     enum phr_state { phr_init, phr_http_start, phr_have_length,
752                      phr_have_type, phr_wait_end, phr_http_end
753     } state = phr_init;
754
755     start = end = NULL;
756     do {
757         if (end == NULL) {
758             result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
759             if (result > 0) {
760                 len += result;
761                 start = (char*)httpBuf;
762                 start[len] = 0;
763             }
764             else {
765                 WOLFSSL_MSG("process_http_response recv http from peer failed");
766                 return -1;
767             }
768         }
769         end = XSTRSTR(start, "\r\n");
770
771         if (end == NULL) {
772             if (len != 0)
773                 XMEMMOVE(httpBuf, start, len);
774             start = end = NULL;
775         }
776         else if (end == start) {
777             if (state == phr_wait_end) {
778                 state = phr_http_end;
779                 len -= 2;
780                 start += 2;
781              }
782              else {
783                 WOLFSSL_MSG("process_http_response header ended early");
784                 return -1;
785              }
786         }
787         else {
788             *end = 0;
789             len -= (int)(end - start) + 2;
790                 /* adjust len to remove the first line including the /r/n */
791
792             if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
793                 start += 9;
794                 if (XSTRNCASECMP(start, "200 OK", 6) != 0 ||
795                                                            state != phr_init) {
796                     WOLFSSL_MSG("process_http_response not OK");
797                     return -1;
798                 }
799                 state = phr_http_start;
800             }
801             else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
802                 start += 13;
803                 while (*start == ' ' && *start != '\0') start++;
804                 if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) {
805                     WOLFSSL_MSG("process_http_response not ocsp-response");
806                     return -1;
807                 }
808                 
809                 if (state == phr_http_start) state = phr_have_type;
810                 else if (state == phr_have_length) state = phr_wait_end;
811                 else {
812                     WOLFSSL_MSG("process_http_response type invalid state");
813                     return -1;
814                 }
815             }
816             else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
817                 start += 15;
818                 while (*start == ' ' && *start != '\0') start++;
819                 recvBufSz = atoi(start);
820
821                 if (state == phr_http_start) state = phr_have_length;
822                 else if (state == phr_have_type) state = phr_wait_end;
823                 else {
824                     WOLFSSL_MSG("process_http_response length invalid state");
825                     return -1;
826                 }
827             }
828             
829             start = end + 2;
830         }
831     } while (state != phr_http_end);
832
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");
836         return -1;
837     }
838
839     /* copy the remainder of the httpBuf into the respBuf */
840     if (len != 0)
841         XMEMCPY(recvBuf, start, len);
842
843     /* receive the OCSP response data */
844     do {
845         result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0);
846         if (result > 0)
847             len += result;
848         else {
849             WOLFSSL_MSG("process_http_response recv ocsp from peer failed");
850             return -1;
851         }
852     } while (len != recvBufSz);
853
854     *respBuf = recvBuf;
855     return recvBufSz;
856 }
857
858
859 #define SCRATCH_BUFFER_SIZE 512
860
861 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
862                         byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
863 {
864     SOCKET_T sfd = 0;
865     word16   port;
866     int      ret = -1;
867 #ifdef WOLFSSL_SMALL_STACK
868     char*    path;
869     char*    domainName;
870 #else
871     char     path[80];
872     char     domainName[80];
873 #endif
874
875 #ifdef WOLFSSL_SMALL_STACK
876     path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
877     if (path == NULL)
878         return -1;
879     
880     domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
881     if (domainName == NULL) {
882         XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
883         return -1;
884     }
885 #endif
886
887     (void)ctx;
888
889     if (ocspReqBuf == NULL || ocspReqSz == 0) {
890         WOLFSSL_MSG("OCSP request is required for lookup");
891     }
892     else if (ocspRespBuf == NULL) {
893         WOLFSSL_MSG("Cannot save OCSP response");
894     }
895     else if (decode_url(url, urlSz, domainName, path, &port) < 0) {
896         WOLFSSL_MSG("Unable to decode OCSP URL");
897     }
898     else {
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);
904
905         if (httpBuf == NULL) {
906             WOLFSSL_MSG("Unable to create OCSP response buffer");
907         }
908         else {
909             httpBufSz = build_http_request(domainName, path, ocspReqSz,
910                                                             httpBuf, httpBufSz);
911
912             if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) {
913                 WOLFSSL_MSG("OCSP Responder connection failed");
914             }
915             else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) !=
916                                                                     httpBufSz) {
917                 WOLFSSL_MSG("OCSP http request failed");
918             }
919             else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
920                                                                     ocspReqSz) {
921                 WOLFSSL_MSG("OCSP ocsp request failed");
922             }
923             else {
924                 ret = process_http_response(sfd, ocspRespBuf, httpBuf,
925                                                            SCRATCH_BUFFER_SIZE);
926             }
927
928             close(sfd);
929             XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER);
930         }
931     }
932
933 #ifdef WOLFSSL_SMALL_STACK
934     XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
935     XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
936 #endif
937
938     return ret;
939 }
940
941
942 void EmbedOcspRespFree(void* ctx, byte *resp)
943 {
944     (void)ctx;
945
946     if (resp)
947         XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER);
948 }
949
950
951 #endif
952
953 #endif /* WOLFSSL_USER_IO */
954
955 WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
956 {
957     ctx->CBIORecv = CBIORecv;
958 }
959
960
961 WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
962 {
963     ctx->CBIOSend = CBIOSend;
964 }
965
966
967 WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
968 {
969         ssl->IOCB_ReadCtx = rctx;
970 }
971
972
973 WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
974 {
975         ssl->IOCB_WriteCtx = wctx;
976 }
977
978
979 WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
980 {
981     if (ssl)
982         return ssl->IOCB_ReadCtx;
983
984     return NULL;
985 }
986
987
988 WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
989 {
990     if (ssl)
991         return ssl->IOCB_WriteCtx;
992
993     return NULL;
994 }
995
996
997 WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
998 {
999     ssl->rflags = flags; 
1000 }
1001
1002
1003 WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
1004 {
1005     ssl->wflags = flags;
1006 }
1007
1008
1009 #ifdef WOLFSSL_DTLS
1010
1011 WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
1012 {
1013     ctx->CBIOCookie = cb;
1014 }
1015
1016
1017 WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
1018 {
1019         ssl->IOCB_CookieCtx = ctx;
1020 }
1021
1022
1023 WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
1024 {
1025     if (ssl)
1026             return ssl->IOCB_CookieCtx;
1027
1028     return NULL;
1029 }
1030
1031 #endif /* WOLFSSL_DTLS */
1032
1033
1034 #ifdef HAVE_NETX
1035
1036 /* The NetX receive callback
1037  *  return :  bytes read, or error
1038  */
1039 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
1040 {
1041     NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
1042     ULONG left;
1043     ULONG total;
1044     ULONG copied = 0;
1045     UINT  status;
1046
1047     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1048         WOLFSSL_MSG("NetX Recv NULL parameters");
1049         return WOLFSSL_CBIO_ERR_GENERAL;
1050     }
1051
1052     if (nxCtx->nxPacket == NULL) {
1053         status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
1054                                        nxCtx->nxWait);
1055         if (status != NX_SUCCESS) {
1056             WOLFSSL_MSG("NetX Recv receive error");
1057             return WOLFSSL_CBIO_ERR_GENERAL;
1058         }
1059     }
1060
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;
1066         }
1067
1068         left = total - nxCtx->nxOffset;
1069         status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
1070                                                buf, sz, &copied);
1071         if (status != NX_SUCCESS) {
1072             WOLFSSL_MSG("NetX Recv data extract offset error");
1073             return WOLFSSL_CBIO_ERR_GENERAL;
1074         }
1075
1076         nxCtx->nxOffset += copied;
1077
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;
1083         }
1084     }
1085
1086     return copied;
1087 }
1088
1089
1090 /* The NetX send callback
1091  *  return : bytes sent, or error
1092  */
1093 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
1094 {
1095     NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
1096     NX_PACKET*      packet;
1097     NX_PACKET_POOL* pool;   /* shorthand */
1098     UINT            status;
1099
1100     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
1101         WOLFSSL_MSG("NetX Send NULL parameters");
1102         return WOLFSSL_CBIO_ERR_GENERAL;
1103     }
1104
1105     pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
1106     status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
1107                                 nxCtx->nxWait);
1108     if (status != NX_SUCCESS) {
1109         WOLFSSL_MSG("NetX Send packet alloc error");
1110         return WOLFSSL_CBIO_ERR_GENERAL;
1111     }
1112
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;
1118     }
1119
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;
1125     }
1126
1127     return sz;
1128 }
1129
1130
1131 /* like set_fd, but for default NetX context */
1132 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
1133 {
1134     if (ssl) {
1135         ssl->nxCtx.nxSocket = nxSocket;
1136         ssl->nxCtx.nxWait   = waitOption;
1137     }
1138 }
1139
1140 #endif /* HAVE_NETX */
1141