Merge pull request #4193 from daverodgman/rsa_private_backport_2.7
Backport 2.7: Fix an incorrect error code if RSA private operation glitched
diff --git a/ChangeLog.d/net_poll-fd_setsize.txt b/ChangeLog.d/net_poll-fd_setsize.txt
new file mode 100644
index 0000000..23b11bb
--- /dev/null
+++ b/ChangeLog.d/net_poll-fd_setsize.txt
@@ -0,0 +1,3 @@
+Security
+ * Fix a stack buffer overflow with mbedtls_net_recv_timeout() when given a
+ file descriptor that is beyond FD_SETSIZE. Reported by FigBug in #4169.
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index 0d61547..5f2b1c5 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -130,6 +130,7 @@
*
* \return 0 if successful, or one of:
* MBEDTLS_ERR_NET_SOCKET_FAILED,
+ * MBEDTLS_ERR_NET_UNKNOWN_HOST,
* MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_LISTEN_FAILED
*
@@ -149,6 +150,8 @@
* can be NULL if client_ip is null
*
* \return 0 if successful, or
+ * MBEDTLS_ERR_NET_SOCKET_FAILED,
+ * MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_ACCEPT_FAILED, or
* MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
* MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
@@ -219,16 +222,21 @@
* 'timeout' seconds. If no error occurs, the actual amount
* read is returned.
*
+ * \note The current implementation of this function uses
+ * select() and returns an error if the file descriptor
+ * is \c FD_SETSIZE or greater.
+ *
* \param ctx Socket
* \param buf The buffer to write to
* \param len Maximum length of the buffer
* \param timeout Maximum number of milliseconds to wait for data
* 0 means no timeout (wait forever)
*
- * \return the number of bytes received,
- * or a non-zero error code:
- * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out,
+ * \return The number of bytes received if successful.
+ * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
* MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
+ * Another negative error code (MBEDTLS_ERR_NET_xxx)
+ * for other failures.
*
* \note This function will block (until data becomes available or
* timeout is reached) even if the socket is set to
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 2876f8f..fa27603 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -535,6 +535,13 @@
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+ /* A limitation of select() is that it only works with file descriptors
+ * 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( fd >= FD_SETSIZE )
+ return( MBEDTLS_ERR_NET_RECV_FAILED );
+
FD_ZERO( &read_fds );
FD_SET( fd, &read_fds );
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index abb6668..fc9ffd1 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -886,11 +886,21 @@
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
- msg "test: no HMAC_DRBG"
+ msg "test: Full minus HMAC_DRBG - main suites"
make test
- # No ssl-opt.sh/compat.sh as they never use HMAC_DRBG so far,
- # so there's little value in running those lengthy tests here.
+ # Normally our ECDSA implementation uses deterministic ECDSA. But since
+ # HMAC_DRBG is disabled in this configuration, randomized ECDSA is used
+ # instead.
+ # Test SSL with non-deterministic ECDSA. Only test features that
+ # might be affected by how ECDSA signature is performed.
+ msg "test: Full minus HMAC_DRBG - ssl-opt.sh (subset)"
+ if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private: sign'
+
+ # To save time, only test one protocol version, since this part of
+ # the protocol is identical in (D)TLS up to 1.2.
+ msg "test: Full minus HMAC_DRBG - compat.sh (ECDSA)"
+ if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA'
}
component_test_no_drbg_all_hashes () {