diff --git a/extras/mbedtls/component.mk b/extras/mbedtls/component.mk index c392471..5b7d658 100644 --- a/extras/mbedtls/component.mk +++ b/extras/mbedtls/component.mk @@ -26,7 +26,7 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \ padlock.o pem.o pk.o \ pk_wrap.o pkcs12.o pkcs5.o \ pkparse.o pkwrite.o platform.o \ - ripemd160.o rsa.o sha1.o \ + ripemd160.o rsa.o rsa_internal.o sha1.o \ sha256.o sha512.o threading.o \ timing.o version.o \ version_features.o xtea.o diff --git a/extras/mbedtls/mbedtls b/extras/mbedtls/mbedtls index f2a597f..1bf6123 160000 --- a/extras/mbedtls/mbedtls +++ b/extras/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit f2a597fa3dd1c7b15e0fee62f6932b253295803d +Subproject commit 1bf6123fca97a9a35c2f403ab0c96495f9580db6 diff --git a/extras/mbedtls/net_lwip.c b/extras/mbedtls/net_lwip.c index 3101380..3926458 100644 --- a/extras/mbedtls/net_lwip.c +++ b/extras/mbedtls/net_lwip.c @@ -1,6 +1,7 @@ /* * TCP/IP or UDP/IP networking functions - * modified for LWIP support on ESP8266 + * Based on mbedtls/library/net_sockets.c + * Modified for LWIP support on ESP8266 * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Additions Copyright (C) 2015 Angus Gratton @@ -21,7 +22,6 @@ * This file is part of mbed TLS (https://tls.mbed.org) */ -#include #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else @@ -30,18 +30,74 @@ #if defined(MBEDTLS_NET_C) +#define ESP_OPEN_RTOS 1 +#define _SOCKLEN_T_DECLARED 1 + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(ESP_OPEN_RTOS) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + #include "mbedtls/net_sockets.h" #include +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#include + +#include +#include + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + #include #include +//#include +#include #include #include +#include +#include #include #include -#include +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + #include #include @@ -65,6 +121,9 @@ static int net_prepare( void ) wsa_init_done = 1; } #else +#if !defined(EFIX64) && !defined(EFI32) && !defined(ESP_OPEN_RTOS) + signal( SIGPIPE, SIG_IGN ); +#endif #endif return( 0 ); } @@ -80,7 +139,8 @@ void mbedtls_net_init( mbedtls_net_context *ctx ) /* * Initiate a TCP connection with host:port and the given protocol */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ) +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) { int ret; struct addrinfo hints, *addr_list, *cur; @@ -109,7 +169,11 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char continue; } - if( connect( ctx->fd, cur->ai_addr, cur->ai_addrlen ) == 0 ) + const struct timeval timeout = { 60, 0 }; /* 60 second timeout */ + setsockopt( ctx->fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout) ); + setsockopt( ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout) ); + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) { ret = 0; break; @@ -130,14 +194,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) { int n, ret; - struct addrinfo *addr_list, *cur; - - /* Only request desired protocol */ - const struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = (proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM), - .ai_protocol = (proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP), - }; + struct addrinfo hints, *addr_list, *cur; struct sockaddr_in sockaddr_ipaddr_any = { .sin_len = sizeof(struct sockaddr_in), @@ -148,8 +205,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char struct addrinfo all_interfaces_addr = { .ai_family = AF_INET, - .ai_socktype = hints.ai_socktype, - .ai_protocol = hints.ai_protocol, + .ai_socktype = (proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM), + .ai_protocol = (proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP), .ai_addrlen = sizeof(struct sockaddr_in), .ai_addr = (struct sockaddr *)&sockaddr_ipaddr_any, }; @@ -157,14 +214,22 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char if( ( ret = net_prepare() ) != 0 ) return( ret ); - if(bind_ip == NULL) { + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( bind_ip == NULL ) { /* mbedTLS docs specify bind_ip == NULL means all interfaces, but lwip getaddrinfo() assumes NULL means localhost. So we swap in a precreated IPADDR_ANY addrinfo result here. */ addr_list = &all_interfaces_addr; } - else if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) { + else + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); - } /* Try the sockaddrs until a binding succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; @@ -187,7 +252,7 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char continue; } - if( bind( ctx->fd, cur->ai_addr, cur->ai_addrlen ) != 0 ) + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) { close( ctx->fd ); ret = MBEDTLS_ERR_NET_BIND_FAILED; @@ -205,12 +270,12 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char } } - /* I we ever get there, it's a success */ + /* Bind was successful */ ret = 0; break; } - if(bind_ip != NULL) { + if( bind_ip != NULL ) { freeaddrinfo( addr_list ); } @@ -218,14 +283,18 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char } -static int socket_errno( const mbedtls_net_context *ctx ) +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) { - int sock_errno = 0; - u32_t optlen = sizeof(sock_errno); - lwip_getsockopt(ctx->fd, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen); - return sock_errno; + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); } - +#else /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. @@ -234,14 +303,18 @@ static int socket_errno( const mbedtls_net_context *ctx ) */ static int net_would_block( const mbedtls_net_context *ctx ) { + int err = errno; + /* * Never return 'WOULD BLOCK' on a non-blocking socket */ if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; return( 0 ); + } - - switch( socket_errno(ctx) ) + switch( errno = err ) { #if defined EAGAIN case EAGAIN: @@ -253,6 +326,7 @@ static int net_would_block( const mbedtls_net_context *ctx ) } return( 0 ); } +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* * Accept a connection from a remote client @@ -264,14 +338,20 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, int ret; int type; - struct sockaddr_in client_addr; + struct sockaddr_storage client_addr; +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) socklen_t n = (socklen_t) sizeof( client_addr ); socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif /* Is this a TCP or UDP socket? */ if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, - (void *) &type, (socklen_t *) &type_len ) != 0 || + (void *) &type, &type_len ) != 0 || ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) { return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); @@ -288,7 +368,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, /* UDP: wait for a message, but keep it in the queue */ char buf[1] = { 0 }; - ret = recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, (struct sockaddr *) &client_addr, &n ); #if defined(_WIN32) @@ -313,7 +393,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, * then bind a new socket to accept new connections */ if( type != SOCK_STREAM ) { - struct sockaddr_in local_addr; + struct sockaddr_storage local_addr; int one = 1; if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) @@ -322,10 +402,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, client_ctx->fd = bind_ctx->fd; bind_ctx->fd = -1; /* In case we exit early */ - n = sizeof( struct sockaddr_in ); + n = sizeof( struct sockaddr_storage ); if( getsockname( client_ctx->fd, (struct sockaddr *) &local_addr, &n ) != 0 || - ( bind_ctx->fd = (int) socket( AF_INET, + ( bind_ctx->fd = (int) socket( local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof( one ) ) != 0 ) @@ -341,6 +421,8 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, if( client_ip != NULL ) { + if( client_addr.ss_family == AF_INET ) + { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; *ip_len = sizeof( addr4->sin_addr.s_addr ); @@ -348,6 +430,19 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { +#if LWIP_IPV6 + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); +#endif + } } return( 0 ); @@ -398,7 +493,9 @@ void mbedtls_net_usleep( unsigned long usec ) #endif } -/* Read at most 'len' characters */ +/* + * Read at most 'len' characters + */ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) { int ret; @@ -414,13 +511,17 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) if( net_would_block( ctx ) != 0 ) return( MBEDTLS_ERR_SSL_WANT_READ ); - int sock_errno = socket_errno(ctx); - - if( sock_errno == EPIPE || sock_errno == ECONNRESET ) +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); - if( sock_errno == EINTR ) + if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif return( MBEDTLS_ERR_NET_RECV_FAILED ); } @@ -456,8 +557,14 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, if( ret < 0 ) { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif return( MBEDTLS_ERR_NET_RECV_FAILED ); } @@ -484,13 +591,17 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) if( net_would_block( ctx ) != 0 ) return( MBEDTLS_ERR_SSL_WANT_WRITE ); - int sock_errno = socket_errno(ctx); - - if( sock_errno == EPIPE || sock_errno == ECONNRESET ) +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) return( MBEDTLS_ERR_NET_CONN_RESET ); - if( sock_errno == EINTR ) + if( errno == EINTR ) return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif return( MBEDTLS_ERR_NET_SEND_FAILED ); }