wolfSSL SSL/TLS library, support up to TLS1.3
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Wed Jul 13 2022 01:38:47 by 1.7.2