wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wolfio.c Source File

wolfio.c

00001 /* wolfio.c
00002  *
00003  * Copyright (C) 2006-2017 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 <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 #include <wolfssl/wolfio.h >
00040 
00041 #if defined(HAVE_HTTP_CLIENT)
00042     #include <stdlib.h>   /* atoi(), strtol() */
00043 #endif
00044 
00045 /*
00046 Possible IO enable options:
00047  * WOLFSSL_USER_IO:     Disables default Embed* callbacks and     default: off
00048                         allows user to define their own using
00049                         wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend
00050  * USE_WOLFSSL_IO:      Enables the wolfSSL IO functions          default: off
00051  * HAVE_HTTP_CLIENT:    Enables HTTP client API's                 default: off
00052                                      (unless HAVE_OCSP or HAVE_CRL_IO defined)
00053  * HAVE_IO_TIMEOUT:     Enables support for connect timeout       default: off
00054  */
00055 
00056 
00057 /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove
00058    automatic setting of default I/O functions EmbedSend() and EmbedReceive()
00059    but they'll still need SetCallback xxx() at end of file
00060 */
00061 
00062 #if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
00063 
00064 /* Translates return codes returned from
00065  * send() and recv() if need be.
00066  */
00067 static WC_INLINE int TranslateReturnCode(int old, int sd)
00068 {
00069     (void)sd;
00070 
00071 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00072     if (old == 0) {
00073         errno = SOCKET_EWOULDBLOCK;
00074         return -1;  /* convert to BSD style wouldblock as error */
00075     }
00076 
00077     if (old < 0) {
00078         errno = RTCS_geterror(sd);
00079         if (errno == RTCSERR_TCP_CONN_CLOSING)
00080             return 0;   /* convert to BSD style closing */
00081         if (errno == RTCSERR_TCP_CONN_RLSD)
00082             errno = SOCKET_ECONNRESET;
00083         if (errno == RTCSERR_TCP_TIMED_OUT)
00084             errno = SOCKET_EAGAIN;
00085     }
00086 #endif
00087 
00088     return old;
00089 }
00090 
00091 static WC_INLINE int wolfSSL_LastError(void)
00092 {
00093 #ifdef USE_WINDOWS_API
00094     return WSAGetLastError();
00095 #elif defined(EBSNET)
00096     return xn_getlasterror();
00097 #else
00098     return errno;
00099 #endif
00100 }
00101 
00102 #endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */
00103 
00104 
00105 #ifdef OPENSSL_EXTRA
00106 /* Use the WOLFSSL read BIO for receiving data. This is set by the function
00107  * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv.
00108  *
00109  * ssl  WOLFSSL struct passed in that has this function set as the receive
00110  *      callback.
00111  * buf  buffer to fill with data read
00112  * sz   size of buf buffer
00113  * ctx  a user set context
00114  *
00115  * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values.
00116  */
00117 int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx)
00118 {
00119     int recvd = WOLFSSL_CBIO_ERR_GENERAL;
00120 
00121     WOLFSSL_ENTER("BioReceive");
00122 
00123     if (ssl->biord == NULL) {
00124         WOLFSSL_MSG("WOLFSSL biord not set");
00125         return WOLFSSL_CBIO_ERR_GENERAL;
00126     }
00127 
00128     switch (ssl->biord->type) {
00129         case WOLFSSL_BIO_MEMORY:
00130         case WOLFSSL_BIO_BIO:
00131             if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) {
00132                return WOLFSSL_CBIO_ERR_WANT_READ;
00133             }
00134             recvd = wolfSSL_BIO_read(ssl->biord, buf, sz);
00135             if (recvd <= 0) {
00136                 return WOLFSSL_CBIO_ERR_GENERAL;
00137             }
00138             break;
00139 
00140        default:
00141             WOLFSSL_MSG("This BIO type is unknown / unsupported");
00142             return WOLFSSL_CBIO_ERR_GENERAL;
00143     }
00144 
00145     (void)ctx;
00146     return recvd;
00147 }
00148 
00149 
00150 /* Use the WOLFSSL write BIO for sending data. This is set by the function
00151  * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend.
00152  *
00153  * ssl  WOLFSSL struct passed in that has this function set as the send callback.
00154  * buf  buffer with data to write out
00155  * sz   size of buf buffer
00156  * ctx  a user set context
00157  *
00158  * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values.
00159  */
00160 int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
00161 {
00162     int sent = WOLFSSL_CBIO_ERR_GENERAL;
00163 
00164     if (ssl->biowr == NULL) {
00165         WOLFSSL_MSG("WOLFSSL biowr not set\n");
00166         return WOLFSSL_CBIO_ERR_GENERAL;
00167     }
00168 
00169     switch (ssl->biowr->type) {
00170         case WOLFSSL_BIO_MEMORY:
00171         case WOLFSSL_BIO_BIO:
00172             sent = wolfSSL_BIO_write(ssl->biowr, buf, sz);
00173             if (sent < 0) {
00174                 return WOLFSSL_CBIO_ERR_GENERAL;
00175             }
00176             break;
00177 
00178         default:
00179             WOLFSSL_MSG("This BIO type is unknown / unsupported");
00180             return WOLFSSL_CBIO_ERR_GENERAL;
00181     }
00182     (void)ctx;
00183 
00184     return sent;
00185 }
00186 #endif
00187 
00188 
00189 #ifdef USE_WOLFSSL_IO
00190 
00191 /* The receive embedded callback
00192  *  return : nb bytes read, or error
00193  */
00194 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
00195 {
00196     int sd = *(int*)ctx;
00197     int recvd;
00198 
00199     recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags);
00200     if (recvd < 0) {
00201         int err = wolfSSL_LastError();
00202         WOLFSSL_MSG("Embed Receive error");
00203 
00204         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00205             WOLFSSL_MSG("\tWould block");
00206             return WOLFSSL_CBIO_ERR_WANT_READ;
00207         }
00208         else if (err == SOCKET_ECONNRESET) {
00209             WOLFSSL_MSG("\tConnection reset");
00210             return WOLFSSL_CBIO_ERR_CONN_RST;
00211         }
00212         else if (err == SOCKET_EINTR) {
00213             WOLFSSL_MSG("\tSocket interrupted");
00214             return WOLFSSL_CBIO_ERR_ISR;
00215         }
00216         else if (err == SOCKET_ECONNABORTED) {
00217             WOLFSSL_MSG("\tConnection aborted");
00218             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00219         }
00220         else {
00221             WOLFSSL_MSG("\tGeneral error");
00222             return WOLFSSL_CBIO_ERR_GENERAL;
00223         }
00224     }
00225     else if (recvd == 0) {
00226         WOLFSSL_MSG("Embed receive connection closed");
00227         return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00228     }
00229 
00230     return recvd;
00231 }
00232 
00233 /* The send embedded callback
00234  *  return : nb bytes sent, or error
00235  */
00236 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx)
00237 {
00238     int sd = *(int*)ctx;
00239     int sent;
00240 
00241     sent = wolfIO_Send(sd, buf, sz, ssl->wflags);
00242     if (sent < 0) {
00243         int err = wolfSSL_LastError();
00244         WOLFSSL_MSG("Embed Send error");
00245 
00246         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00247             WOLFSSL_MSG("\tWould Block");
00248             return WOLFSSL_CBIO_ERR_WANT_WRITE;
00249         }
00250         else if (err == SOCKET_ECONNRESET) {
00251             WOLFSSL_MSG("\tConnection reset");
00252             return WOLFSSL_CBIO_ERR_CONN_RST;
00253         }
00254         else if (err == SOCKET_EINTR) {
00255             WOLFSSL_MSG("\tSocket interrupted");
00256             return WOLFSSL_CBIO_ERR_ISR;
00257         }
00258         else if (err == SOCKET_EPIPE) {
00259             WOLFSSL_MSG("\tSocket EPIPE");
00260             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00261         }
00262         else {
00263             WOLFSSL_MSG("\tGeneral error");
00264             return WOLFSSL_CBIO_ERR_GENERAL;
00265         }
00266     }
00267 
00268     return sent;
00269 }
00270 
00271 
00272 #ifdef WOLFSSL_DTLS
00273 
00274 #include <wolfssl/wolfcrypt/sha.h>
00275 
00276 #define SENDTO_FUNCTION sendto
00277 #define RECVFROM_FUNCTION recvfrom
00278 
00279 
00280 /* The receive embedded callback
00281  *  return : nb bytes read, or error
00282  */
00283 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
00284 {
00285     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
00286     int recvd;
00287     int err;
00288     int sd = dtlsCtx->rfd;
00289     int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
00290     SOCKADDR_S peer;
00291     XSOCKLENT peerSz = sizeof(peer);
00292 
00293     WOLFSSL_ENTER("EmbedReceiveFrom()");
00294 
00295     if (ssl->options.handShakeDone)
00296         dtls_timeout = 0;
00297 
00298     if (!wolfSSL_get_using_nonblock(ssl)) {
00299         #ifdef USE_WINDOWS_API
00300             DWORD timeout = dtls_timeout * 1000;
00301         #else
00302             struct timeval timeout;
00303             XMEMSET(&timeout, 0, sizeof(timeout));
00304             timeout.tv_sec = dtls_timeout;
00305         #endif
00306         if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
00307                        sizeof(timeout)) != 0) {
00308                 WOLFSSL_MSG("setsockopt rcvtimeo failed");
00309         }
00310     }
00311 
00312     recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
00313                                   (SOCKADDR*)&peer, &peerSz);
00314 
00315     recvd = TranslateReturnCode(recvd, sd);
00316 
00317     if (recvd < 0) {
00318         err = wolfSSL_LastError();
00319         WOLFSSL_MSG("Embed Receive From error");
00320 
00321         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00322             if (wolfSSL_dtls_get_using_nonblock(ssl)) {
00323                 WOLFSSL_MSG("\tWould block");
00324                 return WOLFSSL_CBIO_ERR_WANT_READ;
00325             }
00326             else {
00327                 WOLFSSL_MSG("\tSocket timeout");
00328                 return WOLFSSL_CBIO_ERR_TIMEOUT;
00329             }
00330         }
00331         else if (err == SOCKET_ECONNRESET) {
00332             WOLFSSL_MSG("\tConnection reset");
00333             return WOLFSSL_CBIO_ERR_CONN_RST;
00334         }
00335         else if (err == SOCKET_EINTR) {
00336             WOLFSSL_MSG("\tSocket interrupted");
00337             return WOLFSSL_CBIO_ERR_ISR;
00338         }
00339         else if (err == SOCKET_ECONNREFUSED) {
00340             WOLFSSL_MSG("\tConnection refused");
00341             return WOLFSSL_CBIO_ERR_WANT_READ;
00342         }
00343         else {
00344             WOLFSSL_MSG("\tGeneral error");
00345             return WOLFSSL_CBIO_ERR_GENERAL;
00346         }
00347     }
00348     else {
00349         if (dtlsCtx->peer.sz > 0
00350                 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
00351                 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
00352             WOLFSSL_MSG("    Ignored packet from invalid peer");
00353             return WOLFSSL_CBIO_ERR_WANT_READ;
00354         }
00355     }
00356 
00357     return recvd;
00358 }
00359 
00360 
00361 /* The send embedded callback
00362  *  return : nb bytes sent, or error
00363  */
00364 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
00365 {
00366     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
00367     int sd = dtlsCtx->wfd;
00368     int sent;
00369     int len = sz;
00370     int err;
00371 
00372     WOLFSSL_ENTER("EmbedSendTo()");
00373 
00374     sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
00375                                 (const SOCKADDR*)dtlsCtx->peer.sa,
00376                                 dtlsCtx->peer.sz);
00377 
00378     sent = TranslateReturnCode(sent, sd);
00379 
00380     if (sent < 0) {
00381         err = wolfSSL_LastError();
00382         WOLFSSL_MSG("Embed Send To error");
00383 
00384         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00385             WOLFSSL_MSG("\tWould Block");
00386             return WOLFSSL_CBIO_ERR_WANT_WRITE;
00387         }
00388         else if (err == SOCKET_ECONNRESET) {
00389             WOLFSSL_MSG("\tConnection reset");
00390             return WOLFSSL_CBIO_ERR_CONN_RST;
00391         }
00392         else if (err == SOCKET_EINTR) {
00393             WOLFSSL_MSG("\tSocket interrupted");
00394             return WOLFSSL_CBIO_ERR_ISR;
00395         }
00396         else if (err == SOCKET_EPIPE) {
00397             WOLFSSL_MSG("\tSocket EPIPE");
00398             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
00399         }
00400         else {
00401             WOLFSSL_MSG("\tGeneral error");
00402             return WOLFSSL_CBIO_ERR_GENERAL;
00403         }
00404     }
00405 
00406     return sent;
00407 }
00408 
00409 
00410 #ifdef WOLFSSL_MULTICAST
00411 
00412 /* The alternate receive embedded callback for Multicast
00413  *  return : nb bytes read, or error
00414  */
00415 int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
00416 {
00417     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
00418     int recvd;
00419     int err;
00420     int sd = dtlsCtx->rfd;
00421 
00422     WOLFSSL_ENTER("EmbedReceiveFromMcast()");
00423 
00424     recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL);
00425 
00426     recvd = TranslateReturnCode(recvd, sd);
00427 
00428     if (recvd < 0) {
00429         err = wolfSSL_LastError();
00430         WOLFSSL_MSG("Embed Receive From error");
00431 
00432         if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
00433             if (wolfSSL_dtls_get_using_nonblock(ssl)) {
00434                 WOLFSSL_MSG("\tWould block");
00435                 return WOLFSSL_CBIO_ERR_WANT_READ;
00436             }
00437             else {
00438                 WOLFSSL_MSG("\tSocket timeout");
00439                 return WOLFSSL_CBIO_ERR_TIMEOUT;
00440             }
00441         }
00442         else if (err == SOCKET_ECONNRESET) {
00443             WOLFSSL_MSG("\tConnection reset");
00444             return WOLFSSL_CBIO_ERR_CONN_RST;
00445         }
00446         else if (err == SOCKET_EINTR) {
00447             WOLFSSL_MSG("\tSocket interrupted");
00448             return WOLFSSL_CBIO_ERR_ISR;
00449         }
00450         else if (err == SOCKET_ECONNREFUSED) {
00451             WOLFSSL_MSG("\tConnection refused");
00452             return WOLFSSL_CBIO_ERR_WANT_READ;
00453         }
00454         else {
00455             WOLFSSL_MSG("\tGeneral error");
00456             return WOLFSSL_CBIO_ERR_GENERAL;
00457         }
00458     }
00459 
00460     return recvd;
00461 }
00462 #endif /* WOLFSSL_MULTICAST */
00463 
00464 
00465 /* The DTLS Generate Cookie callback
00466  *  return : number of bytes copied into buf, or error
00467  */
00468 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
00469 {
00470     int sd = ssl->wfd;
00471     SOCKADDR_S peer;
00472     XSOCKLENT peerSz = sizeof(peer);
00473     byte digest[WC_SHA256_DIGEST_SIZE];
00474     int  ret = 0;
00475 
00476     (void)ctx;
00477 
00478     XMEMSET(&peer, 0, sizeof(peer));
00479     if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) {
00480         WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie");
00481         return GEN_COOKIE_E;
00482     }
00483 
00484     ret = wc_Sha256Hash((byte*)&peer, peerSz, digest);
00485     if (ret != 0)
00486         return ret;
00487 
00488     if (sz > WC_SHA256_DIGEST_SIZE)
00489         sz = WC_SHA256_DIGEST_SIZE;
00490     XMEMCPY(buf, digest, sz);
00491 
00492     return sz;
00493 }
00494 
00495 #ifdef WOLFSSL_SESSION_EXPORT
00496 
00497     /* get the peer information in human readable form (ip, port, family)
00498      * default function assumes BSD sockets
00499      * can be overriden with wolfSSL_CTX_SetIOGetPeer
00500      */
00501     int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
00502                                                  unsigned short* port, int* fam)
00503     {
00504         SOCKADDR_S peer;
00505         word32     peerSz;
00506         int        ret;
00507 
00508         if (ssl == NULL || ip == NULL || ipSz == NULL ||
00509                                                   port == NULL || fam == NULL) {
00510             return BAD_FUNC_ARG;
00511         }
00512 
00513         /* get peer information stored in ssl struct */
00514         peerSz = sizeof(SOCKADDR_S);
00515         if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
00516                                                                != WOLFSSL_SUCCESS) {
00517             return ret;
00518         }
00519 
00520         /* extract family, ip, and port */
00521         *fam = ((SOCKADDR_S*)&peer)->ss_family;
00522         switch (*fam) {
00523             case WOLFSSL_IP4:
00524                 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
00525                                                            ip, *ipSz) == NULL) {
00526                     WOLFSSL_MSG("XINET_NTOP error");
00527                     return SOCKET_ERROR_E;
00528                 }
00529                 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
00530                 break;
00531 
00532             case WOLFSSL_IP6:
00533             #ifdef WOLFSSL_IPV6
00534                 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
00535                                                            ip, *ipSz) == NULL) {
00536                     WOLFSSL_MSG("XINET_NTOP error");
00537                     return SOCKET_ERROR_E;
00538                 }
00539                 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
00540             #endif /* WOLFSSL_IPV6 */
00541                 break;
00542 
00543             default:
00544                 WOLFSSL_MSG("Unknown family type");
00545                 return SOCKET_ERROR_E;
00546         }
00547         ip[*ipSz - 1] = '\0'; /* make sure has terminator */
00548         *ipSz = (word16)XSTRLEN(ip);
00549 
00550         return WOLFSSL_SUCCESS;
00551     }
00552 
00553     /* set the peer information in human readable form (ip, port, family)
00554      * default function assumes BSD sockets
00555      * can be overriden with wolfSSL_CTX_SetIOSetPeer
00556      */
00557     int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
00558                                                    unsigned short port, int fam)
00559     {
00560         int    ret;
00561         SOCKADDR_S addr;
00562 
00563         /* sanity checks on arguments */
00564         if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
00565             return BAD_FUNC_ARG;
00566         }
00567 
00568         addr.ss_family = fam;
00569         switch (addr.ss_family) {
00570             case WOLFSSL_IP4:
00571                 if (XINET_PTON(addr.ss_family, ip,
00572                                      &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
00573                     WOLFSSL_MSG("XINET_PTON error");
00574                     return SOCKET_ERROR_E;
00575                 }
00576                 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
00577 
00578                 /* peer sa is free'd in SSL_ResourceFree */
00579                 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
00580                                           sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) {
00581                     WOLFSSL_MSG("Import DTLS peer info error");
00582                     return ret;
00583                 }
00584                 break;
00585 
00586             case WOLFSSL_IP6:
00587             #ifdef WOLFSSL_IPV6
00588                 if (XINET_PTON(addr.ss_family, ip,
00589                                    &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
00590                     WOLFSSL_MSG("XINET_PTON error");
00591                     return SOCKET_ERROR_E;
00592                 }
00593                 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
00594 
00595                 /* peer sa is free'd in SSL_ResourceFree */
00596                 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
00597                                          sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) {
00598                     WOLFSSL_MSG("Import DTLS peer info error");
00599                     return ret;
00600                 }
00601             #endif /* WOLFSSL_IPV6 */
00602                 break;
00603 
00604             default:
00605                 WOLFSSL_MSG("Unknown address family");
00606                 return BUFFER_E;
00607         }
00608 
00609         return WOLFSSL_SUCCESS;
00610     }
00611 #endif /* WOLFSSL_SESSION_EXPORT */
00612 #endif /* WOLFSSL_DTLS */
00613 
00614 
00615 int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags)
00616 {
00617     int recvd;
00618 
00619     recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags);
00620     recvd = TranslateReturnCode(recvd, sd);
00621 
00622     return recvd;
00623 }
00624 
00625 int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags)
00626 {
00627     int sent;
00628 
00629     sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags);
00630     sent = TranslateReturnCode(sent, sd);
00631 
00632     return sent;
00633 }
00634 
00635 #endif /* USE_WOLFSSL_IO */
00636 
00637 
00638 #ifdef HAVE_HTTP_CLIENT
00639 
00640 #ifndef HAVE_IO_TIMEOUT
00641     #define io_timeout_sec 0
00642 #else
00643 
00644     #ifndef DEFAULT_TIMEOUT_SEC
00645         #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */
00646     #endif
00647 
00648     static int io_timeout_sec = DEFAULT_TIMEOUT_SEC;
00649 
00650     void wolfIO_SetTimeout(int to_sec)
00651     {
00652         io_timeout_sec = to_sec;
00653     }
00654 
00655     int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking)
00656     {
00657         int ret = 0;
00658 
00659     #ifdef USE_WINDOWS_API
00660         unsigned long blocking = non_blocking;
00661         ret = ioctlsocket(sockfd, FIONBIO, &blocking);
00662         if (ret == SOCKET_ERROR)
00663             ret = -1;
00664     #else
00665         ret = fcntl(sockfd, F_GETFL, 0);
00666         if (ret >= 0) {
00667             if (non_blocking)
00668                 ret |= O_NONBLOCK;
00669             else
00670                 ret &= ~O_NONBLOCK;
00671             ret = fcntl(sockfd, F_SETFL, ret);
00672         }
00673     #endif
00674         if (ret < 0) {
00675             WOLFSSL_MSG("wolfIO_SetBlockingMode failed");
00676         }
00677 
00678         return ret;
00679     }
00680 
00681     int wolfIO_Select(SOCKET_T sockfd, int to_sec)
00682     {
00683         fd_set rfds, wfds;
00684         int nfds = 0;
00685         struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
00686         int ret;
00687 
00688     #ifndef USE_WINDOWS_API
00689         nfds = (int)sockfd + 1;
00690     #endif
00691 
00692         FD_ZERO(&rfds);
00693         FD_SET(sockfd, &rfds);
00694         wfds = rfds;
00695 
00696         ret = select(nfds, &rfds, &wfds, NULL, &timeout);
00697         if (ret == 0) {
00698         #ifdef DEBUG_HTTP
00699             printf("Timeout: %d\n", ret);
00700         #endif
00701             return HTTP_TIMEOUT;
00702         }
00703         else if (ret > 0) {
00704             if (FD_ISSET(sockfd, &wfds)) {
00705                 if (!FD_ISSET(sockfd, &rfds)) {
00706                     return 0;
00707                 }
00708             }
00709         }
00710         return SOCKET_ERROR_E;
00711     }
00712 #endif /* HAVE_IO_TIMEOUT */
00713 
00714 static int wolfIO_Word16ToString(char* d, word16 number)
00715 {
00716     int i = 0;
00717     word16 order = 10000;
00718     word16 digit;
00719 
00720     if (d == NULL)
00721         return i;
00722 
00723     if (number == 0)
00724         d[i++] = '0';
00725     else {
00726         while (order) {
00727             digit = number / order;
00728             if (i > 0 || digit != 0)
00729                 d[i++] = (char)digit + '0';
00730             if (digit != 0)
00731                 number %= digit * order;
00732 
00733             order = (order > 1) ? order / 10 : 0;
00734         }
00735     }
00736     d[i] = 0; /* null terminate */
00737 
00738     return i;
00739 }
00740 
00741 int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec)
00742 {
00743 #ifdef HAVE_SOCKADDR
00744     int ret = 0;
00745     SOCKADDR_S addr;
00746     int sockaddr_len = sizeof(SOCKADDR_IN);
00747 #ifdef HAVE_GETADDRINFO
00748     ADDRINFO hints;
00749     ADDRINFO* answer = NULL;
00750     char strPort[6];
00751 #else
00752     HOSTENT* entry;
00753     SOCKADDR_IN *sin;
00754 #endif
00755 
00756     XMEMSET(&addr, 0, sizeof(addr));
00757 
00758 #ifdef WOLFIO_DEBUG
00759     printf("TCP Connect: %s:%d\n", ip, port);
00760 #endif
00761 
00762 #ifdef HAVE_GETADDRINFO
00763     XMEMSET(&hints, 0, sizeof(hints));
00764     hints.ai_family = AF_UNSPEC;
00765     hints.ai_socktype = SOCK_STREAM;
00766     hints.ai_protocol = IPPROTO_TCP;
00767 
00768     if (wolfIO_Word16ToString(strPort, port) == 0) {
00769         WOLFSSL_MSG("invalid port number for responder");
00770         return -1;
00771     }
00772 
00773     if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) {
00774         WOLFSSL_MSG("no addr info for responder");
00775         return -1;
00776     }
00777 
00778     sockaddr_len = answer->ai_addrlen;
00779     XMEMCPY(&addr, answer->ai_addr, sockaddr_len);
00780     freeaddrinfo(answer);
00781 #else
00782     entry = gethostbyname(ip);
00783     sin = (SOCKADDR_IN *)&addr;
00784 
00785     if (entry) {
00786         sin->sin_family = AF_INET;
00787         sin->sin_port = XHTONS(port);
00788         XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length);
00789     }
00790     else {
00791         WOLFSSL_MSG("no addr info for responder");
00792         return -1;
00793     }
00794 #endif
00795 
00796     *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0);
00797 
00798 #ifdef USE_WINDOWS_API
00799     if (*sockfd == INVALID_SOCKET) {
00800         WOLFSSL_MSG("bad socket fd, out of fds?");
00801         return -1;
00802     }
00803 #else
00804      if (*sockfd < 0) {
00805          WOLFSSL_MSG("bad socket fd, out of fds?");
00806          return -1;
00807      }
00808 #endif
00809 
00810 #ifdef HAVE_IO_TIMEOUT
00811     /* if timeout value provided then set socket non-blocking */
00812     if (to_sec > 0) {
00813         wolfIO_SetBlockingMode(*sockfd, 1);
00814     }
00815 #else
00816     (void)to_sec;
00817 #endif
00818 
00819     ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len);
00820 #ifdef HAVE_IO_TIMEOUT
00821     if (ret != 0) {
00822         if ((errno == EINPROGRESS) && (to_sec > 0)) {
00823             /* wait for connect to complete */
00824             ret = wolfIO_Select(*sockfd, to_sec);
00825 
00826             /* restore blocking mode */
00827             wolfIO_SetBlockingMode(*sockfd, 0);
00828         }
00829     }
00830 #endif
00831     if (ret != 0) {
00832         WOLFSSL_MSG("Responder tcp connect failed");
00833         return -1;
00834     }
00835     return ret;
00836 #else
00837     (void)sockfd;
00838     (void)ip;
00839     (void)port;
00840     (void)to_sec;
00841     return -1;
00842 #endif /* HAVE_SOCKADDR */
00843 }
00844 
00845 #ifndef HTTP_SCRATCH_BUFFER_SIZE
00846     #define HTTP_SCRATCH_BUFFER_SIZE 512
00847 #endif
00848 #ifndef MAX_URL_ITEM_SIZE
00849     #define MAX_URL_ITEM_SIZE   80
00850 #endif
00851 
00852 int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath,
00853     word16* outPort)
00854 {
00855     int result = -1;
00856 
00857     if (url == NULL || urlSz == 0) {
00858         if (outName)
00859             *outName = 0;
00860         if (outPath)
00861             *outPath = 0;
00862         if (outPort)
00863             *outPort = 0;
00864     }
00865     else {
00866         int i, cur;
00867 
00868         /* need to break the url down into scheme, address, and port */
00869         /*     "http://example.com:8080/" */
00870         /*     "http://[::1]:443/"        */
00871         if (XSTRNCMP(url, "http://", 7) == 0) {
00872             cur = 7;
00873         } else cur = 0;
00874 
00875         i = 0;
00876         if (url[cur] == '[') {
00877             cur++;
00878             /* copy until ']' */
00879             while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) {
00880                 if (outName)
00881                     outName[i] = url[cur];
00882                 i++; cur++;
00883             }
00884             cur++; /* skip ']' */
00885         }
00886         else {
00887             while (url[cur] != 0 && url[cur] != ':' &&
00888                                            url[cur] != '/' && cur < urlSz) {
00889                 if (outName)
00890                     outName[i] = url[cur];
00891                 i++; cur++;
00892             }
00893         }
00894         if (outName)
00895             outName[i] = 0;
00896         /* Need to pick out the path after the domain name */
00897 
00898         if (cur < urlSz && url[cur] == ':') {
00899             char port[6];
00900             int j;
00901             word32 bigPort = 0;
00902             i = 0;
00903             cur++;
00904             while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
00905                     i < 6) {
00906                 port[i++] = url[cur++];
00907             }
00908 
00909             for (j = 0; j < i; j++) {
00910                 if (port[j] < '0' || port[j] > '9') return -1;
00911                 bigPort = (bigPort * 10) + (port[j] - '0');
00912             }
00913             if (outPort)
00914                 *outPort = (word16)bigPort;
00915         }
00916         else if (outPort)
00917             *outPort = 80;
00918 
00919 
00920         if (cur < urlSz && url[cur] == '/') {
00921             i = 0;
00922             while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) {
00923                 if (outPath)
00924                     outPath[i] = url[cur];
00925                 i++; cur++;
00926             }
00927             if (outPath)
00928                 outPath[i] = 0;
00929         }
00930         else if (outPath) {
00931             outPath[0] = '/';
00932             outPath[1] = 0;
00933         }
00934 
00935         result = 0;
00936     }
00937 
00938     return result;
00939 }
00940 
00941 static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz,
00942     int chunkSz, char* start, int len, int dynType, void* heap)
00943 {
00944     byte* newRecvBuf = NULL;
00945     int newRecvSz = *recvBufSz + chunkSz;
00946     int pos = 0;
00947 
00948     WOLFSSL_MSG("Processing HTTP response");
00949 #ifdef WOLFIO_DEBUG
00950     printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz);
00951 #endif
00952 
00953     newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType);
00954     if (newRecvBuf == NULL) {
00955         WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed");
00956         return MEMORY_E;
00957     }
00958 
00959     /* if buffer already exists, then we are growing it */
00960     if (*recvBuf) {
00961         XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz);
00962         XFREE(*recvBuf, heap, dynType);
00963         pos += *recvBufSz;
00964         *recvBuf = NULL;
00965     }
00966 
00967     /* copy the remainder of the httpBuf into the respBuf */
00968     if (len != 0) {
00969         XMEMCPY(&newRecvBuf[pos], start, len);
00970         pos += len;
00971     }
00972 
00973     /* receive the remainder of chunk */
00974     while (len < chunkSz) {
00975         int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0);
00976         if (rxSz > 0) {
00977             len += rxSz;
00978             pos += rxSz;
00979         }
00980         else {
00981             WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed");
00982             XFREE(newRecvBuf, heap, dynType);
00983             return -1;
00984         }
00985     }
00986 
00987     *recvBuf = newRecvBuf;
00988     *recvBufSz = newRecvSz;
00989 
00990     return 0;
00991 }
00992 
00993 int wolfIO_HttpProcessResponse(int sfd, const char** appStrList,
00994     byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap)
00995 {
00996     int result = 0;
00997     int len = 0;
00998     char *start, *end;
00999     int respBufSz = 0;
01000     int isChunked = 0, chunkSz = 0;
01001     enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type,
01002                      phr_wait_end, phr_get_chunk_len, phr_get_chunk_data,
01003                      phr_http_end
01004     } state = phr_init;
01005 
01006     *respBuf = NULL;
01007     start = end = NULL;
01008     do {
01009         if (state == phr_get_chunk_data) {
01010             /* get chunk of data */
01011             result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz,
01012                 chunkSz, start, len, dynType, heap);
01013 
01014             state = (result != 0) ? phr_http_end : phr_get_chunk_len;
01015             end = NULL;
01016             len = 0;
01017         }
01018 
01019         /* read data if no \r\n or first time */
01020         if (end == NULL) {
01021             result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0);
01022             if (result > 0) {
01023                 len += result;
01024                 start = (char*)httpBuf;
01025                 start[len] = 0;
01026             }
01027             else {
01028                 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed");
01029                 return -1;
01030             }
01031         }
01032         end = XSTRSTR(start, "\r\n"); /* locate end */
01033 
01034         /* handle incomplete rx */
01035         if (end == NULL) {
01036             if (len != 0)
01037                 XMEMMOVE(httpBuf, start, len);
01038             start = end = NULL;
01039         }
01040         /* when start is "\r\n" */
01041         else if (end == start) {
01042             /* if waiting for end or need chunk len */
01043             if (state == phr_wait_end || state == phr_get_chunk_len) {
01044                 state = (isChunked) ? phr_get_chunk_len : phr_http_end;
01045                 len -= 2; start += 2; /* skip \r\n */
01046              }
01047              else {
01048                 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early");
01049                 return -1;
01050              }
01051         }
01052         else {
01053             *end = 0; /* null terminate */
01054             len -= (int)(end - start) + 2;
01055                 /* adjust len to remove the first line including the /r/n */
01056 
01057         #ifdef WOLFIO_DEBUG
01058             printf("HTTP Resp: %s\n", start);
01059         #endif
01060 
01061             switch (state) {
01062                 case phr_init:
01063                     if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) {
01064                         start += 9;
01065                         if (XSTRNCASECMP(start, "200 OK", 6) != 0) {
01066                             WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK");
01067                             return -1;
01068                         }
01069                         state = phr_http_start;
01070                     }
01071                     break;
01072                 case phr_http_start:
01073                 case phr_have_length:
01074                 case phr_have_type:
01075                     if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) {
01076                         int i;
01077 
01078                         start += 13;
01079                         while (*start == ' ' && *start != '\0') start++;
01080 
01081                         /* try and match against appStrList */
01082                         i = 0;
01083                         while (appStrList[i] != NULL) {
01084                             if (XSTRNCASECMP(start, appStrList[i],
01085                                                 XSTRLEN(appStrList[i])) == 0) {
01086                                 break;
01087                             }
01088                             i++;
01089                         }
01090                         if (appStrList[i] == NULL) {
01091                             WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch");
01092                             return -1;
01093                         }
01094                         state = (state == phr_http_start) ? phr_have_type : phr_wait_end;
01095                     }
01096                     else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) {
01097                         start += 15;
01098                         while (*start == ' ' && *start != '\0') start++;
01099                         chunkSz = atoi(start);
01100                         state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
01101                     }
01102                     else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) {
01103                         start += 18;
01104                         while (*start == ' ' && *start != '\0') start++;
01105                         if (XSTRNCASECMP(start, "chunked", 7) == 0) {
01106                             isChunked = 1;
01107                             state = (state == phr_http_start) ? phr_have_length : phr_wait_end;
01108                         }
01109                     }
01110                     break;
01111                 case phr_get_chunk_len:
01112                     chunkSz = (int)strtol(start, NULL, 16); /* hex format */
01113                     state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data;
01114                     break;
01115                 case phr_get_chunk_data:
01116                     /* processing for chunk data done above, since \r\n isn't required */
01117                 case phr_wait_end:
01118                 case phr_http_end:
01119                     /* do nothing */
01120                     break;
01121             } /* switch (state) */
01122 
01123             /* skip to end plus \r\n */
01124             start = end + 2;
01125         }
01126     } while (state != phr_http_end);
01127 
01128     if (!isChunked) {
01129         result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz,
01130                                                     start, len, dynType, heap);
01131     }
01132 
01133     if (result >= 0) {
01134         result = respBufSz;
01135     }
01136     else {
01137         WOLFSSL_ERROR(result);
01138     }
01139 
01140     return result;
01141 }
01142 
01143 int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName,
01144     const char* path, int pathLen, int reqSz, const char* contentType,
01145     byte* buf, int bufSize)
01146 {
01147     word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen;
01148     char reqSzStr[6];
01149     char* req = (char*)buf;
01150     const char* blankStr = " ";
01151     const char* http11Str = " HTTP/1.1";
01152     const char* hostStr = "\r\nHost: ";
01153     const char* contentLenStr = "\r\nContent-Length: ";
01154     const char* contentTypeStr = "\r\nContent-Type: ";
01155     const char* doubleCrLfStr = "\r\n\r\n";
01156     word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen,
01157         contentTypeStrLen, doubleCrLfStrLen;
01158 
01159     reqTypeLen = (word32)XSTRLEN(reqType);
01160     domainNameLen = (word32)XSTRLEN(domainName);
01161     reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz);
01162     contentTypeLen = (word32)XSTRLEN(contentType);
01163 
01164     blankStrLen = (word32)XSTRLEN(blankStr);
01165     http11StrLen = (word32)XSTRLEN(http11Str);
01166     hostStrLen = (word32)XSTRLEN(hostStr);
01167     contentLenStrLen = (word32)XSTRLEN(contentLenStr);
01168     contentTypeStrLen = (word32)XSTRLEN(contentTypeStr);
01169     doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr);
01170 
01171     /* determine max length and check it */
01172     maxLen =
01173         reqTypeLen +
01174         blankStrLen +
01175         pathLen +
01176         http11StrLen +
01177         hostStrLen +
01178         domainNameLen +
01179         contentLenStrLen +
01180         reqSzStrLen +
01181         contentTypeStrLen +
01182         contentTypeLen +
01183         doubleCrLfStrLen +
01184         1 /* null term */;
01185     if (maxLen > (word32)bufSize)
01186         return 0;
01187 
01188     XSTRNCPY((char*)buf, reqType, reqTypeLen);
01189     buf += reqTypeLen;
01190     XSTRNCPY((char*)buf, blankStr, blankStrLen+1);
01191     buf += blankStrLen;
01192     XSTRNCPY((char*)buf, path, pathLen);
01193     buf += pathLen;
01194     XSTRNCPY((char*)buf, http11Str, http11StrLen+1);
01195     buf += http11StrLen;
01196     if (domainNameLen > 0) {
01197         XSTRNCPY((char*)buf, hostStr, hostStrLen+1);
01198         buf += hostStrLen;
01199         XSTRNCPY((char*)buf, domainName, domainNameLen);
01200         buf += domainNameLen;
01201     }
01202     if (reqSz > 0 && reqSzStrLen > 0) {
01203         XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1);
01204         buf += contentLenStrLen;
01205         XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen);
01206         buf += reqSzStrLen;
01207     }
01208     if (contentTypeLen > 0) {
01209         XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1);
01210         buf += contentTypeStrLen;
01211         XSTRNCPY((char*)buf, contentType, contentTypeLen);
01212         buf += contentTypeLen;
01213     }
01214     XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1);
01215     buf += doubleCrLfStrLen;
01216 
01217 #ifdef WOLFIO_DEBUG
01218     printf("HTTP %s: %s", reqType, req);
01219 #endif
01220 
01221     /* calculate actual length based on original and new pointer */
01222     return (int)((char*)buf - req);
01223 }
01224 
01225 
01226 #ifdef HAVE_OCSP
01227 
01228 int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path,
01229                                     int ocspReqSz, byte* buf, int bufSize)
01230 {
01231     return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path),
01232         ocspReqSz, "application/ocsp-request", buf, bufSize);
01233 }
01234 
01235 /* return: >0 OCSP Response Size
01236  *         -1 error */
01237 int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf,
01238                                        byte* httpBuf, int httpBufSz, void* heap)
01239 {
01240     const char* appStrList[] = {
01241         "application/ocsp-response",
01242         NULL
01243     };
01244 
01245     return wolfIO_HttpProcessResponse(sfd, appStrList,
01246         respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap);
01247 }
01248 
01249 /* in default wolfSSL callback ctx is the heap pointer */
01250 int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
01251                         byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
01252 {
01253     SOCKET_T sfd = 0;
01254     word16   port;
01255     int      ret = -1;
01256 #ifdef WOLFSSL_SMALL_STACK
01257     char*    path;
01258     char*    domainName;
01259 #else
01260     char     path[MAX_URL_ITEM_SIZE];
01261     char     domainName[MAX_URL_ITEM_SIZE];
01262 #endif
01263 
01264 #ifdef WOLFSSL_SMALL_STACK
01265     path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01266     if (path == NULL)
01267         return MEMORY_E;
01268 
01269     domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01270     if (domainName == NULL) {
01271         XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01272         return MEMORY_E;
01273     }
01274 #endif
01275 
01276     if (ocspReqBuf == NULL || ocspReqSz == 0) {
01277         WOLFSSL_MSG("OCSP request is required for lookup");
01278     }
01279     else if (ocspRespBuf == NULL) {
01280         WOLFSSL_MSG("Cannot save OCSP response");
01281     }
01282     else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) {
01283         WOLFSSL_MSG("Unable to decode OCSP URL");
01284     }
01285     else {
01286         /* Note, the library uses the EmbedOcspRespFree() callback to
01287          * free this buffer. */
01288         int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
01289         byte* httpBuf   = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP);
01290 
01291         if (httpBuf == NULL) {
01292             WOLFSSL_MSG("Unable to create OCSP response buffer");
01293         }
01294         else {
01295             httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz,
01296                                                             httpBuf, httpBufSz);
01297 
01298             ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
01299             if ((ret != 0) || (sfd < 0)) {
01300                 WOLFSSL_MSG("OCSP Responder connection failed");
01301             }
01302             else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) !=
01303                                                                     httpBufSz) {
01304                 WOLFSSL_MSG("OCSP http request failed");
01305             }
01306             else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) !=
01307                                                                     ocspReqSz) {
01308                 WOLFSSL_MSG("OCSP ocsp request failed");
01309             }
01310             else {
01311                 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf,
01312                                                  HTTP_SCRATCH_BUFFER_SIZE, ctx);
01313             }
01314 
01315             CloseSocket(sfd);
01316             XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP);
01317         }
01318     }
01319 
01320 #ifdef WOLFSSL_SMALL_STACK
01321     XFREE(path,       NULL, DYNAMIC_TYPE_TMP_BUFFER);
01322     XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01323 #endif
01324 
01325     return ret;
01326 }
01327 
01328 /* in default callback ctx is heap hint */
01329 void EmbedOcspRespFree(void* ctx, byte *resp)
01330 {
01331     if (resp)
01332         XFREE(resp, ctx, DYNAMIC_TYPE_OCSP);
01333 
01334     (void)ctx;
01335 }
01336 #endif /* HAVE_OCSP */
01337 
01338 
01339 #if defined(HAVE_CRL) && defined(HAVE_CRL_IO)
01340 
01341 int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz,
01342     const char* domainName, byte* buf, int bufSize)
01343 {
01344     return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "",
01345         buf, bufSize);
01346 }
01347 
01348 int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf,
01349     int httpBufSz)
01350 {
01351     int result;
01352     byte *respBuf = NULL;
01353 
01354     const char* appStrList[] = {
01355         "application/pkix-crl",
01356         "application/x-pkcs7-crl",
01357         NULL
01358     };
01359 
01360     result = wolfIO_HttpProcessResponse(sfd, appStrList,
01361         &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap);
01362     if (result >= 0) {
01363         result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0);
01364     }
01365     XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL);
01366 
01367     return result;
01368 }
01369 
01370 int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz)
01371 {
01372     SOCKET_T sfd = 0;
01373     word16   port;
01374     int      ret = -1;
01375 #ifdef WOLFSSL_SMALL_STACK
01376     char*    domainName;
01377 #else
01378     char     domainName[MAX_URL_ITEM_SIZE];
01379 #endif
01380 
01381 #ifdef WOLFSSL_SMALL_STACK
01382     domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap,
01383                                                        DYNAMIC_TYPE_TMP_BUFFER);
01384     if (domainName == NULL) {
01385         return MEMORY_E;
01386     }
01387 #endif
01388 
01389     if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) {
01390         WOLFSSL_MSG("Unable to decode CRL URL");
01391     }
01392     else {
01393         int   httpBufSz = HTTP_SCRATCH_BUFFER_SIZE;
01394         byte* httpBuf   = (byte*)XMALLOC(httpBufSz, crl->heap,
01395                                                               DYNAMIC_TYPE_CRL);
01396         if (httpBuf == NULL) {
01397             WOLFSSL_MSG("Unable to create CRL response buffer");
01398         }
01399         else {
01400             httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName,
01401                 httpBuf, httpBufSz);
01402 
01403             ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec);
01404             if ((ret != 0) || (sfd < 0)) {
01405                 WOLFSSL_MSG("CRL connection failed");
01406             }
01407             else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0)
01408                                                                  != httpBufSz) {
01409                 WOLFSSL_MSG("CRL http get failed");
01410             }
01411             else {
01412                 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf,
01413                                                       HTTP_SCRATCH_BUFFER_SIZE);
01414             }
01415 
01416             CloseSocket(sfd);
01417             XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL);
01418         }
01419     }
01420 
01421 #ifdef WOLFSSL_SMALL_STACK
01422     XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER);
01423 #endif
01424 
01425     return ret;
01426 }
01427 #endif /* HAVE_CRL && HAVE_CRL_IO */
01428 
01429 #endif /* HAVE_HTTP_CLIENT */
01430 
01431 
01432 
01433 WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv)
01434 {
01435     ctx->CBIORecv = CBIORecv;
01436     #ifdef OPENSSL_EXTRA
01437     ctx->cbioFlag |= WOLFSSL_CBIO_RECV;
01438     #endif
01439 }
01440 
01441 
01442 WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend)
01443 {
01444     ctx->CBIOSend = CBIOSend;
01445     #ifdef OPENSSL_EXTRA
01446     ctx->cbioFlag |= WOLFSSL_CBIO_SEND;
01447     #endif
01448 }
01449 
01450 
01451 WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
01452 {
01453     ssl->IOCB_ReadCtx = rctx;
01454 }
01455 
01456 
01457 WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx)
01458 {
01459     ssl->IOCB_WriteCtx = wctx;
01460 }
01461 
01462 
01463 WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl)
01464 {
01465     if (ssl)
01466         return ssl->IOCB_ReadCtx;
01467 
01468     return NULL;
01469 }
01470 
01471 
01472 WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl)
01473 {
01474     if (ssl)
01475         return ssl->IOCB_WriteCtx;
01476 
01477     return NULL;
01478 }
01479 
01480 
01481 WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags)
01482 {
01483     ssl->rflags = flags;
01484 }
01485 
01486 
01487 WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags)
01488 {
01489     ssl->wflags = flags;
01490 }
01491 
01492 
01493 #ifdef WOLFSSL_DTLS
01494 
01495 WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb)
01496 {
01497     ctx->CBIOCookie = cb;
01498 }
01499 
01500 
01501 WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx)
01502 {
01503     ssl->IOCB_CookieCtx = ctx;
01504 }
01505 
01506 
01507 WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
01508 {
01509     if (ssl)
01510         return ssl->IOCB_CookieCtx;
01511 
01512     return NULL;
01513 }
01514 
01515 #ifdef WOLFSSL_SESSION_EXPORT
01516 
01517 WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
01518 {
01519     ctx->CBGetPeer = cb;
01520 }
01521 
01522 
01523 WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
01524 {
01525     ctx->CBSetPeer = cb;
01526 }
01527 
01528 #endif /* WOLFSSL_SESSION_EXPORT */
01529 #endif /* WOLFSSL_DTLS */
01530 
01531 
01532 #ifdef HAVE_NETX
01533 
01534 /* The NetX receive callback
01535  *  return :  bytes read, or error
01536  */
01537 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
01538 {
01539     NetX_Ctx* nxCtx = (NetX_Ctx*)ctx;
01540     ULONG left;
01541     ULONG total;
01542     ULONG copied = 0;
01543     UINT  status;
01544 
01545     (void)ssl;
01546 
01547     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
01548         WOLFSSL_MSG("NetX Recv NULL parameters");
01549         return WOLFSSL_CBIO_ERR_GENERAL;
01550     }
01551 
01552     if (nxCtx->nxPacket == NULL) {
01553         status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket,
01554                                        nxCtx->nxWait);
01555         if (status != NX_SUCCESS) {
01556             WOLFSSL_MSG("NetX Recv receive error");
01557             return WOLFSSL_CBIO_ERR_GENERAL;
01558         }
01559     }
01560 
01561     if (nxCtx->nxPacket) {
01562         status = nx_packet_length_get(nxCtx->nxPacket, &total);
01563         if (status != NX_SUCCESS) {
01564             WOLFSSL_MSG("NetX Recv length get error");
01565             return WOLFSSL_CBIO_ERR_GENERAL;
01566         }
01567 
01568         left = total - nxCtx->nxOffset;
01569         status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset,
01570                                                buf, sz, &copied);
01571         if (status != NX_SUCCESS) {
01572             WOLFSSL_MSG("NetX Recv data extract offset error");
01573             return WOLFSSL_CBIO_ERR_GENERAL;
01574         }
01575 
01576         nxCtx->nxOffset += copied;
01577 
01578         if (copied == left) {
01579             WOLFSSL_MSG("NetX Recv Drained packet");
01580             nx_packet_release(nxCtx->nxPacket);
01581             nxCtx->nxPacket = NULL;
01582             nxCtx->nxOffset = 0;
01583         }
01584     }
01585 
01586     return copied;
01587 }
01588 
01589 
01590 /* The NetX send callback
01591  *  return : bytes sent, or error
01592  */
01593 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx)
01594 {
01595     NetX_Ctx*       nxCtx = (NetX_Ctx*)ctx;
01596     NX_PACKET*      packet;
01597     NX_PACKET_POOL* pool;   /* shorthand */
01598     UINT            status;
01599 
01600     (void)ssl;
01601 
01602     if (nxCtx == NULL || nxCtx->nxSocket == NULL) {
01603         WOLFSSL_MSG("NetX Send NULL parameters");
01604         return WOLFSSL_CBIO_ERR_GENERAL;
01605     }
01606 
01607     pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool;
01608     status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET,
01609                                 nxCtx->nxWait);
01610     if (status != NX_SUCCESS) {
01611         WOLFSSL_MSG("NetX Send packet alloc error");
01612         return WOLFSSL_CBIO_ERR_GENERAL;
01613     }
01614 
01615     status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait);
01616     if (status != NX_SUCCESS) {
01617         nx_packet_release(packet);
01618         WOLFSSL_MSG("NetX Send data append error");
01619         return WOLFSSL_CBIO_ERR_GENERAL;
01620     }
01621 
01622     status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait);
01623     if (status != NX_SUCCESS) {
01624         nx_packet_release(packet);
01625         WOLFSSL_MSG("NetX Send socket send error");
01626         return WOLFSSL_CBIO_ERR_GENERAL;
01627     }
01628 
01629     return sz;
01630 }
01631 
01632 
01633 /* like set_fd, but for default NetX context */
01634 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption)
01635 {
01636     if (ssl) {
01637         ssl->nxCtx.nxSocket = nxSocket;
01638         ssl->nxCtx.nxWait   = waitOption;
01639     }
01640 }
01641 
01642 #endif /* HAVE_NETX */
01643 
01644 
01645 #ifdef MICRIUM
01646 
01647 /* Micrium uTCP/IP port, using the NetSock API
01648  * TCP and UDP are currently supported with the callbacks below.
01649  *
01650  * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer()
01651  * and EmbedSetPeer() callbacks implemented.
01652  *
01653  * HAVE_CRL is not yet supported, would need an EmbedCrlLookup()
01654  * callback implemented.
01655  *
01656  * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup()
01657  * callback implemented.
01658  */
01659 
01660 /* The Micrium uTCP/IP send callback
01661  * return : bytes sent, or error
01662  */
01663 int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
01664 {
01665     NET_SOCK_ID sd = *(int*)ctx;
01666     NET_SOCK_RTN_CODE ret;
01667     NET_ERR err;
01668 
01669     ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err);
01670     if (ret < 0) {
01671         WOLFSSL_MSG("Embed Send error");
01672 
01673         if (err == NET_ERR_TX) {
01674             WOLFSSL_MSG("\tWould block");
01675             return WOLFSSL_CBIO_ERR_WANT_WRITE;
01676 
01677         } else {
01678             WOLFSSL_MSG("\tGeneral error");
01679             return WOLFSSL_CBIO_ERR_GENERAL;
01680         }
01681     }
01682 
01683     return ret;
01684 }
01685 
01686 /* The Micrium uTCP/IP receive callback
01687  *  return : nb bytes read, or error
01688  */
01689 int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
01690 {
01691     NET_SOCK_ID sd = *(int*)ctx;
01692     NET_SOCK_RTN_CODE ret;
01693     NET_ERR err;
01694 
01695 #ifdef WOLFSSL_DTLS
01696     {
01697         int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
01698         if (wolfSSL_dtls(ssl)
01699                      && !wolfSSL_dtls_get_using_nonblock(ssl)
01700                      && dtls_timeout != 0) {
01701             /* needs timeout in milliseconds */
01702             NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
01703             if (err != NET_SOCK_ERR_NONE) {
01704                 WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
01705             }
01706         }
01707     }
01708 #endif
01709 
01710     ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err);
01711     if (ret < 0) {
01712         WOLFSSL_MSG("Embed Receive error");
01713 
01714         if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
01715             err == NET_ERR_FAULT_LOCK_ACQUIRE) {
01716             if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
01717                 WOLFSSL_MSG("\tWould block");
01718                 return WOLFSSL_CBIO_ERR_WANT_READ;
01719             }
01720             else {
01721                 WOLFSSL_MSG("\tSocket timeout");
01722                 return WOLFSSL_CBIO_ERR_TIMEOUT;
01723             }
01724 
01725         } else if (err == NET_SOCK_ERR_CLOSED) {
01726             WOLFSSL_MSG("Embed receive connection closed");
01727             return WOLFSSL_CBIO_ERR_CONN_CLOSE;
01728 
01729         } else {
01730             WOLFSSL_MSG("\tGeneral error");
01731             return WOLFSSL_CBIO_ERR_GENERAL;
01732         }
01733     }
01734 
01735     return ret;
01736 }
01737 
01738 /* The Micrium uTCP/IP receivefrom callback
01739  *  return : nb bytes read, or error
01740  */
01741 int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
01742 {
01743     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
01744     NET_SOCK_ID       sd = dtlsCtx->rfd;
01745     NET_SOCK_ADDR     peer;
01746     NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
01747     NET_SOCK_RTN_CODE ret;
01748     NET_ERR err;
01749     int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
01750 
01751     WOLFSSL_ENTER("MicriumReceiveFrom()");
01752 
01753     if (ssl->options.handShakeDone)
01754         dtls_timeout = 0;
01755 
01756     if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
01757         /* needs timeout in milliseconds */
01758         NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
01759         if (err != NET_SOCK_ERR_NONE) {
01760             WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed");
01761         }
01762     }
01763 
01764     ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz,
01765                              0, 0, 0, &err);
01766     if (ret < 0) {
01767         WOLFSSL_MSG("Embed Receive From error");
01768 
01769         if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
01770             err == NET_ERR_FAULT_LOCK_ACQUIRE) {
01771             if (wolfSSL_dtls_get_using_nonblock(ssl)) {
01772                 WOLFSSL_MSG("\tWould block");
01773                 return WOLFSSL_CBIO_ERR_WANT_READ;
01774             }
01775             else {
01776                 WOLFSSL_MSG("\tSocket timeout");
01777                 return WOLFSSL_CBIO_ERR_TIMEOUT;
01778             }
01779         } else {
01780             WOLFSSL_MSG("\tGeneral error");
01781             return WOLFSSL_CBIO_ERR_GENERAL;
01782         }
01783     }
01784     else {
01785         if (dtlsCtx->peer.sz > 0
01786                 && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz
01787                 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
01788             WOLFSSL_MSG("\tIgnored packet from invalid peer");
01789             return WOLFSSL_CBIO_ERR_WANT_READ;
01790         }
01791     }
01792 
01793     return ret;
01794 }
01795 
01796 /* The Micrium uTCP/IP sendto callback
01797  *  return : nb bytes sent, or error
01798  */
01799 int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
01800 {
01801     WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx;
01802     NET_SOCK_ID sd = dtlsCtx->wfd;
01803     NET_SOCK_RTN_CODE ret;
01804     int len = sz;
01805     NET_ERR err;
01806 
01807     WOLFSSL_ENTER("MicriumSendTo()");
01808 
01809     ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags,
01810                            (NET_SOCK_ADDR*)dtlsCtx->peer.sa,
01811                            (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz,
01812                            &err);
01813     if (err < 0) {
01814         WOLFSSL_MSG("Embed Send To error");
01815 
01816         if (err == NET_ERR_TX) {
01817             WOLFSSL_MSG("\tWould block");
01818             return WOLFSSL_CBIO_ERR_WANT_WRITE;
01819 
01820         } else {
01821             WOLFSSL_MSG("\tGeneral error");
01822             return WOLFSSL_CBIO_ERR_GENERAL;
01823         }
01824     }
01825 
01826     return ret;
01827 }
01828 
01829 /* Micrium DTLS Generate Cookie callback
01830  *  return : number of bytes copied into buf, or error
01831  */
01832 int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
01833 {
01834     NET_SOCK_ADDR peer;
01835     NET_SOCK_ADDR_LEN peerSz = sizeof(peer);
01836     byte digest[WC_SHA_DIGEST_SIZE];
01837     int  ret = 0;
01838 
01839     (void)ctx;
01840 
01841     XMEMSET(&peer, 0, sizeof(peer));
01842     if (wolfSSL_dtls_get_peer(ssl, (void*)&peer,
01843                               (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) {
01844         WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie");
01845         return GEN_COOKIE_E;
01846     }
01847 
01848     ret = wc_ShaHash((byte*)&peer, peerSz, digest);
01849     if (ret != 0)
01850         return ret;
01851 
01852     if (sz > WC_SHA_DIGEST_SIZE)
01853         sz = WC_SHA_DIGEST_SIZE;
01854     XMEMCPY(buf, digest, sz);
01855 
01856     return sz;
01857 }
01858 
01859 #endif /* MICRIUM */
01860 
01861 #endif /* WOLFCRYPT_ONLY */
01862