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