diff --git a/include/polarssl/error.h b/include/polarssl/error.h index cdee952e0..7ce2828b2 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -91,7 +91,7 @@ * ECP 4 8 (Started from top) * MD 5 4 * CIPHER 6 6 - * SSL 6 9 (Started from top) + * SSL 6 10 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index bee86a6cc..6c6cb21b4 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -145,6 +145,7 @@ #define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ #define POLARSSL_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ #define POLARSSL_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ /* * Various constants diff --git a/library/error.c b/library/error.c index 22234cf28..73504d450 100644 --- a/library/error.c +++ b/library/error.c @@ -450,6 +450,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); if( use_ret == -(POLARSSL_ERR_SSL_COUNTER_WRAPPING) ) snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); #endif /* POLARSSL_SSL_TLS_C */ #if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index d38d76955..089b7c96b 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -902,6 +902,12 @@ static int ssl_parse_server_hello( ssl_context *ssl ) if( ssl->in_msgtype != SSL_MSG_HANDSHAKE ) { + if( ssl->renegotiation == SSL_RENEGOTIATION ) + { + SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); + return( POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } + SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE ); } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1d68d965e..e6c4efdfd 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4260,14 +4260,19 @@ int ssl_renegotiate( ssl_context *ssl ) */ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) { - int ret; + int ret, record_read = 0; size_t n; SSL_DEBUG_MSG( 2, ( "=> read" ) ); if( ssl->state != SSL_HANDSHAKE_OVER ) { - if( ( ret = ssl_handshake( ssl ) ) != 0 ) + ret = ssl_handshake( ssl ); + if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) { SSL_DEBUG_RET( 1, "ssl_handshake", ret ); return( ret ); @@ -4276,13 +4281,16 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) if( ssl->in_offt == NULL ) { - if( ( ret = ssl_read_record( ssl ) ) != 0 ) + if( ! record_read ) { - if( ret == POLARSSL_ERR_SSL_CONN_EOF ) - return( 0 ); + if( ( ret = ssl_read_record( ssl ) ) != 0 ) + { + if( ret == POLARSSL_ERR_SSL_CONN_EOF ) + return( 0 ); - SSL_DEBUG_RET( 1, "ssl_read_record", ret ); - return( ret ); + SSL_DEBUG_RET( 1, "ssl_read_record", ret ); + return( ret ); + } } if( ssl->in_msglen == 0 && @@ -4352,15 +4360,22 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) } else { - if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) + ret = ssl_start_renegotiation( ssl ); + if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) + { + record_read = 1; + } + else if( ret != 0 ) { SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); return( ret ); } } - /* Tell the user to call ssl_read() again */ - return( POLARSSL_ERR_NET_WANT_READ ); + /* If a non-handshake record was read during renego, fallthrough, + * else tell the user they should call ssl_read() again */ + if( ! record_read ) + return( POLARSSL_ERR_NET_WANT_READ ); } else if( ssl->renegotiation == SSL_RENEGOTIATION_PENDING ) { diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index b6924a750..63258cc60 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -627,7 +627,7 @@ run_test "Renegotiation #4 (client-initiated, server-rejected)" \ -c "=> renegotiate" \ -S "=> renegotiate" \ -S "write hello request" \ - -c "SSL - An unexpected message was received from our peer" \ + -c "SSL - Unexpected message at ServerHello in renegotiation" \ -c "failed" run_test "Renegotiation #5 (server-initiated, client-rejected, default)" \