1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-07 17:36:07 +00:00

mbedtls: Update to upstream version 2.28.3

Rediff patch from PR 1453, lstrlenW is no longer used upstream so
that part of the patch was dropped.

(cherry picked from commit 1fde2092d0)
This commit is contained in:
Rémi Verschelde
2023-04-18 10:38:24 +02:00
parent 212190ae49
commit ac4daf4147
174 changed files with 36064 additions and 35819 deletions

View File

@@ -47,7 +47,7 @@
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
#define IS_EINTR(ret) ((ret) == WSAEINTR)
#if !defined(_WIN32_WINNT)
/* Enables getaddrinfo() & Co */
@@ -70,8 +70,8 @@
#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 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;
@@ -89,7 +89,7 @@ static int wsa_init_done = 0;
#include <netdb.h>
#include <errno.h>
#define IS_EINTR( ret ) ( ( ret ) == EINTR )
#define IS_EINTR(ret) ((ret) == EINTR)
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
@@ -112,25 +112,25 @@ static int wsa_init_done = 0;
/*
* Prepare for using the sockets interface
*/
static int net_prepare( void )
static int net_prepare(void)
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
WSADATA wsaData;
if( wsa_init_done == 0 )
{
if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
return( MBEDTLS_ERR_NET_SOCKET_FAILED );
if (wsa_init_done == 0) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return MBEDTLS_ERR_NET_SOCKET_FAILED;
}
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal( SIGPIPE, SIG_IGN );
signal(SIGPIPE, SIG_IGN);
#endif
#endif
return( 0 );
return 0;
}
/*
@@ -138,10 +138,11 @@ static int net_prepare( void )
* If for_select != 0, check whether the file descriptor is within the range
* allowed for fd_set used for the FD_xxx macros and the select() function.
*/
static int check_fd( int fd, int for_select )
static int check_fd(int fd, int for_select)
{
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
if (fd < 0) {
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
}
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
@@ -151,17 +152,18 @@ static int check_fd( int fd, int for_select )
* that are strictly less than FD_SETSIZE. This is a limitation of the
* fd_set type. Error out early, because attempting to call FD_SET on a
* large file descriptor is a buffer overflow on typical platforms. */
if( for_select && fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_POLL_FAILED );
if (for_select && fd >= FD_SETSIZE) {
return MBEDTLS_ERR_NET_POLL_FAILED;
}
#endif
return( 0 );
return 0;
}
/*
* Initialize a context
*/
void mbedtls_net_init( mbedtls_net_context *ctx )
void mbedtls_net_init(mbedtls_net_context *ctx)
{
ctx->fd = -1;
}
@@ -169,107 +171,103 @@ 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 = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct addrinfo hints, *addr_list, *cur;
if( ( ret = net_prepare() ) != 0 )
return( ret );
if ((ret = net_prepare()) != 0) {
return ret;
}
/* Do name resolution with both IPv6 and IPv4 */
memset( &hints, 0, sizeof( hints ) );
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( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
return MBEDTLS_ERR_NET_UNKNOWN_HOST;
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
{
ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
cur->ai_protocol );
if( ctx->fd < 0 )
{
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
{
if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) {
ret = 0;
break;
}
close( ctx->fd );
close(ctx->fd);
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo( addr_list );
freeaddrinfo(addr_list);
return( ret );
return ret;
}
/*
* Create a listening socket on bind_ip:port
*/
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)
{
int n, ret;
struct addrinfo hints, *addr_list, *cur;
if( ( ret = net_prepare() ) != 0 )
return( ret );
if ((ret = net_prepare()) != 0) {
return ret;
}
/* Bind to IPv6 and/or IPv4, but only in the desired protocol */
memset( &hints, 0, sizeof( hints ) );
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 )
if (bind_ip == NULL) {
hints.ai_flags = AI_PASSIVE;
}
if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
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;
for( cur = addr_list; cur != NULL; cur = cur->ai_next )
{
ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
cur->ai_protocol );
if( ctx->fd < 0 )
{
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
n = 1;
if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof( n ) ) != 0 )
{
close( ctx->fd );
if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof(n)) != 0) {
close(ctx->fd);
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
{
close( ctx->fd );
if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) {
close(ctx->fd);
ret = MBEDTLS_ERR_NET_BIND_FAILED;
continue;
}
/* Listen only makes sense for TCP */
if( proto == MBEDTLS_NET_PROTO_TCP )
{
if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
{
close( ctx->fd );
if (proto == MBEDTLS_NET_PROTO_TCP) {
if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) {
close(ctx->fd);
ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
continue;
}
@@ -280,22 +278,22 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
break;
}
freeaddrinfo( addr_list );
freeaddrinfo(addr_list);
return( ret );
return ret;
}
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
#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 )
static int net_would_block(const mbedtls_net_context *ctx)
{
((void) ctx);
return( WSAGetLastError() == WSAEWOULDBLOCK );
return WSAGetLastError() == WSAEWOULDBLOCK;
}
#else
/*
@@ -304,39 +302,37 @@ static int net_would_block( const mbedtls_net_context *ctx )
*
* Note: on a blocking socket this function always returns 0!
*/
static int net_would_block( const mbedtls_net_context *ctx )
static int net_would_block(const mbedtls_net_context *ctx)
{
int err = errno;
/*
* Never return 'WOULD BLOCK' on a blocking socket
*/
if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
{
if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) {
errno = err;
return( 0 );
return 0;
}
switch( errno = err )
{
switch (errno = err) {
#if defined EAGAIN
case EAGAIN:
#endif
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
return( 1 );
return 1;
}
return( 0 );
return 0;
}
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/*
* Accept a connection from a remote client
*/
int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len )
int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int type;
@@ -346,132 +342,123 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
socklen_t n = (socklen_t) sizeof( client_addr );
socklen_t type_len = (socklen_t) sizeof( type );
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 );
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, &type_len ) != 0 ||
( type != SOCK_STREAM && type != SOCK_DGRAM ) )
{
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE,
(void *) &type, &type_len) != 0 ||
(type != SOCK_STREAM && type != SOCK_DGRAM)) {
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
if( type == SOCK_STREAM )
{
if (type == SOCK_STREAM) {
/* TCP: actual accept() */
ret = client_ctx->fd = (int) accept( bind_ctx->fd,
(struct sockaddr *) &client_addr, &n );
}
else
{
ret = client_ctx->fd = (int) accept(bind_ctx->fd,
(struct sockaddr *) &client_addr, &n);
} else {
/* UDP: wait for a message, but keep it in the queue */
char buf[1] = { 0 };
ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
(struct sockaddr *) &client_addr, &n );
ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK,
(struct sockaddr *) &client_addr, &n);
#if defined(_WIN32)
if( ret == SOCKET_ERROR &&
WSAGetLastError() == WSAEMSGSIZE )
{
if (ret == SOCKET_ERROR &&
WSAGetLastError() == WSAEMSGSIZE) {
/* We know buf is too small, thanks, just peeking here */
ret = 0;
}
#endif
}
if( ret < 0 )
{
if( net_would_block( bind_ctx ) != 0 )
return( MBEDTLS_ERR_SSL_WANT_READ );
if (ret < 0) {
if (net_would_block(bind_ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
/* UDP: hijack the listening socket to communicate with the client,
* then bind a new socket to accept new connections */
if( type != SOCK_STREAM )
{
if (type != SOCK_STREAM) {
struct sockaddr_storage local_addr;
int one = 1;
if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) {
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
client_ctx->fd = bind_ctx->fd;
bind_ctx->fd = -1; /* In case we exit early */
n = sizeof( struct sockaddr_storage );
if( getsockname( client_ctx->fd,
(struct sockaddr *) &local_addr, &n ) != 0 ||
( 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 )
{
return( MBEDTLS_ERR_NET_SOCKET_FAILED );
n = sizeof(struct sockaddr_storage);
if (getsockname(client_ctx->fd,
(struct sockaddr *) &local_addr, &n) != 0 ||
(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) {
return MBEDTLS_ERR_NET_SOCKET_FAILED;
}
if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
{
return( MBEDTLS_ERR_NET_BIND_FAILED );
if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) {
return MBEDTLS_ERR_NET_BIND_FAILED;
}
}
if( client_ip != NULL )
{
if( client_addr.ss_family == AF_INET )
{
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 );
*ip_len = sizeof(addr4->sin_addr.s_addr);
if( buf_size < *ip_len )
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
if (buf_size < *ip_len) {
return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
}
memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
}
else
{
memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len);
} else {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
*ip_len = sizeof( addr6->sin6_addr.s6_addr );
*ip_len = sizeof(addr6->sin6_addr.s6_addr);
if( buf_size < *ip_len )
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
if (buf_size < *ip_len) {
return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
}
memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
}
}
return( 0 );
return 0;
}
/*
* Set the socket blocking or non-blocking
*/
int mbedtls_net_set_block( mbedtls_net_context *ctx )
int mbedtls_net_set_block(mbedtls_net_context *ctx)
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
u_long n = 0;
return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
return ioctlsocket(ctx->fd, FIONBIO, &n);
#else
return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK);
#endif
}
int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
int mbedtls_net_set_nonblock(mbedtls_net_context *ctx)
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
u_long n = 1;
return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
return ioctlsocket(ctx->fd, FIONBIO, &n);
#else
return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK);
#endif
}
@@ -479,7 +466,7 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
* Check if data is available on the socket
*/
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
@@ -489,207 +476,220 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
int fd = ctx->fd;
ret = check_fd( fd, 1 );
if( ret != 0 )
return( ret );
ret = check_fd(fd, 1);
if (ret != 0) {
return ret;
}
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
/* Ensure that memory sanitizers consider read_fds and write_fds as
* initialized even on platforms such as Glibc/x86_64 where FD_ZERO
* is implemented in assembly. */
memset( &read_fds, 0, sizeof( read_fds ) );
memset( &write_fds, 0, sizeof( write_fds ) );
memset(&read_fds, 0, sizeof(read_fds));
memset(&write_fds, 0, sizeof(write_fds));
#endif
#endif
FD_ZERO( &read_fds );
if( rw & MBEDTLS_NET_POLL_READ )
{
FD_ZERO(&read_fds);
if (rw & MBEDTLS_NET_POLL_READ) {
rw &= ~MBEDTLS_NET_POLL_READ;
FD_SET( fd, &read_fds );
FD_SET(fd, &read_fds);
}
FD_ZERO( &write_fds );
if( rw & MBEDTLS_NET_POLL_WRITE )
{
FD_ZERO(&write_fds);
if (rw & MBEDTLS_NET_POLL_WRITE) {
rw &= ~MBEDTLS_NET_POLL_WRITE;
FD_SET( fd, &write_fds );
FD_SET(fd, &write_fds);
}
if( rw != 0 )
return( MBEDTLS_ERR_NET_BAD_INPUT_DATA );
if (rw != 0) {
return MBEDTLS_ERR_NET_BAD_INPUT_DATA;
}
tv.tv_sec = timeout / 1000;
tv.tv_usec = ( timeout % 1000 ) * 1000;
tv.tv_usec = (timeout % 1000) * 1000;
do
{
ret = select( fd + 1, &read_fds, &write_fds, NULL,
timeout == (uint32_t) -1 ? NULL : &tv );
do {
ret = select(fd + 1, &read_fds, &write_fds, NULL,
timeout == (uint32_t) -1 ? NULL : &tv);
} while (IS_EINTR(ret));
if (ret < 0) {
return MBEDTLS_ERR_NET_POLL_FAILED;
}
while( IS_EINTR( ret ) );
if( ret < 0 )
return( MBEDTLS_ERR_NET_POLL_FAILED );
ret = 0;
if( FD_ISSET( fd, &read_fds ) )
if (FD_ISSET(fd, &read_fds)) {
ret |= MBEDTLS_NET_POLL_READ;
if( FD_ISSET( fd, &write_fds ) )
}
if (FD_ISSET(fd, &write_fds)) {
ret |= MBEDTLS_NET_POLL_WRITE;
}
return( ret );
return ret;
}
/*
* Portable usleep helper
*/
void mbedtls_net_usleep( unsigned long usec )
void mbedtls_net_usleep(unsigned long usec)
{
#if defined(_WIN32)
Sleep( ( usec + 999 ) / 1000 );
Sleep((usec + 999) / 1000);
#else
struct timeval tv;
tv.tv_sec = usec / 1000000;
#if defined(__unix__) || defined(__unix) || \
( defined(__APPLE__) && defined(__MACH__) )
(defined(__APPLE__) && defined(__MACH__))
tv.tv_usec = (suseconds_t) usec % 1000000;
#else
tv.tv_usec = usec % 1000000;
#endif
select( 0, NULL, NULL, NULL, &tv );
select(0, NULL, NULL, NULL, &tv);
#endif
}
/*
* Read at most 'len' characters
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd( fd, 0 );
if( ret != 0 )
return( ret );
ret = (int) read( fd, buf, len );
if( ret < 0 )
{
if( net_would_block( ctx ) != 0 )
return( MBEDTLS_ERR_SSL_WANT_READ );
#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( errno == EINTR )
return( MBEDTLS_ERR_SSL_WANT_READ );
#endif
return( MBEDTLS_ERR_NET_RECV_FAILED );
ret = check_fd(fd, 0);
if (ret != 0) {
return ret;
}
return( ret );
ret = (int) read(fd, buf, len);
if (ret < 0) {
if (net_would_block(ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#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 (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#endif
return MBEDTLS_ERR_NET_RECV_FAILED;
}
return ret;
}
/*
* Read at most 'len' characters, blocking for at most 'timeout' ms
*/
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
size_t len, uint32_t timeout )
int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,
size_t len, uint32_t timeout)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd( fd, 1 );
if( ret != 0 )
return( ret );
ret = check_fd(fd, 1);
if (ret != 0) {
return ret;
}
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = ( timeout % 1000 ) * 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if( ret == 0 )
return( MBEDTLS_ERR_SSL_TIMEOUT );
if (ret == 0) {
return MBEDTLS_ERR_SSL_TIMEOUT;
}
if( ret < 0 )
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
if( WSAGetLastError() == WSAEINTR )
return( MBEDTLS_ERR_SSL_WANT_READ );
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 );
if (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#endif
return( MBEDTLS_ERR_NET_RECV_FAILED );
return MBEDTLS_ERR_NET_RECV_FAILED;
}
/* This call will not block */
return( mbedtls_net_recv( ctx, buf, len ) );
return mbedtls_net_recv(ctx, buf, len);
}
/*
* Write at most 'len' characters
*/
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd( fd, 0 );
if( ret != 0 )
return( ret );
ret = (int) write( fd, buf, len );
if( ret < 0 )
{
if( net_would_block( ctx ) != 0 )
return( MBEDTLS_ERR_SSL_WANT_WRITE );
#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( errno == EINTR )
return( MBEDTLS_ERR_SSL_WANT_WRITE );
#endif
return( MBEDTLS_ERR_NET_SEND_FAILED );
ret = check_fd(fd, 0);
if (ret != 0) {
return ret;
}
return( ret );
ret = (int) write(fd, buf, len);
if (ret < 0) {
if (net_would_block(ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
#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 (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
#endif
return MBEDTLS_ERR_NET_SEND_FAILED;
}
return ret;
}
/*
* Close the connection
*/
void mbedtls_net_close( mbedtls_net_context *ctx )
void mbedtls_net_close(mbedtls_net_context *ctx)
{
if( ctx->fd == -1 )
if (ctx->fd == -1) {
return;
}
close( ctx->fd );
close(ctx->fd);
ctx->fd = -1;
}
@@ -697,13 +697,14 @@ void mbedtls_net_close( mbedtls_net_context *ctx )
/*
* Gracefully close the connection
*/
void mbedtls_net_free( mbedtls_net_context *ctx )
void mbedtls_net_free(mbedtls_net_context *ctx)
{
if( ctx->fd == -1 )
if (ctx->fd == -1) {
return;
}
shutdown( ctx->fd, 2 );
close( ctx->fd );
shutdown(ctx->fd, 2);
close(ctx->fd);
ctx->fd = -1;
}