Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers io.c Source File

io.c

00001 /* io.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 
00024 #ifdef HAVE_CONFIG_H
00025     #include <config.h>
00026 #endif
00027 
00028 #include <wolfssl/wolfcrypt/settings.h>
00029 
00030 #ifndef WOLFCRYPT_ONLY
00031 
00032 #ifdef _WIN32_WCE
00033     /* On WinCE winsock2.h must be included before windows.h for socket stuff */
00034     #include <winsock2.h>
00035 #endif
00036 
00037 #include <wolfssl/internal.h>
00038 #include <wolfssl/error-ssl.h>
00039 
00040 
00041 /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
00042    automatic setting of default I/O functions EmbedSend() and EmbedReceive()
00043    but they'll still need SetCallback xxx() at end of file
00044 */
00045 #ifndef WOLFSSL_USER_IO
00046 
00047 #ifdef HAVE_LIBZ
00048     #include "zlib.h"
00049 #endif
00050 
00051 #ifndef USE_WINDOWS_API
00052     #ifdef WOLFSSL_LWIP
00053         /* lwIP needs to be configured to use sockets API in this mode */
00054         /* LWIP_SOCKET 1 in lwip/opt.h or in build */
00055         #include "lwip/sockets.h"
00056         #include <errno.h>
00057         #ifndef LWIP_PROVIDE_ERRNO
00058             #define LWIP_PROVIDE_ERRNO 1
00059         #endif
00060     #elif defined(FREESCALE_MQX)
00061         #include <posix.h>
00062         #include <rtcs.h>
00063     #elif defined(FREESCALE_KSDK_MQX)
00064         #include <rtcs.h>
00065     #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
00066         #if !defined(WOLFSSL_MDK_ARM)
00067             #include "cmsis_os.h"
00068             #include "rl_net.h"
00069         #else
00070             #include <rtl.h>
00071         #endif
00072         #include "errno.h"
00073         #define SOCKET_T int
00074     #elif defined(WOLFSSL_TIRTOS)
00075         #include <sys/socket.h>
00076     #elif defined(FREERTOS_TCP)
00077         #include "FreeRTOS_Sockets.h"
00078     #elif defined(WOLFSSL_IAR_ARM)
00079         /* nothing */
00080     #elif defined(WOLFSSL_VXWORKS)
00081         #include <sockLib.h>
00082         #include <errno.h>
00083     #else
00084         #include <sys/types.h>
00085         #include <errno.h>
00086         #ifndef EBSNET
00087             #include <unistd.h>
00088         #endif
00089         #include <fcntl.h>
00090 
00091         #if defined(HAVE_RTP_SYS)
00092             #include <socket.h>
00093         #elif defined(EBSNET)
00094             #include "rtipapi.h"  /* errno */
00095             #include "socket.h"
00096         #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP)
00097             #include <sys/socket.h>
00098             #include <arpa/inet.h>
00099             #include <netinet/in.h>
00100             #include <netdb.h>
00101             #ifdef __PPU
00102                 #include <netex/errno.h>
00103             #else
00104                 #include <sys/ioctl.h>
00105             #endif
00106         #endif
00107     #endif
00108 #endif /* USE_WINDOWS_API */
00109 
00110 #ifdef __sun
00111     #include <sys/filio.h>
00112 #endif
00113 
00114 #ifdef USE_WINDOWS_API
00115     /* no epipe yet */
00116     #ifndef WSAEPIPE
00117         #define WSAEPIPE       -12345
00118     #endif
00119     #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
00120     #define SOCKET_EAGAIN      WSAETIMEDOUT
00121     #define SOCKET_ECONNRESET  WSAECONNRESET
00122     #define SOCKET_EINTR       WSAEINTR
00123     #define SOCKET_EPIPE       WSAEPIPE
00124     #define SOCKET_ECONNREFUSED WSAENOTCONN
00125     #define SOCKET_ECONNABORTED WSAECONNABORTED
00126     #define close(s) closesocket(s)
00127 #elif defined(__PPU)
00128     #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
00129     #define SOCKET_EAGAIN      SYS_NET_EAGAIN
00130     #define SOCKET_ECONNRESET  SYS_NET_ECONNRESET
00131     #define SOCKET_EINTR       SYS_NET_EINTR
00132     #define SOCKET_EPIPE       SYS_NET_EPIPE
00133     #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED
00134     #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED
00135 #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00136     #if MQX_USE_IO_OLD
00137         /* RTCS old I/O doesn't have an EWOULDBLOCK */
00138         #define SOCKET_EWOULDBLOCK  EAGAIN
00139         #define SOCKET_EAGAIN       EAGAIN
00140         #define SOCKET_ECONNRESET   RTCSERR_TCP_CONN_RESET
00141         #define SOCKET_EINTR        EINTR
00142         #define SOCKET_EPIPE        EPIPE
00143         #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED
00144         #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED
00145     #else
00146         #define SOCKET_EWOULDBLOCK  NIO_EWOULDBLOCK
00147         #define SOCKET_EAGAIN       NIO_EAGAIN
00148         #define SOCKET_ECONNRESET   NIO_ECONNRESET
00149         #define SOCKET_EINTR        NIO_EINTR
00150         #define SOCKET_EPIPE        NIO_EPIPE
00151         #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED
00152         #define SOCKET_ECONNABORTED NIO_ECONNABORTED
00153     #endif
00154 #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET)
00155     #if !defined(WOLFSSL_MDK_ARM)
00156         #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK
00157         #define SOCKET_EAGAIN      BSD_ERROR_LOCKED
00158         #define SOCKET_ECONNRESET  BSD_ERROR_CLOSED
00159         #define SOCKET_EINTR       BSD_ERROR
00160         #define SOCKET_EPIPE       BSD_ERROR
00161         #define SOCKET_ECONNREFUSED BSD_ERROR
00162         #define SOCKET_ECONNABORTED BSD_ERROR
00163     #else
00164         #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK
00165         #define SOCKET_EAGAIN      SCK_ELOCKED
00166         #define SOCKET_ECONNRESET  SCK_ECLOSED
00167         #define SOCKET_EINTR       SCK_ERROR
00168         #define SOCKET_EPIPE       SCK_ERROR
00169         #define SOCKET_ECONNREFUSED SCK_ERROR
00170         #define SOCKET_ECONNABORTED SCK_ERROR
00171     #endif
00172 #elif defined(WOLFSSL_PICOTCP)
00173     #define SOCKET_EWOULDBLOCK  PICO_ERR_EAGAIN
00174     #define SOCKET_EAGAIN       PICO_ERR_EAGAIN
00175     #define SOCKET_ECONNRESET   PICO_ERR_ECONNRESET
00176     #define SOCKET_EINTR        PICO_ERR_EINTR
00177     #define SOCKET_EPIPE        PICO_ERR_EIO
00178     #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED
00179     #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN
00180 #elif defined(FREERTOS_TCP)
00181     #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK
00182     #define SOCKET_EAGAIN       FREERTOS_EWOULDBLOCK
00183     #define SOCKET_ECONNRESET   FREERTOS_SOCKET_ERROR
00184     #define SOCKET_EINTR        FREERTOS_SOCKET_ERROR
00185     #define SOCKET_EPIPE        FREERTOS_SOCKET_ERROR
00186     #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR
00187     #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR
00188 #else
00189     #define SOCKET_EWOULDBLOCK EWOULDBLOCK
00190     #define SOCKET_EAGAIN      EAGAIN
00191     #define SOCKET_ECONNRESET  ECONNRESET
00192     #define SOCKET_EINTR       EINTR
00193     #define SOCKET_EPIPE       EPIPE
00194     #define SOCKET_ECONNREFUSED ECONNREFUSED
00195     #define SOCKET_ECONNABORTED ECONNABORTED
00196 #endif /* USE_WINDOWS_API */
00197 
00198 
00199 #ifdef DEVKITPRO
00200     /* from network.h */
00201     int net_send(int, const void*, int, unsigned int);
00202     int net_recv(int, void*, int, unsigned int);
00203     #define SEND_FUNCTION net_send
00204     #define RECV_FUNCTION net_recv
00205 #elif defined(WOLFSSL_LWIP)
00206     #define SEND_FUNCTION lwip_send
00207     #define RECV_FUNCTION lwip_recv
00208 #elif defined(WOLFSSL_PICOTCP)
00209     #define SEND_FUNCTION pico_send
00210     #define RECV_FUNCTION pico_recv
00211 #elif defined(FREERTOS_TCP)
00212     #define RECV_FUNCTION(a,b,c,d)  FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d))
00213     #define SEND_FUNCTION(a,b,c,d)  FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d))
00214 #else
00215     #define SEND_FUNCTION send
00216     #define RECV_FUNCTION recv
00217 #endif
00218 
00219 
00220 /* Translates return codes returned from
00221  * send() and recv() if need be.
00222  */
00223 static INLINE int TranslateReturnCode(int old, int sd)
00224 {
00225     (void)sd;
00226 
00227 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00228     if (old == 0) {
00229         errno = SOCKET_EWOULDBLOCK;
00230         return -1;  /* convert to BSD style wouldblock as error */
00231     }
00232 
00233     if (old < 0) {
00234         errno = RTCS_geterror(sd);
00235         if (errno == RTCSERR_TCP_CONN_CLOSING)
00236             return 0;   /* convert to BSD style closing */
00237         if (errno == RTCSERR_TCP_CONN_RLSD)
00238             errno = SOCKET_ECONNRESET;
00239         if (errno == RTCSERR_TCP_TIMED_OUT)
00240             errno = SOCKET_EAGAIN;
00241     }
00242 #endif
00243 
00244     return old;
00245 }
00246 
00247 static INLINE int LastError(void)
00248 {
00249 #ifdef USE_WINDOWS_API
00250     return WSAGetLastError();
00251 #elif defined(EBSNET)
00252     return xn_getlasterror();
00253 #else
00254     return errno;
00255 #endif
00256 }
00257 
00258 /* The receive embedded callback
00259  *  return : nb bytes read, or error
00260  */
00261 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
00262 {
00263     int recvd;
00264     int err;
00265     int sd = *(int*)ctx;
00266 
00267 #ifdef WOLFSSL_DTLS
00268     {
00269         int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
00270         if (wolfSSL_dtls(ssl)
00271                      && !wolfSSL_get_using_nonblock(ssl)
00272                      && dtls_timeout != 0) {
00273             #ifdef USE_WINDOWS_API
00274                 DWORD timeout = dtls_timeout * 1000;
00275             #else
00276                 struct timeval timeout;
00277                 XMEMSET(&timeout, 0, sizeof(timeout));
00278                 timeout.tv_sec = dtls_timeout;
00279             #endif
00280             if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
00281                            sizeof(timeout)) != 0) {
00282                 WOLFSSL_MSG("setsockopt rcvtimeo failed");
00283             }
00284         }
00285     }
00286 #endif
00287 
00288     recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags);
00289 
00290     recvd = TranslateReturnCode(recvd, sd);
00291 
00292     if (recvd < 0) {
00293         err = LastError();
00294         WOLFSSL_MSG("Embed Receive error");
00295 
00296         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00297             if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) {
00298                 WOLFSSL_MSG("    Would block");
00299                 return WOLFSSL_CBIO_ERR_WANT_READ;
00300             }
00301             else {
00302                 WOLFSSL_MSG("    Socket timeout");
00303                 return WOLFSSL_CBIO_ERR_TIMEOUT;
00304             }
00305         }
00306         else if (err == SOCKET_ECONNRESET) {
00307             WOLFSSL_MSG("    Connection reset");
00308             return WOLFSSL_CBIO_ERR_CONN_RST;
00309         }
00310         else if (err == SOCKET_EINTR) {
00311             WOLFSSL_MSG("    Socket interrupted");
00312             return WOLFSSL_CBIO_ERR_ISR;
00313         }
00314         else if (err == SOCKET_ECONNREFUSED) {
00315             WOLFSSL_MSG("    Connection refused");
00316             return WOLFSSL_CBIO_ERR_WANT_READ;
00317         }
00318         else if (err == SOCKET_ECONNABORTED) {
00319             WOLFSSL_MSG("    Connection aborted");
00320             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00321         }
00322         else {
00323             WOLFSSL_MSG("    General error");
00324             return WOLFSSL_CBIO_ERR_GENERAL;
00325         }
00326     }
00327     else if (recvd == 0) {
00328         WOLFSSL_MSG("Embed receive connection closed");
00329         return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00330     }
00331 
00332     return recvd;
00333 }
00334 
00335 /* The send embedded callback
00336  *  return : nb bytes sent, or error
00337  */
00338 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
00339 {
00340     int sd = *(int*)ctx;
00341     int sent;
00342     int len = sz;
00343     int err;
00344 
00345     sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags);
00346 
00347     sent = TranslateReturnCode(sent, sd);
00348 
00349     if (sent < 0) {
00350         err = LastError();
00351         WOLFSSL_MSG("Embed Send error");
00352 
00353         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00354             WOLFSSL_MSG("    Would Block");
00355             return WOLFSSL_CBIO_ERR_WANT_WRITE;
00356         }
00357         else if (err == SOCKET_ECONNRESET) {
00358             WOLFSSL_MSG("    Connection reset");
00359             return WOLFSSL_CBIO_ERR_CONN_RST;
00360         }
00361         else if (err == SOCKET_EINTR) {
00362             WOLFSSL_MSG("    Socket interrupted");
00363             return WOLFSSL_CBIO_ERR_ISR;
00364         }
00365         else if (err == SOCKET_EPIPE) {
00366             WOLFSSL_MSG("    Socket EPIPE");
00367             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00368         }
00369         else {
00370             WOLFSSL_MSG("    General error");
00371             return WOLFSSL_CBIO_ERR_GENERAL;
00372         }
00373     }
00374 
00375     return sent;
00376 }
00377 
00378 
00379 #ifdef WOLFSSL_DTLS
00380 
00381 #include <wolfssl/wolfcrypt/sha.h>
00382 
00383 #ifdef USE_WINDOWS_API
00384    #define XSOCKLENT int
00385 #else
00386    #define XSOCKLENT socklen_t
00387 #endif
00388 
00389 #define SENDTO_FUNCTION sendto
00390 #define RECVFROM_FUNCTION recvfrom
00391 
00392 
00393 /* The receive embedded callback
00394  *  return : nb bytes read, or error
00395  */
00396 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
00397 {
00398     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
00399     int recvd;
00400     int err;
00401     int sd = dtlsCtx->fd;
00402     int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
00403     struct sockaddr_storage peer;
00404     XSOCKLENT peerSz = sizeof(peer);
00405 
00406     WOLFSSL_ENTER("EmbedReceiveFrom()");
00407 
00408     if (ssl->options.handShakeDone)
00409         dtls_timeout = 0;
00410 
00411     if (!wolfSSL_get_using_nonblock(ssl)) {
00412         #ifdef USE_WINDOWS_API
00413             DWORD timeout = dtls_timeout * 1000;
00414         #else
00415             struct timeval timeout;
00416             XMEMSET(&timeout, 0, sizeof(timeout));
00417             timeout.tv_sec = dtls_timeout;
00418         #endif
00419         if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
00420                        sizeof(timeout)) != 0) {
00421                 WOLFSSL_MSG("setsockopt rcvtimeo failed");
00422         }
00423     }
00424 
00425     recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
00426                                   (struct sockaddr*)&peer, &peerSz);
00427 
00428     recvd = TranslateReturnCode(recvd, sd);
00429 
00430     if (recvd < 0) {
00431         err = LastError();
00432         WOLFSSL_MSG("Embed Receive From error");
00433 
00434         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00435             if (wolfSSL_get_using_nonblock(ssl)) {
00436                 WOLFSSL_MSG("    Would block");
00437                 return WOLFSSL_CBIO_ERR_WANT_READ;
00438             }
00439             else {
00440                 WOLFSSL_MSG("    Socket timeout");
00441                 return WOLFSSL_CBIO_ERR_TIMEOUT;
00442             }
00443         }
00444         else if (err == SOCKET_ECONNRESET) {
00445             WOLFSSL_MSG("    Connection reset");
00446             return WOLFSSL_CBIO_ERR_CONN_RST;
00447         }
00448         else if (err == SOCKET_EINTR) {
00449             WOLFSSL_MSG("    Socket interrupted");
00450             return WOLFSSL_CBIO_ERR_ISR;
00451         }
00452         else if (err == SOCKET_ECONNREFUSED) {
00453             WOLFSSL_MSG("    Connection refused");
00454             return WOLFSSL_CBIO_ERR_WANT_READ;
00455         }
00456         else {
00457             WOLFSSL_MSG("    General error");
00458             return WOLFSSL_CBIO_ERR_GENERAL;
00459         }
00460     }
00461     else {
00462         if (dtlsCtx->peer.sz > 0
00463                 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
00464                 && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
00465             WOLFSSL_MSG("    Ignored packet from invalid peer");
00466             return WOLFSSL_CBIO_ERR_WANT_READ;
00467         }
00468     }
00469 
00470     return recvd;
00471 }
00472 
00473 
00474 /* The send embedded callback
00475  *  return : nb bytes sent, or error
00476  */
00477 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
00478 {
00479     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
00480     int sd = dtlsCtx->fd;
00481     int sent;
00482     int len = sz;
00483     int err;
00484 
00485     WOLFSSL_ENTER("EmbedSendTo()");
00486 
00487     sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
00488                                 (const struct sockaddr*)dtlsCtx->peer.sa,
00489                                 dtlsCtx->peer.sz);
00490 
00491     sent = TranslateReturnCode(sent, sd);
00492 
00493     if (sent < 0) {
00494         err = LastError();
00495         WOLFSSL_MSG("Embed Send To error");
00496 
00497         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00498             WOLFSSL_MSG("    Would Block");
00499             return WOLFSSL_CBIO_ERR_WANT_WRITE;
00500         }
00501         else if (err == SOCKET_ECONNRESET) {
00502             WOLFSSL_MSG("    Connection reset");
00503             return WOLFSSL_CBIO_ERR_CONN_RST;
00504         }
00505         else if (err == SOCKET_EINTR) {
00506             WOLFSSL_MSG("    Socket interrupted");
00507             return WOLFSSL_CBIO_ERR_ISR;
00508         }
00509         else if (err == SOCKET_EPIPE) {
00510             WOLFSSL_MSG("    Socket EPIPE");
00511             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00512         }
00513         else {
00514             WOLFSSL_MSG("    General error");
00515             return WOLFSSL_CBIO_ERR_GENERAL;
00516         }
00517     }
00518 
00519     return sent;
00520 }
00521 
00522 
00523 /* The DTLS Generate Cookie callback
00524  *  return : number of bytes copied into buf, or error
00525  */
00526 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
00527 {
00528     int sd = ssl->wfd;
00529     struct sockaddr_storage peer;
00530     XSOCKLENT peerSz = sizeof(peer);
00531     byte digest[SHA_DIGEST_SIZE];
00532     int  ret = 0;
00533 
00534     (void)ctx;
00535 
00536     XMEMSET(&peer, 0, sizeof(peer));
00537     if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) {
00538         WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
00539         return GEN_COOKIE_E;
00540     }
00541 
00542     ret = wc_ShaHash((byte*)&peer, peerSz, digest);
00543     if (ret != 0)
00544         return ret;
00545 
00546     if (sz > SHA_DIGEST_SIZE)
00547         sz = SHA_DIGEST_SIZE;
00548     XMEMCPY(buf, digest, sz);
00549 
00550     return sz;
00551 }
00552 
00553 #endif /* WOLFSSL_DTLS */
00554 
00555 #ifdef HAVE_OCSP
00556 
00557 #include <stdlib.h>   /* atoi() */
00558 
00559 
00560 static int Word16ToString(char* d, word16 number)
00561 {
00562     int i = 0;
00563 
00564     if (d != NULL) {
00565         word16 order = 10000;
00566         word16 digit;
00567 
00568         if (number == 0) {
00569             d[i++] = '0';
00570         }
00571         else {
00572             while (order) {
00573                 digit = number / order;
00574                 if (i > 0 || digit != 0) {
00575                     d[i++] = (char)digit + '0';
00576                 }
00577                 if (digit != 0)
00578                     number %= digit * order;
00579                 if (order > 1)
00580                     order /= 10;
00581                 else
00582                     order = 0;
00583             }
00584         }
00585         d[i] = 0;
00586     }
00587 
00588     return i;
00589 }
00590 
00591 
00592 static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
00593 {
00594     struct sockaddr_storage addr;
00595     int sockaddr_len = sizeof(struct sockaddr_in);
00596     XMEMSET(&addr, 0, sizeof(addr));
00597 
00598     #ifdef HAVE_GETADDRINFO
00599     {
00600         struct addrinfo hints;
00601         struct addrinfo* answer = NULL;
00602         char strPort[6];
00603 
00604         XMEMSET(&hints, 0, sizeof(hints));
00605         hints.ai_family = AF_UNSPEC;
00606         hints.ai_socktype = SOCK_STREAM;
00607         hints.ai_protocol = IPPROTO_TCP;
00608 
00609         if (Word16ToString(strPort, port) == 0) {
00610             WOLFSSL_MSG("invalid port number for OCSP responder");
00611             return -1;
00612         }
00613 
00614         if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
00615             WOLFSSL_MSG("no addr info for OCSP responder");
00616             return -1;
00617         }
00618 
00619         sockaddr_len = answer->ai_addrlen;
00620         XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
00621         freeaddrinfo(answer);
00622 
00623     }
00624     #else /* HAVE_GETADDRINFO */
00625     {
00626         struct hostent* entry = gethostbyname(ip);
00627         struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
00628 
00629         if (entry) {
00630             sin->sin_family = AF_INET;
00631             sin->sin_port = htons(port);
00632             XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0],
00633                                                                entry->h_length);
00634         }
00635         else {
00636             WOLFSSL_MSG("no addr info for OCSP responder");
00637             return -1;
00638         }
00639     }
00640     #endif /* HAVE_GETADDRINFO */
00641 
00642     *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
00643 
00644 #ifdef USE_WINDOWS_API
00645     if (*sockfd == INVALID_SOCKET) {
00646         WOLFSSL_MSG("bad socket fd, out of fds?");
00647         return -1;
00648     }
00649 #else
00650      if (*sockfd < 0) {
00651          WOLFSSL_MSG("bad socket fd, out of fds?");
00652          return -1;
00653      }
00654 #endif
00655 
00656     if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) {
00657         WOLFSSL_MSG("OCSP responder tcp connect failed");
00658         return -1;
00659     }
00660 
00661     return 0;
00662 }
00663 
00664 
00665 static int build_http_request(const char* domainName, const char* path,
00666                                     int ocspReqSz, byte* buf, int bufSize)
00667 {
00668     word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen;
00669     char ocspReqSzStr[6];
00670 
00671     domainNameLen = (word32)XSTRLEN(domainName);
00672     pathLen = (word32)XSTRLEN(path);
00673     ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz);
00674 
00675     completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84;
00676     if (completeLen > (word32)bufSize)
00677         return 0;
00678 
00679     XSTRNCPY((char*)buf, "POST ", 5);
00680     buf += 5;
00681     XSTRNCPY((char*)buf, path, pathLen);
00682     buf += pathLen;
00683     XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17);
00684     buf += 17;
00685     XSTRNCPY((char*)buf, domainName, domainNameLen);
00686     buf += domainNameLen;
00687     XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18);
00688     buf += 18;
00689     XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen);
00690     buf += ocspReqSzStrLen;
00691     XSTRNCPY((char*)buf,
00692                       "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44);
00693 
00694     return completeLen;
00695 }
00696 
00697 
00698 static int decode_url(const char* url, int urlSz,
00699     char* outName, char* outPath, word16* outPort)
00700 {
00701     int result = -1;
00702 
00703     if (outName != NULL && outPath != NULL && outPort != NULL)
00704     {
00705         if (url == NULL || urlSz == 0)
00706         {
00707             *outName = 0;
00708             *outPath = 0;
00709             *outPort = 0;
00710         }
00711         else
00712         {
00713             int i, cur;
00714 
00715             /* need to break the url down into scheme, address, and port */
00716             /*     "http://example.com:8080/" */
00717             /*     "http://[::1]:443/"        */
00718             if (XSTRNCMP(url, "http://", 7) == 0) {
00719                 cur = 7;
00720             } else cur = 0;
00721 
00722             i = 0;
00723             if (url[cur] == '[') {
00724                 cur++;
00725                 /* copy until ']' */
00726                 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
00727                     outName[i++] = url[cur++];
00728                 }
00729                 cur++; /* skip ']' */
00730             }
00731             else {
00732                 while (url[cur] != 0 && url[cur] != ':' &&
00733                                                url[cur] != '/' && cur < urlSz) {
00734                     outName[i++] = url[cur++];
00735                 }
00736             }
00737             outName[i] = 0;
00738             /* Need to pick out the path after the domain name */
00739 
00740             if (cur < urlSz && url[cur] == ':') {
00741                 char port[6];
00742                 int j;
00743                 word32 bigPort = 0;
00744                 i = 0;
00745                 cur++;
00746                 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
00747                         i < 6) {
00748                     port[i++] = url[cur++];
00749                 }
00750 
00751                 for (j = 0; j < i; j++) {
00752                     if (port[j] < '0' || port[j] > '9') return -1;
00753                     bigPort = (bigPort * 10) + (port[j] - '0');
00754                 }
00755                 *outPort = (word16)bigPort;
00756             }
00757             else
00758                 *outPort = 80;
00759 
00760             if (cur < urlSz && url[cur] == '/') {
00761                 i = 0;
00762                 while (cur < urlSz && url[cur] != 0 && i < 80) {
00763                     outPath[i++] = url[cur++];
00764                 }
00765                 outPath[i] = 0;
00766             }
00767             else {
00768                 outPath[0] = '/';
00769                 outPath[1] = 0;
00770             }
00771             result = 0;
00772         }
00773     }
00774 
00775     return result;
00776 }
00777 
00778 
00779 /* return: >0 OCSP Response Size
00780  *         -1 error */
00781 static int process_http_response(int sfd, byte** respBuf,
00782                                                   byte* httpBuf, int httpBufSz)
00783 {
00784     int result;
00785     int len = 0;
00786     char *start, *end;
00787     byte *recvBuf = NULL;
00788     int recvBufSz = 0;
00789     enum phr_state { phr_init, phr_http_start, phr_have_length,
00790                      phr_have_type, phr_wait_end, phr_http_end
00791     } state = phr_init;
00792 
00793     start = end = NULL;
00794     do {
00795         if (end == NULL) {
00796             result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
00797             if (result > 0) {
00798                 len += result;
00799                 start = (char*)httpBuf;
00800                 start[len] = 0;
00801             }
00802             else {
00803                 WOLFSSL_MSG("process_http_response recv http from peer failed");
00804                 return -1;
00805             }
00806         }
00807         end = XSTRSTR(start, "\r\n");
00808 
00809         if (end == NULL) {
00810             if (len != 0)
00811                 XMEMMOVE(httpBuf, start, len);
00812             start = end = NULL;
00813         }
00814         else if (end == start) {
00815             if (state == phr_wait_end) {
00816                 state = phr_http_end;
00817                 len -= 2;
00818                 start += 2;
00819              }
00820              else {
00821                 WOLFSSL_MSG("process_http_response header ended early");
00822                 return -1;
00823              }
00824         }
00825         else {
00826             *end = 0;
00827             len -= (int)(end - start) + 2;
00828                 /* adjust len to remove the first line including the /r/n */
00829 
00830             if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
00831                 start += 9;
00832                 if (XSTRNCASECMP(start, "200 OK", 6) != 0 ||
00833                                                            state != phr_init) {
00834                     WOLFSSL_MSG("process_http_response not OK");
00835                     return -1;
00836                 }
00837                 state = phr_http_start;
00838             }
00839             else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
00840                 start += 13;
00841                 while (*start == ' ' && *start != '\0') start++;
00842                 if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) {
00843                     WOLFSSL_MSG("process_http_response not ocsp-response");
00844                     return -1;
00845                 }
00846 
00847                 if (state == phr_http_start) state = phr_have_type;
00848                 else if (state == phr_have_length) state = phr_wait_end;
00849                 else {
00850                     WOLFSSL_MSG("process_http_response type invalid state");
00851                     return -1;
00852                 }
00853             }
00854             else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
00855                 start += 15;
00856                 while (*start == ' ' && *start != '\0') start++;
00857                 recvBufSz = atoi(start);
00858 
00859                 if (state == phr_http_start) state = phr_have_length;
00860                 else if (state == phr_have_type) state = phr_wait_end;
00861                 else {
00862                     WOLFSSL_MSG("process_http_response length invalid state");
00863                     return -1;
00864                 }
00865             }
00866 
00867             start = end + 2;
00868         }
00869     } while (state != phr_http_end);
00870 
00871     recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_OCSP);
00872     if (recvBuf == NULL) {
00873         WOLFSSL_MSG("process_http_response couldn't create response buffer");
00874         return -1;
00875     }
00876 
00877     /* copy the remainder of the httpBuf into the respBuf */
00878     if (len != 0)
00879         XMEMCPY(recvBuf, start, len);
00880 
00881     /* receive the OCSP response data */
00882     do {
00883         result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0);
00884         if (result > 0)
00885             len += result;
00886         else {
00887             WOLFSSL_MSG("process_http_response recv ocsp from peer failed");
00888             return -1;
00889         }
00890     } while (len != recvBufSz);
00891 
00892     *respBuf = recvBuf;
00893     return recvBufSz;
00894 }
00895 
00896 
00897 #define SCRATCH_BUFFER_SIZE 512
00898 
00899 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
00900                         byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
00901 {
00902     SOCKET_T sfd = 0;
00903     word16   port;
00904     int      ret = -1;
00905 #ifdef WOLFSSL_SMALL_STACK
00906     char*    path;
00907     char*    domainName;
00908 #else
00909     char     path[80];
00910     char     domainName[80];
00911 #endif
00912 
00913 #ifdef WOLFSSL_SMALL_STACK
00914     path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00915     if (path == NULL)
00916         return -1;
00917 
00918     domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00919     if (domainName == NULL) {
00920         XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00921         return -1;
00922     }
00923 #endif
00924 
00925     (void)ctx;
00926 
00927     if (ocspReqBuf == NULL || ocspReqSz == 0) {
00928         WOLFSSL_MSG("OCSP request is required for lookup");
00929     }
00930     else if (ocspRespBuf == NULL) {
00931         WOLFSSL_MSG("Cannot save OCSP response");
00932     }
00933     else if (decode_url(url, urlSz, domainName, path, &port) < 0) {
00934         WOLFSSL_MSG("Unable to decode OCSP URL");
00935     }
00936     else {
00937         /* Note, the library uses the EmbedOcspRespFree() callback to
00938          * free this buffer. */
00939         int   httpBufSz = SCRATCH_BUFFER_SIZE;
00940         byte* httpBuf   = (byte*)XMALLOC(httpBufSz, NULL,
00941                                                         DYNAMIC_TYPE_OCSP);
00942 
00943         if (httpBuf == NULL) {
00944             WOLFSSL_MSG("Unable to create OCSP response buffer");
00945         }
00946         else {
00947             httpBufSz = build_http_request(domainName, path, ocspReqSz,
00948                                                             httpBuf, httpBufSz);
00949 
00950             if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) {
00951                 WOLFSSL_MSG("OCSP Responder connection failed");
00952             }
00953             else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) !=
00954                                                                     httpBufSz) {
00955                 WOLFSSL_MSG("OCSP http request failed");
00956             }
00957             else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
00958                                                                     ocspReqSz) {
00959                 WOLFSSL_MSG("OCSP ocsp request failed");
00960             }
00961             else {
00962                 ret = process_http_response(sfd, ocspRespBuf, httpBuf,
00963                                                            SCRATCH_BUFFER_SIZE);
00964             }
00965 
00966             close(sfd);
00967             XFREE(httpBuf, NULL, DYNAMIC_TYPE_OCSP);
00968         }
00969     }
00970 
00971 #ifdef WOLFSSL_SMALL_STACK
00972     XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
00973     XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00974 #endif
00975 
00976     return ret;
00977 }
00978 
00979 
00980 void EmbedOcspRespFree(void* ctx, byte *resp)
00981 {
00982     (void)ctx;
00983 
00984     if (resp)
00985         XFREE(resp, NULL, DYNAMIC_TYPE_OCSP);
00986 }
00987 
00988 
00989 #endif
00990 
00991 #endif /* WOLFSSL_USER_IO */
00992 
00993 WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
00994 {
00995     ctx->CBIORecv = CBIORecv;
00996 }
00997 
00998 
00999 WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
01000 {
01001     ctx->CBIOSend = CBIOSend;
01002 }
01003 
01004 
01005 WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
01006 {
01007     ssl->IOCB_ReadCtx = rctx;
01008 }
01009 
01010 
01011 WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
01012 {
01013     ssl->IOCB_WriteCtx = wctx;
01014 }
01015 
01016 
01017 WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
01018 {
01019     if (ssl)
01020         return ssl->IOCB_ReadCtx;
01021 
01022     return NULL;
01023 }
01024 
01025 
01026 WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
01027 {
01028     if (ssl)
01029         return ssl->IOCB_WriteCtx;
01030 
01031     return NULL;
01032 }
01033 
01034 
01035 WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
01036 {
01037     ssl->rflags = flags;
01038 }
01039 
01040 
01041 WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
01042 {
01043     ssl->wflags = flags;
01044 }
01045 
01046 
01047 #ifdef WOLFSSL_DTLS
01048 
01049 WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
01050 {
01051     ctx->CBIOCookie = cb;
01052 }
01053 
01054 
01055 WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
01056 {
01057     ssl->IOCB_CookieCtx = ctx;
01058 }
01059 
01060 
01061 WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
01062 {
01063     if (ssl)
01064         return ssl->IOCB_CookieCtx;
01065 
01066     return NULL;
01067 }
01068 
01069 #endif /* WOLFSSL_DTLS */
01070 
01071 
01072 #ifdef HAVE_NETX
01073 
01074 /* The NetX receive callback
01075  *  return :  bytes read, or error
01076  */
01077 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
01078 {
01079     NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
01080     ULONG left;
01081     ULONG total;
01082     ULONG copied = 0;
01083     UINT  status;
01084 
01085     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
01086         WOLFSSL_MSG("NetX Recv NULL parameters");
01087         return WOLFSSL_CBIO_ERR_GENERAL;
01088     }
01089 
01090     if (nxCtx->nxPacket == NULL) {
01091         status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
01092                                        nxCtx->nxWait);
01093         if (status != NX_SUCCESS) {
01094             WOLFSSL_MSG("NetX Recv receive error");
01095             return WOLFSSL_CBIO_ERR_GENERAL;
01096         }
01097     }
01098 
01099     if (nxCtx->nxPacket) {
01100         status = nx_packet_length_get(nxCtx->nxPacket, &total);
01101         if (status != NX_SUCCESS) {
01102             WOLFSSL_MSG("NetX Recv length get error");
01103             return WOLFSSL_CBIO_ERR_GENERAL;
01104         }
01105 
01106         left = total - nxCtx->nxOffset;
01107         status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
01108                                                buf, sz, &copied);
01109         if (status != NX_SUCCESS) {
01110             WOLFSSL_MSG("NetX Recv data extract offset error");
01111             return WOLFSSL_CBIO_ERR_GENERAL;
01112         }
01113 
01114         nxCtx->nxOffset += copied;
01115 
01116         if (copied == left) {
01117             WOLFSSL_MSG("NetX Recv Drained packet");
01118             nx_packet_release(nxCtx->nxPacket);
01119             nxCtx->nxPacket = NULL;
01120             nxCtx->nxOffset = 0;
01121         }
01122     }
01123 
01124     return copied;
01125 }
01126 
01127 
01128 /* The NetX send callback
01129  *  return : bytes sent, or error
01130  */
01131 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
01132 {
01133     NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
01134     NX_PACKET*      packet;
01135     NX_PACKET_POOL* pool;   /* shorthand */
01136     UINT            status;
01137 
01138     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
01139         WOLFSSL_MSG("NetX Send NULL parameters");
01140         return WOLFSSL_CBIO_ERR_GENERAL;
01141     }
01142 
01143     pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
01144     status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
01145                                 nxCtx->nxWait);
01146     if (status != NX_SUCCESS) {
01147         WOLFSSL_MSG("NetX Send packet alloc error");
01148         return WOLFSSL_CBIO_ERR_GENERAL;
01149     }
01150 
01151     status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
01152     if (status != NX_SUCCESS) {
01153         nx_packet_release(packet);
01154         WOLFSSL_MSG("NetX Send data append error");
01155         return WOLFSSL_CBIO_ERR_GENERAL;
01156     }
01157 
01158     status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
01159     if (status != NX_SUCCESS) {
01160         nx_packet_release(packet);
01161         WOLFSSL_MSG("NetX Send socket send error");
01162         return WOLFSSL_CBIO_ERR_GENERAL;
01163     }
01164 
01165     return sz;
01166 }
01167 
01168 
01169 /* like set_fd, but for default NetX context */
01170 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
01171 {
01172     if (ssl) {
01173         ssl->nxCtx.nxSocket = nxSocket;
01174         ssl->nxCtx.nxWait   = waitOption;
01175     }
01176 }
01177 
01178 #endif /* HAVE_NETX */
01179 #endif /* WOLFCRYPT_ONLY */
01180 
01181