diff --git a/ChangeLog b/ChangeLog index 7824fc4212..38aaaa5469 100644 --- a/ChangeLog +++ b/ChangeLog @@ -94,6 +94,9 @@ Features errors on use of deprecated functions. Bugfix + * Fix potential NULL pointer dereference (not trigerrable remotely) when + ssl_write() is called before the handshake is finished (introduced in + 1.3.10) (first reported by Martin Blumenstingl). * Fix bug in pk_parse_key() that caused some valid private EC keys to be rejected. * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3dccb431e8..85a2622183 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6327,38 +6327,17 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) } /* - * Send application data to be encrypted by the SSL layer + * Send application data to be encrypted by the SSL layer, + * taking care of max fragment length and buffer size */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -static int ssl_write_real( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) -#else -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) -#endif +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) { int ret; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) unsigned int max_len; #endif - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /* * Assume mfl_code is correct since it was checked when set @@ -6411,8 +6390,6 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ } } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); - return( (int) len ); } @@ -6424,7 +6401,8 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ * remember wether we already did the split or not. */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +static int ssl_write_split( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) { int ret; @@ -6452,6 +6430,43 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_ } #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_handshake", ret ); + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + ret = ssl_write_split( ssl, buf, len ); +#else + ret = ssl_write_real( ssl, buf, len ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + /* * Notify the peer that the connection is being closed */