From 8ec8102c9a6356b420aebf5074d042902b060a2c Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 10 Oct 2017 10:35:08 +0100 Subject: [PATCH] Split WANT_READ in two error codes This commit restricts WANT_READ to indicate that no data is available on the underlying transport. To signal the need for further processing - which was previously also handled through this error code - a new internal error code MBEDTLS_ERR_SSL_CONTINUE_PROCESSING is introduced. --- include/mbedtls/ssl.h | 63 ++++++++++++++++++++++++++++++++++--------- library/error.c | 4 ++- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 8b82eff8f..e811bb907 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -102,13 +102,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 @@ -2397,6 +2398,19 @@ 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 MBEDTLS_ERR_SSL_WANT_READ is returned, the handshake is + * unfinished and no further data is available from the underlying + * transport. In this case, the function needs to be called 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 currently processed underlying transport's datagram + * 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 @@ -2460,20 +2474,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 for EOF, or + * - 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 @@ -2486,6 +2500,29 @@ 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! + * + * 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. + * + * \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. + * - If the function returns MBEDTLS_ERR_SSL_WANT_READ this does not mean + * that no data was available from the underlying transport in the first place, + * as there might have been delayed or duplicated messages, or a renegotiation + * request from the peer. Therefore, the user 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 currently processed underlying transport's datagram + * might or might not contain further DTLS records, and the user should + * consult \c mbedtls_ssl_check_pending in that regard. + * */ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); diff --git a/library/error.c b/library/error.c index 8977cc4e5..c42642467 100644 --- a/library/error.c +++ b/library/error.c @@ -426,7 +426,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) ) @@ -439,6 +439,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 signalling that further message-processing should be done" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)