mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-12-23 00:35:33 +00:00
Merge branch 'pr_946' into development-proposed
This commit is contained in:
commit
80aa3b8d65
16
ChangeLog
16
ChangeLog
|
@ -19,6 +19,14 @@ Features
|
|||
mbedtls_ecdh_compute_shared()) are supported for now. Contributed by
|
||||
Nicholas Wilson (#348).
|
||||
|
||||
API Changes
|
||||
* Add function mbedtls_net_poll to public API allowing to wait for a
|
||||
network context to become ready for reading or writing.
|
||||
* Add function mbedtls_ssl_check_pending to public API allowing to check
|
||||
if more data is pending to be processed in the internal message buffers.
|
||||
This function is necessary to determine when it is safe to idle on the
|
||||
underlying transport in case event-driven IO is used.
|
||||
|
||||
Bugfix
|
||||
* Fix spurious uninitialized variable warning in cmac.c. Fix independently
|
||||
contributed by Brian J Murray and David Brown.
|
||||
|
@ -39,6 +47,14 @@ Bugfix
|
|||
the mbedtls_cipher_update() documentation. Contributed by Andy Leiserson.
|
||||
* Fix overriding and ignoring return values when parsing and writing to
|
||||
a file in pk_sign program. Found by kevlut in #1142.
|
||||
* Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations
|
||||
where data needs to be fetched from the underlying transport in order
|
||||
to make progress. Previously, this error code was also occasionally
|
||||
returned when unexpected messages were being discarded, ignoring that
|
||||
further messages could potentially already be pending to be processed
|
||||
in the internal buffers; these cases lead to deadlocks in case
|
||||
event-driven I/O was used.
|
||||
Found and reported by Hubert Mis in #772.
|
||||
|
||||
Changes
|
||||
* Remove some redundant code in bignum.c. Contributed by Alexey Skalozub.
|
||||
|
|
|
@ -46,12 +46,17 @@
|
|||
#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */
|
||||
#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */
|
||||
#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */
|
||||
#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */
|
||||
#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */
|
||||
|
||||
#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
|
||||
|
||||
#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */
|
||||
#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */
|
||||
|
||||
#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */
|
||||
#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -133,6 +138,29 @@ 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 );
|
||||
|
||||
/**
|
||||
* \brief Check and wait for the context to be ready for read/write
|
||||
*
|
||||
* \param ctx Socket to check
|
||||
* \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and
|
||||
* MBEDTLS_NET_POLL_WRITE specifying the events
|
||||
* to wait for:
|
||||
* - If MBEDTLS_NET_POLL_READ is set, the function
|
||||
* will return as soon as the net context is available
|
||||
* for reading.
|
||||
* - If MBEDTLS_NET_POLL_WRITE is set, the function
|
||||
* will return as soon as the net context is available
|
||||
* for writing.
|
||||
* \param timeout Maximal amount of time to wait before returning,
|
||||
* in milliseconds. If \c timeout is zero, the
|
||||
* function returns immediately. If \c timeout is
|
||||
* -1u, the function blocks potentially indefinitely.
|
||||
*
|
||||
* \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE
|
||||
* on success or timeout, or a negative return code otherwise.
|
||||
*/
|
||||
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout );
|
||||
|
||||
/**
|
||||
* \brief Set the socket blocking
|
||||
*
|
||||
|
|
|
@ -112,13 +112,14 @@
|
|||
#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */
|
||||
#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */
|
||||
#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
|
||||
#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */
|
||||
#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */
|
||||
#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */
|
||||
#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */
|
||||
#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */
|
||||
#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */
|
||||
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
|
||||
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
|
||||
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
|
||||
|
||||
/*
|
||||
* Various constants
|
||||
|
@ -2301,11 +2302,59 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
|
|||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||
|
||||
/**
|
||||
* \brief Return the number of data bytes available to read
|
||||
* \brief Check if there is data already read from the
|
||||
* underlying transport but not yet processed.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return how many bytes are available in the read buffer
|
||||
* \return 0 if nothing's pending, 1 otherwise.
|
||||
*
|
||||
* \note This is different in purpose and behaviour from
|
||||
* \c mbedtls_ssl_get_bytes_avail in that it considers
|
||||
* any kind of unprocessed data, not only unread
|
||||
* application data. If \c mbedtls_ssl_get_bytes
|
||||
* returns a non-zero value, this function will
|
||||
* also signal pending data, but the converse does
|
||||
* not hold. For example, in DTLS there might be
|
||||
* further records waiting to be processed from
|
||||
* the current underlying transport's datagram.
|
||||
*
|
||||
* \note If this function returns 1 (data pending), this
|
||||
* does not imply that a subsequent call to
|
||||
* \c mbedtls_ssl_read will provide any data;
|
||||
* e.g., the unprocessed data might turn out
|
||||
* to be an alert or a handshake message.
|
||||
*
|
||||
* \note This function is useful in the following situation:
|
||||
* If the SSL/TLS module successfully returns from an
|
||||
* operation - e.g. a handshake or an application record
|
||||
* read - and you're awaiting incoming data next, you
|
||||
* must not immediately idle on the underlying transport
|
||||
* to have data ready, but you need to check the value
|
||||
* of this function first. The reason is that the desired
|
||||
* data might already be read but not yet processed.
|
||||
* If, in contrast, a previous call to the SSL/TLS module
|
||||
* returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary
|
||||
* to call this function, as the latter error code entails
|
||||
* that all internal data has been processed.
|
||||
*
|
||||
*/
|
||||
int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl );
|
||||
|
||||
/**
|
||||
* \brief Return the number of application data bytes
|
||||
* remaining to be read from the current record.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return How many bytes are available in the application
|
||||
* data record read buffer.
|
||||
*
|
||||
* \note When working over a datagram transport, this is
|
||||
* useful to detect the current datagram's boundary
|
||||
* in case \c mbedtls_ssl_read has written the maximal
|
||||
* amount of data fitting into the input buffer.
|
||||
*
|
||||
*/
|
||||
size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
|
||||
|
||||
|
@ -2420,11 +2469,25 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
|
|||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
|
||||
* a specific SSL error code.
|
||||
*
|
||||
* If this function returns MBEDTLS_ERR_SSL_WANT_READ, the
|
||||
* handshake is unfinished and no further data is available
|
||||
* from the underlying transport. In this case, you must call
|
||||
* the function again at some later stage.
|
||||
*
|
||||
* \note Remarks regarding event-driven DTLS:
|
||||
* If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
|
||||
* from the underlying transport layer is currently being processed,
|
||||
* and it is safe to idle until the timer or the underlying transport
|
||||
* signal a new event. This is not true for a successful handshake,
|
||||
* in which case the datagram of the underlying transport that is
|
||||
* currently being processed might or might not contain further
|
||||
* DTLS records.
|
||||
*
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*
|
||||
* \note If DTLS is in use, then you may choose to handle
|
||||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
|
||||
|
@ -2441,10 +2504,10 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
|
|||
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
|
||||
*
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
|
@ -2468,10 +2531,10 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
|
|||
* value.
|
||||
*
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*/
|
||||
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||
|
@ -2483,20 +2546,20 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
|||
* \param buf buffer that will hold the data
|
||||
* \param len maximum number of bytes to read
|
||||
*
|
||||
* \return the number of bytes read, or
|
||||
* 0 for EOF, or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
|
||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or
|
||||
* another negative error code.
|
||||
* \return One of the following:
|
||||
* - 0 if the read end of the underlying transport was closed,
|
||||
* - the (positive) number of bytes read, or
|
||||
* - a negative error code on failure.
|
||||
*
|
||||
* \note If this function returns something other than a positive
|
||||
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or
|
||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data
|
||||
* is available from the underlying transport. In this case,
|
||||
* the function needs to be called again at some later stage.
|
||||
*
|
||||
* \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
||||
* If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending
|
||||
* but the underlying transport isn't available for writing. In this
|
||||
* case, the function needs to be called again at some later stage.
|
||||
*
|
||||
* When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
||||
* (which can only happen server-side), it means that a client
|
||||
* is initiating a new connection using the same source port.
|
||||
* You can either treat that as a connection close and wait
|
||||
|
@ -2509,6 +2572,28 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
|||
* again. WARNING: not validating the identity of the client
|
||||
* again, or not transmitting the new identity to the
|
||||
* application layer, would allow authentication bypass!
|
||||
*
|
||||
* \note If this function returns something other than a positive value
|
||||
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
|
||||
* you must stop using the SSL context for reading or writing,
|
||||
* and either free it or call \c mbedtls_ssl_session_reset() on it
|
||||
* before re-using it for a new connection; the current connection
|
||||
* must be closed.
|
||||
*
|
||||
* \note Remarks regarding event-driven DTLS:
|
||||
* - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
|
||||
* from the underlying transport layer is currently being processed,
|
||||
* and it is safe to idle until the timer or the underlying transport
|
||||
* signal a new event.
|
||||
* - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was
|
||||
* initially available on the underlying transport, as this data may have
|
||||
* been only e.g. duplicated messages or a renegotiation request.
|
||||
* Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even
|
||||
* when reacting to an incoming-data event from the underlying transport.
|
||||
* - On success, the datagram of the underlying transport that is currently
|
||||
* being processed may contain further DTLS records. You should call
|
||||
* \c mbedtls_ssl_check_pending to check for remaining records.
|
||||
*
|
||||
*/
|
||||
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len );
|
||||
|
||||
|
@ -2529,11 +2614,11 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
* or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
|
||||
* or another negative error code.
|
||||
*
|
||||
* \note If this function returns something other than a positive
|
||||
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* \note If this function returns something other than a positive value
|
||||
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*
|
||||
* \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
|
||||
* it must be called later with the *same* arguments,
|
||||
|
@ -2562,10 +2647,10 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_
|
|||
* \return 0 if successful, or a specific SSL error code.
|
||||
*
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*/
|
||||
int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
||||
unsigned char level,
|
||||
|
@ -2578,10 +2663,10 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
|||
* \return 0 if successful, or a specific SSL error code.
|
||||
*
|
||||
* \note If this function returns something other than 0 or
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
||||
* becomes unusable, and you should either free it or call
|
||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
||||
* a new connection; the current connection must be closed.
|
||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||
* the SSL context for reading or writing, and either free it or
|
||||
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||
* for a new connection; the current connection must be closed.
|
||||
*/
|
||||
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||
if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" );
|
||||
mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) )
|
||||
|
@ -491,6 +491,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||
mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
|
||||
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
|
||||
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
|
||||
#endif /* MBEDTLS_SSL_TLS_C */
|
||||
|
||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||
|
@ -745,6 +747,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||
mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" );
|
||||
if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) )
|
||||
mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" );
|
||||
if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) )
|
||||
mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" );
|
||||
if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) )
|
||||
mbedtls_snprintf( buf, buflen, "NET - Input invalid" );
|
||||
#endif /* MBEDTLS_NET_C */
|
||||
|
||||
#if defined(MBEDTLS_OID_C)
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
|
||||
!defined(EFI32)
|
||||
|
||||
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
|
||||
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#endif
|
||||
|
@ -82,6 +84,8 @@ static int wsa_init_done = 0;
|
|||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define IS_EINTR( ret ) ( ( ret ) == EINTR )
|
||||
|
||||
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
||||
|
||||
/* Some MS functions want int and MSVC warns if we pass size_t,
|
||||
|
@ -438,6 +442,68 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if data is available on the socket
|
||||
*/
|
||||
|
||||
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
|
||||
{
|
||||
int ret;
|
||||
struct timeval tv;
|
||||
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
|
||||
int fd = ctx->fd;
|
||||
|
||||
if( fd < 0 )
|
||||
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
|
||||
|
||||
/* Ensure that memory sanitizers consider
|
||||
* read_fds and write_fds as initialized even
|
||||
* if FD_ZERO is implemented in assembly. */
|
||||
memset( &read_fds, 0, sizeof( read_fds ) );
|
||||
memset( &write_fds, 0, sizeof( write_fds ) );
|
||||
|
||||
FD_ZERO( &read_fds );
|
||||
if( rw & MBEDTLS_NET_POLL_READ )
|
||||
{
|
||||
rw &= ~MBEDTLS_NET_POLL_READ;
|
||||
FD_SET( fd, &read_fds );
|
||||
}
|
||||
|
||||
FD_ZERO( &write_fds );
|
||||
if( rw & MBEDTLS_NET_POLL_WRITE )
|
||||
{
|
||||
rw &= ~MBEDTLS_NET_POLL_WRITE;
|
||||
FD_SET( fd, &write_fds );
|
||||
}
|
||||
|
||||
if( rw != 0 )
|
||||
return( MBEDTLS_ERR_NET_BAD_INPUT_DATA );
|
||||
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = ( timeout % 1000 ) * 1000;
|
||||
|
||||
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 );
|
||||
|
||||
ret = 0;
|
||||
if( FD_ISSET( fd, &read_fds ) )
|
||||
ret |= MBEDTLS_NET_POLL_READ;
|
||||
if( FD_ISSET( fd, &write_fds ) )
|
||||
ret |= MBEDTLS_NET_POLL_WRITE;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
/*
|
||||
* Portable usleep helper
|
||||
*/
|
||||
|
@ -497,8 +563,8 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
|
|||
/*
|
||||
* 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;
|
||||
struct timeval tv;
|
||||
|
|
|
@ -3750,7 +3750,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
/* Read the message without adding it to the checksum */
|
||||
do {
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
|
||||
do ret = mbedtls_ssl_read_record_layer( ssl );
|
||||
while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||
return( ret );
|
||||
|
@ -3758,7 +3761,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
|
||||
ret = mbedtls_ssl_handle_message_type( ssl );
|
||||
|
||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
|
||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
|
||||
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
|
||||
|
||||
if( 0 != ret )
|
||||
{
|
||||
|
|
|
@ -2337,7 +2337,10 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
|
|||
* that will end up being dropped.
|
||||
*/
|
||||
if( ssl_check_timer( ssl ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
|
||||
ret = MBEDTLS_ERR_SSL_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
|
||||
|
@ -3085,7 +3088,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
|
|||
if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
|
||||
|
@ -3162,9 +3165,11 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
|
|||
int ret;
|
||||
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
|
||||
|
||||
/* ssl->handshake is NULL when receiving ClientHello for renego */
|
||||
if( ssl->handshake != NULL &&
|
||||
recv_msg_seq != ssl->handshake->in_msg_seq )
|
||||
( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
|
||||
recv_msg_seq != ssl->handshake->in_msg_seq ) ||
|
||||
( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
|
||||
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
|
||||
{
|
||||
/* Retransmit only on last message from previous flight, to avoid
|
||||
* too many retransmissions.
|
||||
|
@ -3191,7 +3196,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
|
|||
ssl->handshake->in_msg_seq ) );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
}
|
||||
/* Wait until message completion to increment in_msg_seq */
|
||||
|
||||
|
@ -3594,81 +3599,23 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
/* Check length against bounds of the current transform and version */
|
||||
if( ssl->transform_in == NULL )
|
||||
{
|
||||
if( ssl->in_msglen < 1 ||
|
||||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ssl->in_msglen < ssl->transform_in->minlen )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/*
|
||||
* TLS encrypted messages can have up to 256 bytes of padding
|
||||
*/
|
||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen +
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* DTLS-related tests done last, because most of them may result in
|
||||
* silently dropping the record (but not the whole datagram), and we only
|
||||
* want to consider that after ensuring that the "basic" fields (type,
|
||||
* version, length) are sane.
|
||||
* DTLS-related tests.
|
||||
* Check epoch before checking length constraint because
|
||||
* the latter varies with the epoch. E.g., if a ChangeCipherSpec
|
||||
* message gets duplicated before the corresponding Finished message,
|
||||
* the second ChangeCipherSpec should be discarded because it belongs
|
||||
* to an old epoch, but not because its length is shorter than
|
||||
* the minimum record length for packets using the new record transform.
|
||||
* Note that these two kinds of failures are handled differently,
|
||||
* as an unexpected record is silently skipped but an invalid
|
||||
* record leads to the entire datagram being dropped.
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
{
|
||||
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
|
||||
|
||||
/* Drop unexpected ChangeCipherSpec messages */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Drop unexpected ApplicationData records,
|
||||
* except at the beginning of renegotiations */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
||||
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
||||
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Check epoch (and sequence number) with DTLS */
|
||||
if( rec_epoch != ssl->in_epoch )
|
||||
{
|
||||
|
@ -3708,9 +3655,74 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Drop unexpected ChangeCipherSpec messages */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
||||
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
|
||||
/* Drop unexpected ApplicationData records,
|
||||
* except at the beginning of renegotiations */
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
||||
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
||||
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
|
||||
/* Check length against bounds of the current transform and version */
|
||||
if( ssl->transform_in == NULL )
|
||||
{
|
||||
if( ssl->in_msglen < 1 ||
|
||||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ssl->in_msglen < ssl->transform_in->minlen )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/*
|
||||
* TLS encrypted messages can have up to 256 bytes of padding
|
||||
*/
|
||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
||||
ssl->in_msglen > ssl->transform_in->minlen +
|
||||
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -3799,7 +3811,10 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
|
|||
{
|
||||
do {
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
|
||||
do ret = mbedtls_ssl_read_record_layer( ssl );
|
||||
while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
|
||||
if( ret != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||
return( ret );
|
||||
|
@ -3807,11 +3822,12 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
|
|||
|
||||
ret = mbedtls_ssl_handle_message_type( ssl );
|
||||
|
||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
|
||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
|
||||
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
|
||||
|
||||
if( 0 != ret )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
@ -3849,11 +3865,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||
* (2) Alert messages:
|
||||
* Consume whole record content, in_msglen = 0.
|
||||
*
|
||||
* NOTE: This needs to be fixed, since like for
|
||||
* handshake messages it is allowed to have
|
||||
* multiple alerts witin a single record.
|
||||
* Internal reference IOTSSL-1321.
|
||||
*
|
||||
* (3) Change cipher spec:
|
||||
* Consume whole record content, in_msglen = 0.
|
||||
*
|
||||
|
@ -3881,12 +3892,12 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||
*/
|
||||
|
||||
/* Notes:
|
||||
* (1) in_hslen is *NOT* necessarily the size of the
|
||||
* (1) in_hslen is not necessarily the size of the
|
||||
* current handshake content: If DTLS handshake
|
||||
* fragmentation is used, that's the fragment
|
||||
* size instead. Using the total handshake message
|
||||
* size here is FAULTY and should be changed at
|
||||
* some point. Internal reference IOTSSL-1414.
|
||||
* size here is faulty and should be changed at
|
||||
* some point.
|
||||
* (2) While it doesn't seem to cause problems, one
|
||||
* has to be very careful not to assume that in_hslen
|
||||
* is always <= in_msglen in a sensible communication.
|
||||
|
@ -3937,12 +3948,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
/* Need to fetch a new record */
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
read_record_header:
|
||||
#endif
|
||||
|
||||
/* Current record either fully processed or to be discarded. */
|
||||
|
||||
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
|
||||
|
@ -3977,7 +3982,7 @@ read_record_header:
|
|||
}
|
||||
|
||||
/* Get next record */
|
||||
goto read_record_header;
|
||||
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
}
|
||||
#endif
|
||||
return( ret );
|
||||
|
@ -3996,7 +4001,13 @@ read_record_header:
|
|||
/* Done reading this record, get ready for the next one */
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
{
|
||||
ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl );
|
||||
if( ssl->next_record_offset < ssl->in_left )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
ssl->in_left = 0;
|
||||
|
@ -4043,7 +4054,7 @@ read_record_header:
|
|||
ssl->in_left = 0;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
|
||||
goto read_record_header;
|
||||
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
|
@ -4064,46 +4075,6 @@ read_record_header:
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When we sent the last flight of the handshake, we MUST respond to a
|
||||
* retransmit of the peer's previous flight with a retransmit. (In
|
||||
* practice, only the Finished message will make it, other messages
|
||||
* including CCS use the old transform so they're dropped as invalid.)
|
||||
*
|
||||
* If the record we received is not a handshake message, however, it
|
||||
* means the peer received our last flight so we can clean up
|
||||
* handshake info.
|
||||
*
|
||||
* This check needs to be done before prepare_handshake() due to an edge
|
||||
* case: if the client immediately requests renegotiation, this
|
||||
* finishes the current handshake first, avoiding the new ClientHello
|
||||
* being mistaken for an ancient message in the current handshake.
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->handshake != NULL &&
|
||||
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
|
||||
{
|
||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) );
|
||||
|
||||
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
}
|
||||
else
|
||||
{
|
||||
ssl_handshake_wrapup_free_hs_transform( ssl );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -4148,7 +4119,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
|
|||
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
||||
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
|
||||
/* Will be handled when trying to parse ServerHello */
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -4170,6 +4141,15 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
|
|||
return MBEDTLS_ERR_SSL_NON_FATAL;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->handshake != NULL &&
|
||||
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
|
||||
{
|
||||
ssl_handshake_wrapup_free_hs_transform( ssl );
|
||||
}
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
@ -6506,6 +6486,61 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
|
|||
return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
|
||||
}
|
||||
|
||||
int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
|
||||
{
|
||||
/*
|
||||
* Case A: We're currently holding back
|
||||
* a message for further processing.
|
||||
*/
|
||||
|
||||
if( ssl->keep_current_message == 1 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Case B: Further records are pending in the current datagram.
|
||||
*/
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||
ssl->in_left > ssl->next_record_offset )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
|
||||
return( 1 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
/*
|
||||
* Case C: A handshake message is being processed.
|
||||
*/
|
||||
|
||||
if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Case D: An application data message is being processed
|
||||
*/
|
||||
if( ssl->in_offt != NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* In all other cases, the rest of the message can be dropped.
|
||||
* As in ssl_read_record_layer, this needs to be adapted if
|
||||
* we implement support for multiple alerts in single records.
|
||||
*/
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl )
|
||||
{
|
||||
if( ssl->session != NULL )
|
||||
|
@ -6914,25 +6949,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
}
|
||||
|
||||
/*
|
||||
* TODO
|
||||
*
|
||||
* The logic should be streamlined here:
|
||||
*
|
||||
* Instead of
|
||||
*
|
||||
* The logic could be streamlined here. Instead of
|
||||
* - Manually checking whether ssl->in_offt is NULL
|
||||
* - Fetching a new record if yes
|
||||
* - Setting ssl->in_offt if one finds an application record
|
||||
* - Resetting keep_current_message after handling the application data
|
||||
*
|
||||
* one should
|
||||
*
|
||||
* - Adapt read_record to set ssl->in_offt automatically
|
||||
* when a new application data record is processed.
|
||||
* - Always call mbedtls_ssl_read_record here.
|
||||
*
|
||||
* This way, the logic of ssl_read would be much clearer:
|
||||
*
|
||||
* (1) Always call record layer and see what kind of record is on
|
||||
* and have it ready for consumption (in particular, in_offt
|
||||
* properly set for application data records).
|
||||
|
@ -6942,13 +6968,12 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
* (3) If it's something different from application data,
|
||||
* handle it accordingly, e.g. potentially start a
|
||||
* renegotiation.
|
||||
*
|
||||
* This will also remove the need to manually reset
|
||||
* ssl->keep_current_message = 0 below.
|
||||
*
|
||||
*/
|
||||
|
||||
if( ssl->in_offt == NULL )
|
||||
/* Loop as long as no application data record is available */
|
||||
while( ssl->in_offt == NULL )
|
||||
{
|
||||
/* Start timer if not already running */
|
||||
if( ssl->f_get_timer != NULL &&
|
||||
|
@ -7002,7 +7027,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
/* With DTLS, drop the packet (probably from last handshake) */
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
}
|
||||
|
@ -7017,7 +7044,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
/* With DTLS, drop the packet (probably from last handshake) */
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
{
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
}
|
||||
|
@ -7090,7 +7119,25 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||
}
|
||||
}
|
||||
|
||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
||||
/* At this point, we don't know whether the renegotiation has been
|
||||
* completed or not. The cases to consider are the following:
|
||||
* 1) The renegotiation is complete. In this case, no new record
|
||||
* has been read yet.
|
||||
* 2) The renegotiation is incomplete because the client received
|
||||
* an application data record while awaiting the ServerHello.
|
||||
* 3) The renegotiation is incomplete because the client received
|
||||
* a non-handshake, non-application data message while awaiting
|
||||
* the ServerHello.
|
||||
* In each of these case, looping will be the proper action:
|
||||
* - For 1), the next iteration will read a new record and check
|
||||
* if it's application data.
|
||||
* - For 2), the loop condition isn't satisfied as application data
|
||||
* is present, hence continue is the same as break
|
||||
* - For 3), the loop condition is satisfied and read_record
|
||||
* will re-deliver the message that was held back by the client
|
||||
* when expecting the ServerHello.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
|
||||
|
|
|
@ -73,6 +73,7 @@ int main( void )
|
|||
#define DFL_REQUEST_SIZE -1
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
#define DFL_NBIO 0
|
||||
#define DFL_EVENT 0
|
||||
#define DFL_READ_TIMEOUT 0
|
||||
#define DFL_MAX_RESEND 0
|
||||
#define DFL_CA_FILE ""
|
||||
|
@ -250,6 +251,8 @@ int main( void )
|
|||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||
" event=%%d default: 0 (loop)\n" \
|
||||
" options: 1 (level-triggered, implies nbio=1),\n" \
|
||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||
" max_resend=%%d default: 0 (no resend on timeout)\n" \
|
||||
"\n" \
|
||||
|
@ -302,6 +305,7 @@ struct options
|
|||
const char *server_port; /* port on which the ssl service runs */
|
||||
int debug_level; /* level of debugging */
|
||||
int nbio; /* should I/O be blocking? */
|
||||
int event; /* loop or event-driven IO? level or edge triggered? */
|
||||
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
||||
int max_resend; /* DTLS times to resend on read timeout */
|
||||
const char *request_page; /* page on server to request */
|
||||
|
@ -353,7 +357,8 @@ static void my_debug( void *ctx, int level,
|
|||
if( *p == '/' || *p == '\\' )
|
||||
basename = p + 1;
|
||||
|
||||
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s", basename, line, level, str );
|
||||
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s",
|
||||
basename, line, level, str );
|
||||
fflush( (FILE *) ctx );
|
||||
}
|
||||
|
||||
|
@ -399,7 +404,8 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len )
|
|||
/*
|
||||
* Enabled if debug_level > 1 in code below
|
||||
*/
|
||||
static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
|
||||
static int my_verify( void *data, mbedtls_x509_crt *crt,
|
||||
int depth, uint32_t *flags )
|
||||
{
|
||||
char buf[1024];
|
||||
((void) data);
|
||||
|
@ -436,6 +442,57 @@ static int ssl_sig_hashes_for_test[] = {
|
|||
};
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
* Wait for an event from the underlying transport or the timer
|
||||
* (Used in event-driven IO mode).
|
||||
*/
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
int idle( mbedtls_net_context *fd,
|
||||
int idle_reason )
|
||||
#else
|
||||
int idle( mbedtls_net_context *fd,
|
||||
mbedtls_timing_delay_context *timer,
|
||||
int idle_reason )
|
||||
#endif
|
||||
{
|
||||
|
||||
int ret;
|
||||
int poll_type = 0;
|
||||
|
||||
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
poll_type = MBEDTLS_NET_POLL_WRITE;
|
||||
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
|
||||
poll_type = MBEDTLS_NET_POLL_READ;
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
else
|
||||
return( 0 );
|
||||
#endif
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
/* Check if timer has expired */
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
if( timer != NULL &&
|
||||
mbedtls_timing_get_delay( timer ) == 2 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
/* Check if underlying transport became available */
|
||||
if( poll_type != 0 )
|
||||
{
|
||||
ret = mbedtls_net_poll( fd, poll_type, 0 );
|
||||
if( ret < 0 )
|
||||
return( ret );
|
||||
if( ret == poll_type )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
int ret = 0, len, tail_len, i, written, frags, retry_left;
|
||||
|
@ -521,6 +578,7 @@ int main( int argc, char *argv[] )
|
|||
opt.server_port = DFL_SERVER_PORT;
|
||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||
opt.nbio = DFL_NBIO;
|
||||
opt.event = DFL_EVENT;
|
||||
opt.read_timeout = DFL_READ_TIMEOUT;
|
||||
opt.max_resend = DFL_MAX_RESEND;
|
||||
opt.request_page = DFL_REQUEST_PAGE;
|
||||
|
@ -594,6 +652,12 @@ int main( int argc, char *argv[] )
|
|||
if( opt.nbio < 0 || opt.nbio > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "event" ) == 0 )
|
||||
{
|
||||
opt.event = atoi( q );
|
||||
if( opt.event < 0 || opt.event > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "read_timeout" ) == 0 )
|
||||
opt.read_timeout = atoi( q );
|
||||
else if( strcmp( p, "max_resend" ) == 0 )
|
||||
|
@ -638,16 +702,23 @@ int main( int argc, char *argv[] )
|
|||
}
|
||||
else if( strcmp( p, "renegotiation" ) == 0 )
|
||||
{
|
||||
opt.renegotiation = (atoi( q )) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||
opt.renegotiation = (atoi( q )) ?
|
||||
MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
||||
}
|
||||
else if( strcmp( p, "allow_legacy" ) == 0 )
|
||||
{
|
||||
switch( atoi( q ) )
|
||||
{
|
||||
case -1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; break;
|
||||
case 0: opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; break;
|
||||
case 1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; break;
|
||||
case -1:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE;
|
||||
break;
|
||||
case 0:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
|
||||
break;
|
||||
case 1:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION;
|
||||
break;
|
||||
default: goto usage;
|
||||
}
|
||||
}
|
||||
|
@ -704,8 +775,12 @@ int main( int argc, char *argv[] )
|
|||
{
|
||||
switch( atoi( q ) )
|
||||
{
|
||||
case 0: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; break;
|
||||
case 1: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; break;
|
||||
case 0:
|
||||
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED;
|
||||
break;
|
||||
case 1:
|
||||
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
|
||||
break;
|
||||
default: goto usage;
|
||||
}
|
||||
}
|
||||
|
@ -864,6 +939,15 @@ int main( int argc, char *argv[] )
|
|||
goto usage;
|
||||
}
|
||||
|
||||
/* Event-driven IO is incompatible with the above custom
|
||||
* receive and send functions, as the polling builds on
|
||||
* refers to the underlying net_context. */
|
||||
if( opt.event == 1 && opt.nbio != 1 )
|
||||
{
|
||||
mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" );
|
||||
opt.nbio = 1;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold( opt.debug_level );
|
||||
#endif
|
||||
|
@ -871,7 +955,8 @@ int main( int argc, char *argv[] )
|
|||
if( opt.force_ciphersuite[0] > 0 )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||
ciphersuite_info =
|
||||
mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||
|
||||
if( opt.max_version != -1 &&
|
||||
ciphersuite_info->min_minor_ver > opt.max_version )
|
||||
|
@ -1051,11 +1136,12 @@ int main( int argc, char *argv[] )
|
|||
fflush( stdout );
|
||||
|
||||
mbedtls_entropy_init( &entropy );
|
||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *) pers,
|
||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
|
||||
&entropy, (const unsigned char *) pers,
|
||||
strlen( pers ) ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1098,7 +1184,8 @@ int main( int argc, char *argv[] )
|
|||
#endif
|
||||
if( ret < 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1208,8 @@ int main( int argc, char *argv[] )
|
|||
else
|
||||
#endif
|
||||
#if defined(MBEDTLS_CERTS_C)
|
||||
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
|
||||
ret = mbedtls_x509_crt_parse( &clicert,
|
||||
(const unsigned char *) mbedtls_test_cli_crt,
|
||||
mbedtls_test_cli_crt_len );
|
||||
#else
|
||||
{
|
||||
|
@ -1131,7 +1219,8 @@ int main( int argc, char *argv[] )
|
|||
#endif
|
||||
if( ret != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1144,7 +1233,8 @@ int main( int argc, char *argv[] )
|
|||
else
|
||||
#endif
|
||||
#if defined(MBEDTLS_CERTS_C)
|
||||
ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key,
|
||||
ret = mbedtls_pk_parse_key( &pkey,
|
||||
(const unsigned char *) mbedtls_test_cli_key,
|
||||
mbedtls_test_cli_key_len, NULL, 0 );
|
||||
#else
|
||||
{
|
||||
|
@ -1154,7 +1244,8 @@ int main( int argc, char *argv[] )
|
|||
#endif
|
||||
if( ret != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1172,11 +1263,13 @@ int main( int argc, char *argv[] )
|
|||
opt.server_addr, opt.server_port );
|
||||
fflush( stdout );
|
||||
|
||||
if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.server_port,
|
||||
if( ( ret = mbedtls_net_connect( &server_fd,
|
||||
opt.server_addr, opt.server_port,
|
||||
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
||||
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1186,7 +1279,8 @@ int main( int argc, char *argv[] )
|
|||
ret = mbedtls_net_set_block( &server_fd );
|
||||
if( ret != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1203,7 +1297,8 @@ int main( int argc, char *argv[] )
|
|||
opt.transport,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1226,13 +1321,15 @@ int main( int argc, char *argv[] )
|
|||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
|
||||
mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max );
|
||||
mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min,
|
||||
opt.hs_to_max );
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||
if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
@ -1268,7 +1365,8 @@ int main( int argc, char *argv[] )
|
|||
if( opt.alpn_string != NULL )
|
||||
if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
@ -1307,7 +1405,8 @@ int main( int argc, char *argv[] )
|
|||
{
|
||||
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -1326,16 +1425,19 @@ int main( int argc, char *argv[] )
|
|||
(const unsigned char *) opt.psk_identity,
|
||||
strlen( opt.psk_identity ) ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( opt.min_version != DFL_MIN_VERSION )
|
||||
mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.min_version );
|
||||
mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||
opt.min_version );
|
||||
|
||||
if( opt.max_version != DFL_MAX_VERSION )
|
||||
mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.max_version );
|
||||
mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||
opt.max_version );
|
||||
|
||||
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
|
||||
if( opt.fallback != DFL_FALLBACK )
|
||||
|
@ -1344,14 +1446,16 @@ int main( int argc, char *argv[] )
|
|||
|
||||
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
@ -1363,7 +1467,8 @@ int main( int argc, char *argv[] )
|
|||
(const unsigned char *) opt.ecjpake_pw,
|
||||
strlen( opt.ecjpake_pw ) ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -1372,7 +1477,8 @@ int main( int argc, char *argv[] )
|
|||
if( opt.nbio == 2 )
|
||||
mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL );
|
||||
else
|
||||
mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv,
|
||||
mbedtls_ssl_set_bio( &ssl, &server_fd,
|
||||
mbedtls_net_send, mbedtls_net_recv,
|
||||
opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL );
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
|
@ -1390,9 +1496,11 @@ int main( int argc, char *argv[] )
|
|||
|
||||
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n",
|
||||
-ret );
|
||||
if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
|
||||
mbedtls_printf(
|
||||
" Unable to verify the server's certificate. "
|
||||
|
@ -1404,10 +1512,23 @@ int main( int argc, char *argv[] )
|
|||
mbedtls_printf( "\n" );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
ret = idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
ret = idle( &server_fd, ret );
|
||||
#endif
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
|
||||
mbedtls_ssl_get_version( &ssl ), mbedtls_ssl_get_ciphersuite( &ssl ) );
|
||||
mbedtls_ssl_get_version( &ssl ),
|
||||
mbedtls_ssl_get_ciphersuite( &ssl ) );
|
||||
|
||||
if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 )
|
||||
mbedtls_printf( " [ Record expansion is %d ]\n", ret );
|
||||
|
@ -1435,7 +1556,8 @@ int main( int argc, char *argv[] )
|
|||
|
||||
if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1454,7 +1576,8 @@ int main( int argc, char *argv[] )
|
|||
|
||||
mbedtls_printf( " failed\n" );
|
||||
|
||||
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
|
||||
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ),
|
||||
" ! ", flags );
|
||||
|
||||
mbedtls_printf( "%s\n", vrfy_buf );
|
||||
}
|
||||
|
@ -1484,9 +1607,21 @@ int main( int argc, char *argv[] )
|
|||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
mbedtls_printf( " ok\n" );
|
||||
}
|
||||
|
@ -1530,27 +1665,54 @@ send_request:
|
|||
{
|
||||
for( written = 0, frags = 0; written < len; written += ret, frags++ )
|
||||
{
|
||||
while( ( ret = mbedtls_ssl_write( &ssl, buf + written, len - written ) )
|
||||
<= 0 )
|
||||
while( ( ret = mbedtls_ssl_write( &ssl, buf + written,
|
||||
len - written ) ) <= 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not stream, so datagram */
|
||||
{
|
||||
do ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1565,7 +1727,8 @@ send_request:
|
|||
}
|
||||
|
||||
buf[written] = '\0';
|
||||
mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
|
||||
mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n",
|
||||
written, frags, (char *) buf );
|
||||
|
||||
/*
|
||||
* 7. Read the HTTP response
|
||||
|
@ -1586,7 +1749,18 @@ send_request:
|
|||
|
||||
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
|
@ -1604,7 +1778,8 @@ send_request:
|
|||
goto reconnect;
|
||||
|
||||
default:
|
||||
mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret );
|
||||
mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -1628,9 +1803,24 @@ send_request:
|
|||
len = sizeof( buf ) - 1;
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
|
||||
do ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
|
@ -1671,7 +1861,8 @@ send_request:
|
|||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1680,9 +1871,20 @@ send_request:
|
|||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &server_fd, &timer, ret );
|
||||
#else
|
||||
idle( &server_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf( " ok\n" );
|
||||
|
@ -1729,21 +1931,25 @@ reconnect:
|
|||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n", ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n",
|
||||
ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.server_port,
|
||||
if( ( ret = mbedtls_net_connect( &server_fd,
|
||||
opt.server_addr, opt.server_port,
|
||||
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
||||
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1763,7 +1969,8 @@ reconnect:
|
|||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ int main( void )
|
|||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
#define DFL_NBIO 0
|
||||
#define DFL_EVENT 0
|
||||
#define DFL_READ_TIMEOUT 0
|
||||
#define DFL_CA_FILE ""
|
||||
#define DFL_CA_PATH ""
|
||||
|
@ -331,6 +332,8 @@ int main( void )
|
|||
" debug_level=%%d default: 0 (disabled)\n" \
|
||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||
" event=%%d default: 0 (loop)\n" \
|
||||
" options: 1 (level-triggered, implies nbio=1),\n" \
|
||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||
"\n" \
|
||||
USAGE_DTLS \
|
||||
|
@ -399,6 +402,7 @@ struct options
|
|||
const char *server_port; /* port on which the ssl service runs */
|
||||
int debug_level; /* level of debugging */
|
||||
int nbio; /* should I/O be blocking? */
|
||||
int event; /* loop or event-driven IO? level or edge triggered? */
|
||||
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
||||
const char *ca_file; /* the file with the CA certificate(s) */
|
||||
const char *ca_path; /* the path with the CA certificate(s) reside */
|
||||
|
@ -837,6 +841,56 @@ static int ssl_sig_hashes_for_test[] = {
|
|||
};
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
* Wait for an event from the underlying transport or the timer
|
||||
* (Used in event-driven IO mode).
|
||||
*/
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
int idle( mbedtls_net_context *fd,
|
||||
int idle_reason )
|
||||
#else
|
||||
int idle( mbedtls_net_context *fd,
|
||||
mbedtls_timing_delay_context *timer,
|
||||
int idle_reason )
|
||||
#endif
|
||||
{
|
||||
int ret;
|
||||
int poll_type = 0;
|
||||
|
||||
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
poll_type = MBEDTLS_NET_POLL_WRITE;
|
||||
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
|
||||
poll_type = MBEDTLS_NET_POLL_READ;
|
||||
#if !defined(MBEDTLS_TIMING_C)
|
||||
else
|
||||
return( 0 );
|
||||
#endif
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
/* Check if timer has expired */
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
if( timer != NULL &&
|
||||
mbedtls_timing_get_delay( timer ) == 2 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
/* Check if underlying transport became available */
|
||||
if( poll_type != 0 )
|
||||
{
|
||||
ret = mbedtls_net_poll( fd, poll_type, 0 );
|
||||
if( ret < 0 )
|
||||
return( ret );
|
||||
if( ret == poll_type )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
int ret = 0, len, written, frags, exchanges_left;
|
||||
|
@ -969,6 +1023,7 @@ int main( int argc, char *argv[] )
|
|||
opt.server_addr = DFL_SERVER_ADDR;
|
||||
opt.server_port = DFL_SERVER_PORT;
|
||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||
opt.event = DFL_EVENT;
|
||||
opt.nbio = DFL_NBIO;
|
||||
opt.read_timeout = DFL_READ_TIMEOUT;
|
||||
opt.ca_file = DFL_CA_FILE;
|
||||
|
@ -1047,6 +1102,12 @@ int main( int argc, char *argv[] )
|
|||
if( opt.nbio < 0 || opt.nbio > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "event" ) == 0 )
|
||||
{
|
||||
opt.event = atoi( q );
|
||||
if( opt.event < 0 || opt.event > 2 )
|
||||
goto usage;
|
||||
}
|
||||
else if( strcmp( p, "read_timeout" ) == 0 )
|
||||
opt.read_timeout = atoi( q );
|
||||
else if( strcmp( p, "ca_file" ) == 0 )
|
||||
|
@ -1088,16 +1149,23 @@ int main( int argc, char *argv[] )
|
|||
opt.version_suites = q;
|
||||
else if( strcmp( p, "renegotiation" ) == 0 )
|
||||
{
|
||||
opt.renegotiation = (atoi( q )) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||
opt.renegotiation = (atoi( q )) ?
|
||||
MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
||||
}
|
||||
else if( strcmp( p, "allow_legacy" ) == 0 )
|
||||
{
|
||||
switch( atoi( q ) )
|
||||
{
|
||||
case -1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; break;
|
||||
case 0: opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; break;
|
||||
case 1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; break;
|
||||
case -1:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE;
|
||||
break;
|
||||
case 0:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
|
||||
break;
|
||||
case 1:
|
||||
opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION;
|
||||
break;
|
||||
default: goto usage;
|
||||
}
|
||||
}
|
||||
|
@ -1254,8 +1322,12 @@ int main( int argc, char *argv[] )
|
|||
{
|
||||
switch( atoi( q ) )
|
||||
{
|
||||
case 0: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; break;
|
||||
case 1: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; break;
|
||||
case 0:
|
||||
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED;
|
||||
break;
|
||||
case 1:
|
||||
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
|
||||
break;
|
||||
default: goto usage;
|
||||
}
|
||||
}
|
||||
|
@ -1328,6 +1400,15 @@ int main( int argc, char *argv[] )
|
|||
goto usage;
|
||||
}
|
||||
|
||||
/* Event-driven IO is incompatible with the above custom
|
||||
* receive and send functions, as the polling builds on
|
||||
* refers to the underlying net_context. */
|
||||
if( opt.event == 1 && opt.nbio != 1 )
|
||||
{
|
||||
mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" );
|
||||
opt.nbio = 1;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold( opt.debug_level );
|
||||
#endif
|
||||
|
@ -1335,7 +1416,8 @@ int main( int argc, char *argv[] )
|
|||
if( opt.force_ciphersuite[0] > 0 )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||
ciphersuite_info =
|
||||
mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||
|
||||
if( opt.max_version != -1 &&
|
||||
ciphersuite_info->min_minor_ver > opt.max_version )
|
||||
|
@ -1526,11 +1608,12 @@ int main( int argc, char *argv[] )
|
|||
fflush( stdout );
|
||||
|
||||
mbedtls_entropy_init( &entropy );
|
||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
|
||||
(const unsigned char *) pers,
|
||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
|
||||
&entropy, (const unsigned char *) pers,
|
||||
strlen( pers ) ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -1645,8 +1728,7 @@ int main( int argc, char *argv[] )
|
|||
strcmp( opt.key_file2, "none" ) != 0 )
|
||||
{
|
||||
#if !defined(MBEDTLS_CERTS_C)
|
||||
mbedtls_printf( "Not certificated or key provided, and \n"
|
||||
"MBEDTLS_CERTS_C not defined!\n" );
|
||||
mbedtls_printf( "Not certificated or key provided, and \nMBEDTLS_CERTS_C not defined!\n" );
|
||||
goto exit;
|
||||
#else
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
|
@ -1654,14 +1736,16 @@ int main( int argc, char *argv[] )
|
|||
(const unsigned char *) mbedtls_test_srv_crt_rsa,
|
||||
mbedtls_test_srv_crt_rsa_len ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
if( ( ret = mbedtls_pk_parse_key( &pkey,
|
||||
(const unsigned char *) mbedtls_test_srv_key_rsa,
|
||||
mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
key_cert_init = 2;
|
||||
|
@ -1671,14 +1755,16 @@ int main( int argc, char *argv[] )
|
|||
(const unsigned char *) mbedtls_test_srv_crt_ec,
|
||||
mbedtls_test_srv_crt_ec_len ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
if( ( ret = mbedtls_pk_parse_key( &pkey2,
|
||||
(const unsigned char *) mbedtls_test_srv_key_ec,
|
||||
mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
key_cert_init2 = 2;
|
||||
|
@ -2088,8 +2174,8 @@ reset:
|
|||
if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
|
||||
client_ip, cliip_len ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! "
|
||||
"mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret );
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n",
|
||||
-ret );
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
@ -2117,9 +2203,24 @@ handshake:
|
|||
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
|
||||
fflush( stdout );
|
||||
|
||||
do ret = mbedtls_ssl_handshake( &ssl );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||
{
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
ret = idle( &client_fd, &timer, ret );
|
||||
#else
|
||||
ret = idle( &client_fd, ret );
|
||||
#endif
|
||||
if( ret != 0 )
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
|
||||
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
|
||||
{
|
||||
|
@ -2225,7 +2326,18 @@ data_exchange:
|
|||
|
||||
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
{
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
|
@ -2313,9 +2425,40 @@ data_exchange:
|
|||
len = sizeof( buf ) - 1;
|
||||
memset( buf, 0, sizeof( buf ) );
|
||||
|
||||
do ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
/* Without the call to `mbedtls_ssl_check_pending`, it might
|
||||
* happen that the client sends application data in the same
|
||||
* datagram as the Finished message concluding the handshake.
|
||||
* In this case, the application data would be ready to be
|
||||
* processed while the underlying transport wouldn't signal
|
||||
* any further incoming data.
|
||||
*
|
||||
* See the test 'Event-driven I/O: session-id resume, UDP packing'
|
||||
* in tests/ssl-opt.sh.
|
||||
*/
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( mbedtls_ssl_check_pending( &ssl ) == 0 &&
|
||||
opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &client_fd, &timer, MBEDTLS_ERR_SSL_WANT_READ );
|
||||
#else
|
||||
idle( &client_fd, MBEDTLS_ERR_SSL_WANT_READ );
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||
|
||||
/* Note that even if `mbedtls_ssl_check_pending` returns true,
|
||||
* it can happen that the subsequent call to `mbedtls_ssl_read`
|
||||
* returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages
|
||||
* might be discarded (e.g. because they are retransmissions). */
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
}
|
||||
|
||||
if( ret <= 0 )
|
||||
{
|
||||
|
@ -2356,6 +2499,16 @@ data_exchange:
|
|||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
||||
goto reset;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_printf( " ok\n" );
|
||||
|
@ -2390,14 +2543,39 @@ data_exchange:
|
|||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
||||
goto reset;
|
||||
}
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Not stream, so datagram */
|
||||
{
|
||||
do ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
||||
while( 1 )
|
||||
{
|
||||
ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||
|
||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||
break;
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if( opt.event == 1 /* level triggered IO */ )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle( &client_fd, &timer, ret );
|
||||
#else
|
||||
idle( &client_fd, ret );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( ret < 0 )
|
||||
{
|
||||
|
|
|
@ -53,6 +53,7 @@ int main( void )
|
|||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/timing.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -74,17 +75,21 @@ int main( void )
|
|||
#include <unistd.h>
|
||||
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
||||
|
||||
/* For gettimeofday() */
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#define MAX_MSG_SIZE 16384 + 2048 /* max record/datagram size */
|
||||
|
||||
#define DFL_SERVER_ADDR "localhost"
|
||||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_LISTEN_ADDR "localhost"
|
||||
#define DFL_LISTEN_PORT "5556"
|
||||
#define DFL_PACK 0
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
#define USAGE_PACK \
|
||||
" pack=%%d default: 0 (don't pack)\n" \
|
||||
" options: t > 0 (pack for t milliseconds)\n"
|
||||
#else
|
||||
#define USAGE_PACK
|
||||
#endif
|
||||
|
||||
#define USAGE \
|
||||
"\n usage: udp_proxy param=<>...\n" \
|
||||
|
@ -108,6 +113,7 @@ int main( void )
|
|||
" protect_len=%%d default: (don't protect packets of this size)\n" \
|
||||
"\n" \
|
||||
" seed=%%d default: (use current time)\n" \
|
||||
USAGE_PACK \
|
||||
"\n"
|
||||
|
||||
/*
|
||||
|
@ -128,7 +134,8 @@ static struct options
|
|||
int bad_ad; /* inject corrupted ApplicationData record */
|
||||
int protect_hvr; /* never drop or delay HelloVerifyRequest */
|
||||
int protect_len; /* never drop/delay packet of the given size*/
|
||||
|
||||
unsigned pack; /* merge packets into single datagram for
|
||||
* at most \c merge milliseconds if > 0 */
|
||||
unsigned int seed; /* seed for "random" events */
|
||||
} opt;
|
||||
|
||||
|
@ -152,6 +159,7 @@ static void get_options( int argc, char *argv[] )
|
|||
opt.server_port = DFL_SERVER_PORT;
|
||||
opt.listen_addr = DFL_LISTEN_ADDR;
|
||||
opt.listen_port = DFL_LISTEN_PORT;
|
||||
opt.pack = DFL_PACK;
|
||||
/* Other members default to 0 */
|
||||
|
||||
for( i = 1; i < argc; i++ )
|
||||
|
@ -193,6 +201,15 @@ static void get_options( int argc, char *argv[] )
|
|||
if( opt.drop < 0 || opt.drop > 20 || opt.drop == 1 )
|
||||
exit_usage( p, q );
|
||||
}
|
||||
else if( strcmp( p, "pack" ) == 0 )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
opt.pack = (unsigned) atoi( q );
|
||||
#else
|
||||
mbedtls_printf( " option pack only defined if MBEDTLS_TIMING_C is enabled\n" );
|
||||
exit( 1 );
|
||||
#endif
|
||||
}
|
||||
else if( strcmp( p, "mtu" ) == 0 )
|
||||
{
|
||||
opt.mtu = atoi( q );
|
||||
|
@ -267,25 +284,122 @@ static const char *msg_type( unsigned char *msg, size_t len )
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
/* Return elapsed time in milliseconds since the first call */
|
||||
static unsigned long ellapsed_time( void )
|
||||
static unsigned ellapsed_time( void )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return( 0 );
|
||||
#else
|
||||
static struct timeval ref = { 0, 0 };
|
||||
struct timeval now;
|
||||
static int initialized = 0;
|
||||
static struct mbedtls_timing_hr_time hires;
|
||||
|
||||
if( ref.tv_sec == 0 && ref.tv_usec == 0 )
|
||||
if( initialized == 0 )
|
||||
{
|
||||
gettimeofday( &ref, NULL );
|
||||
(void) mbedtls_timing_get_timer( &hires, 1 );
|
||||
initialized = 1;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
gettimeofday( &now, NULL );
|
||||
return( 1000 * ( now.tv_sec - ref.tv_sec )
|
||||
+ ( now.tv_usec - ref.tv_usec ) / 1000 );
|
||||
#endif
|
||||
return( mbedtls_timing_get_timer( &hires, 0 ) );
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mbedtls_net_context *ctx;
|
||||
|
||||
const char *description;
|
||||
|
||||
unsigned packet_lifetime;
|
||||
unsigned num_datagrams;
|
||||
|
||||
unsigned char data[MAX_MSG_SIZE];
|
||||
size_t len;
|
||||
|
||||
} ctx_buffer;
|
||||
|
||||
static ctx_buffer outbuf[2];
|
||||
|
||||
static int ctx_buffer_flush( ctx_buffer *buf )
|
||||
{
|
||||
int ret;
|
||||
|
||||
mbedtls_printf( " %05u flush %s: %u bytes, %u datagrams, last %u ms\n",
|
||||
ellapsed_time(), buf->description,
|
||||
(unsigned) buf->len, buf->num_datagrams,
|
||||
ellapsed_time() - buf->packet_lifetime );
|
||||
|
||||
ret = mbedtls_net_send( buf->ctx, buf->data, buf->len );
|
||||
|
||||
buf->len = 0;
|
||||
buf->num_datagrams = 0;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static unsigned ctx_buffer_time_remaining( ctx_buffer *buf )
|
||||
{
|
||||
unsigned const cur_time = ellapsed_time();
|
||||
|
||||
if( buf->num_datagrams == 0 )
|
||||
return( (unsigned) -1 );
|
||||
|
||||
if( cur_time - buf->packet_lifetime >= opt.pack )
|
||||
return( 0 );
|
||||
|
||||
return( opt.pack - ( cur_time - buf->packet_lifetime ) );
|
||||
}
|
||||
|
||||
static int ctx_buffer_append( ctx_buffer *buf,
|
||||
const unsigned char * data,
|
||||
size_t len )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( len > (size_t) INT_MAX )
|
||||
return( -1 );
|
||||
|
||||
if( len > sizeof( buf->data ) )
|
||||
{
|
||||
mbedtls_printf( " ! buffer size %u too large (max %u)\n",
|
||||
(unsigned) len, (unsigned) sizeof( buf->data ) );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if( sizeof( buf->data ) - buf->len < len )
|
||||
{
|
||||
if( ( ret = ctx_buffer_flush( buf ) ) <= 0 )
|
||||
return( ret );
|
||||
}
|
||||
|
||||
memcpy( buf->data + buf->len, data, len );
|
||||
|
||||
buf->len += len;
|
||||
if( ++buf->num_datagrams == 1 )
|
||||
buf->packet_lifetime = ellapsed_time();
|
||||
|
||||
return( (int) len );
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
static int dispatch_data( mbedtls_net_context *ctx,
|
||||
const unsigned char * data,
|
||||
size_t len )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
ctx_buffer *buf = NULL;
|
||||
if( opt.pack > 0 )
|
||||
{
|
||||
if( outbuf[0].ctx == ctx )
|
||||
buf = &outbuf[0];
|
||||
else if( outbuf[1].ctx == ctx )
|
||||
buf = &outbuf[1];
|
||||
|
||||
if( buf == NULL )
|
||||
return( -1 );
|
||||
|
||||
return( ctx_buffer_append( buf, data, len ) );
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
return( mbedtls_net_send( ctx, data, len ) );
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -300,12 +414,22 @@ typedef struct
|
|||
/* Print packet. Outgoing packets come with a reason (forward, dupl, etc.) */
|
||||
void print_packet( const packet *p, const char *why )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
if( why == NULL )
|
||||
mbedtls_printf( " %05lu %s %s (%u bytes)\n",
|
||||
mbedtls_printf( " %05u dispatch %s %s (%u bytes)\n",
|
||||
ellapsed_time(), p->way, p->type, p->len );
|
||||
else
|
||||
mbedtls_printf( " %s %s (%u bytes): %s\n",
|
||||
mbedtls_printf( " %05u dispatch %s %s (%u bytes): %s\n",
|
||||
ellapsed_time(), p->way, p->type, p->len, why );
|
||||
#else
|
||||
if( why == NULL )
|
||||
mbedtls_printf( " dispatch %s %s (%u bytes)\n",
|
||||
p->way, p->type, p->len );
|
||||
else
|
||||
mbedtls_printf( " dispatch %s %s (%u bytes): %s\n",
|
||||
p->way, p->type, p->len, why );
|
||||
#endif
|
||||
|
||||
fflush( stdout );
|
||||
}
|
||||
|
||||
|
@ -320,20 +444,28 @@ int send_packet( const packet *p, const char *why )
|
|||
{
|
||||
unsigned char buf[MAX_MSG_SIZE];
|
||||
memcpy( buf, p->buf, p->len );
|
||||
++buf[p->len - 1];
|
||||
|
||||
print_packet( p, "corrupted" );
|
||||
if( ( ret = mbedtls_net_send( dst, buf, p->len ) ) <= 0 )
|
||||
if( p->len <= 13 )
|
||||
{
|
||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
||||
mbedtls_printf( " ! can't corrupt empty AD record" );
|
||||
}
|
||||
else
|
||||
{
|
||||
++buf[13];
|
||||
print_packet( p, "corrupted" );
|
||||
}
|
||||
|
||||
if( ( ret = dispatch_data( dst, buf, p->len ) ) <= 0 )
|
||||
{
|
||||
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
||||
print_packet( p, why );
|
||||
if( ( ret = mbedtls_net_send( dst, p->buf, p->len ) ) <= 0 )
|
||||
if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 )
|
||||
{
|
||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
||||
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
@ -344,9 +476,9 @@ int send_packet( const packet *p, const char *why )
|
|||
{
|
||||
print_packet( p, "duplicated" );
|
||||
|
||||
if( ( ret = mbedtls_net_send( dst, p->buf, p->len ) ) <= 0 )
|
||||
if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 )
|
||||
{
|
||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
||||
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||
return( ret );
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +604,12 @@ int main( int argc, char *argv[] )
|
|||
|
||||
mbedtls_net_context listen_fd, client_fd, server_fd;
|
||||
|
||||
#if defined( MBEDTLS_TIMING_C )
|
||||
struct timeval tm;
|
||||
#endif
|
||||
|
||||
struct timeval *tm_ptr = NULL;
|
||||
|
||||
int nb_fds;
|
||||
fd_set read_fds;
|
||||
|
||||
|
@ -560,14 +698,65 @@ accept:
|
|||
nb_fds = listen_fd.fd;
|
||||
++nb_fds;
|
||||
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
if( opt.pack > 0 )
|
||||
{
|
||||
outbuf[0].ctx = &server_fd;
|
||||
outbuf[0].description = "S <- C";
|
||||
outbuf[0].num_datagrams = 0;
|
||||
outbuf[0].len = 0;
|
||||
|
||||
outbuf[1].ctx = &client_fd;
|
||||
outbuf[1].description = "S -> C";
|
||||
outbuf[1].num_datagrams = 0;
|
||||
outbuf[1].len = 0;
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
if( opt.pack > 0 )
|
||||
{
|
||||
unsigned max_wait_server, max_wait_client, max_wait;
|
||||
max_wait_server = ctx_buffer_time_remaining( &outbuf[0] );
|
||||
max_wait_client = ctx_buffer_time_remaining( &outbuf[1] );
|
||||
|
||||
max_wait = (unsigned) -1;
|
||||
|
||||
if( max_wait_server == 0 )
|
||||
ctx_buffer_flush( &outbuf[0] );
|
||||
else
|
||||
max_wait = max_wait_server;
|
||||
|
||||
if( max_wait_client == 0 )
|
||||
ctx_buffer_flush( &outbuf[1] );
|
||||
else
|
||||
{
|
||||
if( max_wait_client < max_wait )
|
||||
max_wait = max_wait_client;
|
||||
}
|
||||
|
||||
if( max_wait != (unsigned) -1 )
|
||||
{
|
||||
tm.tv_sec = max_wait / 1000;
|
||||
tm.tv_usec = ( max_wait % 1000 ) * 1000;
|
||||
|
||||
tm_ptr = &tm;
|
||||
}
|
||||
else
|
||||
{
|
||||
tm_ptr = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_TIMING_C */
|
||||
|
||||
FD_ZERO( &read_fds );
|
||||
FD_SET( server_fd.fd, &read_fds );
|
||||
FD_SET( client_fd.fd, &read_fds );
|
||||
FD_SET( listen_fd.fd, &read_fds );
|
||||
|
||||
if( ( ret = select( nb_fds, &read_fds, NULL, NULL, NULL ) ) <= 0 )
|
||||
if( ( ret = select( nb_fds, &read_fds, NULL, NULL, tm_ptr ) ) < 0 )
|
||||
{
|
||||
perror( "select" );
|
||||
goto exit;
|
||||
|
@ -589,6 +778,7 @@ accept:
|
|||
&client_fd, &server_fd ) ) != 0 )
|
||||
goto accept;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exit:
|
||||
|
|
117
programs/test/udp_proxy_wrapper.sh
Executable file
117
programs/test/udp_proxy_wrapper.sh
Executable file
|
@ -0,0 +1,117 @@
|
|||
#!/bin/sh
|
||||
# -*-sh-basic-offset: 4-*-
|
||||
# Usage: udp_proxy_wrapper.sh [PROXY_PARAM...] -- [SERVER_PARAM...]
|
||||
|
||||
set -u
|
||||
|
||||
MBEDTLS_BASE="$(dirname -- "$0")/../.."
|
||||
TPXY_BIN="$MBEDTLS_BASE/programs/test/udp_proxy"
|
||||
SRV_BIN="$MBEDTLS_BASE/programs/ssl/ssl_server2"
|
||||
|
||||
: ${VERBOSE:=0}
|
||||
|
||||
stop_proxy() {
|
||||
if [ -n "${tpxy_pid:-}" ]; then
|
||||
echo
|
||||
echo " * Killing proxy (pid $tpxy_pid) ..."
|
||||
kill $tpxy_pid
|
||||
fi
|
||||
}
|
||||
|
||||
stop_server() {
|
||||
if [ -n "${srv_pid:-}" ]; then
|
||||
echo
|
||||
echo " * Killing server (pid $srv_pid) ..."
|
||||
kill $srv_pid >/dev/null 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
stop_server
|
||||
stop_proxy
|
||||
exit 129
|
||||
}
|
||||
|
||||
trap cleanup INT TERM HUP
|
||||
|
||||
# Extract the proxy parameters
|
||||
tpxy_cmd_snippet='"$TPXY_BIN"'
|
||||
while [ $# -ne 0 ] && [ "$1" != "--" ]; do
|
||||
tail="$1" quoted=""
|
||||
while [ -n "$tail" ]; do
|
||||
case "$tail" in
|
||||
*\'*) quoted="${quoted}${tail%%\'*}'\\''" tail="${tail#*\'}";;
|
||||
*) quoted="${quoted}${tail}"; tail=; false;;
|
||||
esac
|
||||
done
|
||||
tpxy_cmd_snippet="$tpxy_cmd_snippet '$quoted'"
|
||||
shift
|
||||
done
|
||||
unset tail quoted
|
||||
if [ $# -eq 0 ]; then
|
||||
echo " * No server arguments (must be preceded by \" -- \") - exit"
|
||||
exit 3
|
||||
fi
|
||||
shift
|
||||
|
||||
dtls_enabled=
|
||||
ipv6_in_use=
|
||||
server_port_orig=
|
||||
server_addr_orig=
|
||||
for param; do
|
||||
case "$param" in
|
||||
server_port=*) server_port_orig="${param#*=}";;
|
||||
server_addr=*:*) server_addr_orig="${param#*=}"; ipv6_in_use=1;;
|
||||
server_addr=*) server_addr_orig="${param#*=}";;
|
||||
dtls=[!0]*) dtls_enabled=1;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$dtls_enabled" ] || [ -n "$ipv6_in_use" ]; then
|
||||
echo >&2 "$0: Couldn't find DTLS enabling, or IPv6 is in use - immediate fallback to server application..."
|
||||
if [ $VERBOSE -gt 0 ]; then
|
||||
echo "[ $SRV_BIN $* ]"
|
||||
fi
|
||||
exec "$SRV_BIN" "$@"
|
||||
fi
|
||||
|
||||
if [ -z "$server_port_orig" ]; then
|
||||
server_port_orig=4433
|
||||
fi
|
||||
echo " * Server port: $server_port_orig"
|
||||
tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_port=\$server_port_orig\""
|
||||
tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_port=\$server_port\""
|
||||
|
||||
if [ -n "$server_addr_orig" ]; then
|
||||
echo " * Server address: $server_addr_orig"
|
||||
tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_addr=\$server_addr_orig\""
|
||||
tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_addr=\$server_addr_orig\""
|
||||
fi
|
||||
|
||||
server_port=$(( server_port_orig + 1 ))
|
||||
set -- "$@" "server_port=$server_port"
|
||||
echo " * Intermediate port: $server_port"
|
||||
|
||||
echo " * Start proxy in background ..."
|
||||
if [ $VERBOSE -gt 0 ]; then
|
||||
echo "[ $tpxy_cmd_snippet ]"
|
||||
fi
|
||||
eval exec "$tpxy_cmd_snippet" >/dev/null 2>&1 &
|
||||
tpxy_pid=$!
|
||||
|
||||
if [ $VERBOSE -gt 0 ]; then
|
||||
echo " * Proxy ID: $TPXY_PID"
|
||||
fi
|
||||
|
||||
echo " * Starting server ..."
|
||||
if [ $VERBOSE -gt 0 ]; then
|
||||
echo "[ $SRV_BIN $* ]"
|
||||
fi
|
||||
|
||||
exec "$SRV_BIN" "$@" >&2 &
|
||||
srv_pid=$!
|
||||
|
||||
wait $srv_pid
|
||||
|
||||
stop_proxy
|
||||
return 0
|
156
tests/ssl-opt.sh
156
tests/ssl-opt.sh
|
@ -465,9 +465,12 @@ run_test() {
|
|||
eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
|
||||
wait_client_done
|
||||
|
||||
sleep 0.05
|
||||
|
||||
# terminate the server (and the proxy)
|
||||
kill $SRV_PID
|
||||
wait $SRV_PID
|
||||
|
||||
if [ -n "$PXY_CMD" ]; then
|
||||
kill $PXY_PID >/dev/null 2>&1
|
||||
wait $PXY_PID
|
||||
|
@ -631,16 +634,19 @@ fi
|
|||
get_options "$@"
|
||||
|
||||
# sanity checks, avoid an avalanche of errors
|
||||
if [ ! -x "$P_SRV" ]; then
|
||||
echo "Command '$P_SRV' is not an executable file"
|
||||
P_SRV_BIN="${P_SRV%%[ ]*}"
|
||||
P_CLI_BIN="${P_CLI%%[ ]*}"
|
||||
P_PXY_BIN="${P_PXY%%[ ]*}"
|
||||
if [ ! -x "$P_SRV_BIN" ]; then
|
||||
echo "Command '$P_SRV_BIN' is not an executable file"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -x "$P_CLI" ]; then
|
||||
echo "Command '$P_CLI' is not an executable file"
|
||||
if [ ! -x "$P_CLI_BIN" ]; then
|
||||
echo "Command '$P_CLI_BIN' is not an executable file"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -x "$P_PXY" ]; then
|
||||
echo "Command '$P_PXY' is not an executable file"
|
||||
if [ ! -x "$P_PXY_BIN" ]; then
|
||||
echo "Command '$P_PXY_BIN' is not an executable file"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$MEMCHECK" -gt 0 ]; then
|
||||
|
@ -2704,6 +2710,118 @@ run_test "Non-blocking I/O: session-id resume" \
|
|||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
# Tests for event-driven I/O: exercise a variety of handshake flows
|
||||
|
||||
run_test "Event-driven I/O: basic handshake" \
|
||||
"$P_SRV event=1 tickets=0 auth_mode=none" \
|
||||
"$P_CLI event=1 tickets=0" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: client auth" \
|
||||
"$P_SRV event=1 tickets=0 auth_mode=required" \
|
||||
"$P_CLI event=1 tickets=0" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: ticket" \
|
||||
"$P_SRV event=1 tickets=1 auth_mode=none" \
|
||||
"$P_CLI event=1 tickets=1" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: ticket + client auth" \
|
||||
"$P_SRV event=1 tickets=1 auth_mode=required" \
|
||||
"$P_CLI event=1 tickets=1" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: ticket + client auth + resume" \
|
||||
"$P_SRV event=1 tickets=1 auth_mode=required" \
|
||||
"$P_CLI event=1 tickets=1 reconnect=1" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: ticket + resume" \
|
||||
"$P_SRV event=1 tickets=1 auth_mode=none" \
|
||||
"$P_CLI event=1 tickets=1 reconnect=1" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O: session-id resume" \
|
||||
"$P_SRV event=1 tickets=0 auth_mode=none" \
|
||||
"$P_CLI event=1 tickets=0 reconnect=1" \
|
||||
0 \
|
||||
-S "mbedtls_ssl_handshake returned" \
|
||||
-C "mbedtls_ssl_handshake returned" \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: basic handshake" \
|
||||
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=none" \
|
||||
"$P_CLI dtls=1 event=1 tickets=0" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: client auth" \
|
||||
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=required" \
|
||||
"$P_CLI dtls=1 event=1 tickets=0" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: ticket" \
|
||||
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
|
||||
"$P_CLI dtls=1 event=1 tickets=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: ticket + client auth" \
|
||||
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
|
||||
"$P_CLI dtls=1 event=1 tickets=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: ticket + client auth + resume" \
|
||||
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
|
||||
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: ticket + resume" \
|
||||
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
|
||||
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
run_test "Event-driven I/O, DTLS: session-id resume" \
|
||||
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=none" \
|
||||
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
# This test demonstrates the need for the mbedtls_ssl_check_pending function.
|
||||
# During session resumption, the client will send its ApplicationData record
|
||||
# within the same datagram as the Finished messages. In this situation, the
|
||||
# server MUST NOT idle on the underlying transport after handshake completion,
|
||||
# because the ApplicationData request has already been queued internally.
|
||||
run_test "Event-driven I/O, DTLS: session-id resume, UDP packing" \
|
||||
-p "$P_PXY pack=50" \
|
||||
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=required" \
|
||||
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
|
||||
0 \
|
||||
-c "Read from server: .* bytes read"
|
||||
|
||||
# Tests for version negotiation
|
||||
|
||||
run_test "Version check: all -> 1.2" \
|
||||
|
@ -4195,8 +4313,8 @@ run_test "DTLS proxy: duplicate every packet" \
|
|||
0 \
|
||||
-c "replayed record" \
|
||||
-s "replayed record" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-S "resend" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK"
|
||||
|
@ -4208,13 +4326,29 @@ run_test "DTLS proxy: duplicate every packet, server anti-replay off" \
|
|||
0 \
|
||||
-c "replayed record" \
|
||||
-S "replayed record" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-c "resend" \
|
||||
-s "resend" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK"
|
||||
|
||||
run_test "DTLS proxy: multiple records in same datagram" \
|
||||
-p "$P_PXY pack=50" \
|
||||
"$P_SRV dtls=1 debug_level=2" \
|
||||
"$P_CLI dtls=1 debug_level=2" \
|
||||
0 \
|
||||
-c "next record in same datagram" \
|
||||
-s "next record in same datagram"
|
||||
|
||||
run_test "DTLS proxy: multiple records in same datagram, duplicate every packet" \
|
||||
-p "$P_PXY pack=50 duplicate=1" \
|
||||
"$P_SRV dtls=1 debug_level=2" \
|
||||
"$P_CLI dtls=1 debug_level=2" \
|
||||
0 \
|
||||
-c "next record in same datagram" \
|
||||
-s "next record in same datagram"
|
||||
|
||||
run_test "DTLS proxy: inject invalid AD record, default badmac_limit" \
|
||||
-p "$P_PXY bad_ad=1" \
|
||||
"$P_SRV dtls=1 debug_level=1" \
|
||||
|
@ -4270,8 +4404,6 @@ run_test "DTLS proxy: delay ChangeCipherSpec" \
|
|||
0 \
|
||||
-c "record from another epoch" \
|
||||
-s "record from another epoch" \
|
||||
-c "discarding invalid record" \
|
||||
-s "discarding invalid record" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK"
|
||||
|
||||
|
|
Loading…
Reference in a new issue