Simplify retaining of messages for future processing

There are situations in which it is not clear what message to expect
next. For example, the message following the ServerHello might be
either a Certificate, a ServerKeyExchange or a CertificateRequest. We
deal with this situation in the following way: Initially, the message
processing function for one of the allowed message types is called,
which fetches and decodes a new message. If that message is not the
expected one, the function returns successfully (instead of throwing
an error as usual for unexpected messages), and the handshake
continues to the processing function for the next possible message. To
not have this function fetch a new message, a flag in the SSL context
structure is used to indicate that the last message was retained for
further processing, and if that's set, the following processing
function will not fetch a new record.

This commit simplifies the usage of this message-retaining parameter
by doing the check within the record-fetching routine instead of the
specific message-processing routines. The code gets cleaner this way
and allows retaining messages to be used in other situations as well
without much effort. This will be used in the next commits.
This commit is contained in:
Hanno Becker 2017-06-08 15:41:02 +01:00
parent 674df30480
commit 10699cc96c
3 changed files with 40 additions and 36 deletions

View file

@ -846,7 +846,9 @@ struct _ssl_context
size_t in_hslen; /*!< current handshake message length */
int nb_zero; /*!< # of 0-length encrypted messages */
int record_read; /*!< record is already present */
int keep_current_message; /*!< drop or reuse current message
on next call to record layer? */
/*
* Record layer (outgoing data)

View file

@ -1943,7 +1943,9 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_PSK ||
ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_RSA_PSK )
{
ssl->record_read = 1;
/* Current message is probably either
* CertificateRequest or ServerHelloDone */
ssl->keep_current_message = 1;
goto exit;
}
@ -2260,36 +2262,31 @@ static int ssl_parse_certificate_request( ssl_context *ssl )
* n+4 .. ... Distinguished Name #1
* ... .. ... length of DN 2, etc.
*/
if( ssl->record_read == 0 )
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
ssl->record_read = 1;
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
ssl->client_auth = 0;
ssl->state++;
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) );
return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
if( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST )
ssl->client_auth++;
ssl->state++;
ssl->client_auth = ( ssl->in_msg[0] == SSL_HS_CERTIFICATE_REQUEST );
SSL_DEBUG_MSG( 3, ( "got %s certificate request",
ssl->client_auth ? "a" : "no" ) );
if( ssl->client_auth == 0 )
{
/* Current message is probably the ServerHelloDone */
ssl->keep_current_message = 1;
goto exit;
ssl->record_read = 0;
}
// TODO: handshake_failure alert for an anonymous server to request
// client authentication
@ -2386,21 +2383,17 @@ static int ssl_parse_server_hello_done( ssl_context *ssl )
SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
if( ssl->record_read == 0 )
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
if( ( ret = ssl_read_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
SSL_DEBUG_RET( 1, "ssl_read_record", ret );
return( ret );
}
if( ssl->in_msgtype != SSL_MSG_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) );
return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
}
ssl->record_read = 0;
if( ssl->in_hslen != 4 ||
ssl->in_msg[0] != SSL_HS_SERVER_HELLO_DONE )

View file

@ -2169,6 +2169,15 @@ int ssl_read_record( ssl_context *ssl )
SSL_DEBUG_MSG( 2, ( "=> read record" ) );
if( ssl->keep_current_message == 1 )
{
SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
SSL_DEBUG_MSG( 2, ( "<= read record" ) );
ssl->keep_current_message = 0;
return( 0 );
}
if( ssl->in_hslen != 0 &&
ssl->in_hslen < ssl->in_msglen )
{
@ -3750,7 +3759,7 @@ int ssl_session_reset( ssl_context *ssl )
ssl->in_hslen = 0;
ssl->nb_zero = 0;
ssl->record_read = 0;
ssl->keep_current_message = 0;
ssl->out_msg = ssl->out_ctr + 13;
ssl->out_msgtype = 0;