From 1aa586e41d8b097ebe7c6a546de2e2cae9d7be44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 3 Sep 2014 12:54:04 +0200 Subject: [PATCH] Check handshake message_seq field --- library/ssl_srv.c | 23 +++++++++++++++++++---- library/ssl_tls.c | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index dce8b748f..69d3d3edb 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1293,12 +1293,27 @@ static int ssl_parse_client_hello( ssl_context *ssl ) */ if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) { - ssl->handshake->out_msg_seq = ( ssl->in_msg[4] << 8 ) | - ssl->in_msg[5]; + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; } + else + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; - // TODO: DTLS: check message_seq on non-initial handshakes? - // (or already done in ssl_read_record?) + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%d (expected %d)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + ssl->handshake->in_msg_seq++; + } /* * For now we don't support fragmentation, so make sure diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5dd690b3e..263e64ec9 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2246,8 +2246,8 @@ static int ssl_reassemble_dtls_handshake( ssl_context *ssl ) } else { - /* Make sure msg_type, length, message_seq are consistent */ - if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 6 ) != 0 ) + /* Make sure msg_type and length are consistent */ + if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) { SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); return( POLARSSL_ERR_SSL_INVALID_RECORD ); @@ -2357,8 +2357,18 @@ static int ssl_prepare_handshake_record( ssl_context *ssl ) if( ssl->transport == SSL_TRANSPORT_DATAGRAM ) { int ret; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - // TODO: DTLS: check message_seq + /* ssl->handshake is NULL when receiving ClientHello for renego */ + if( ssl->handshake != NULL && + recv_msg_seq != ssl->handshake->in_msg_seq ) + { + SSL_DEBUG_MSG( 2, ( "dropping out-of-order message: " + "message_seq = %d, expected = %d", + recv_msg_seq, ssl->handshake->in_msg_seq ) ); + return( POLARSSL_ERR_NET_WANT_READ ); + } + /* Wait until message completion to increment in_msg_seq */ /* Reassemble if current message is fragmented or reassembly is * already in progress */ @@ -2388,6 +2398,15 @@ static int ssl_prepare_handshake_record( ssl_context *ssl ) if( ssl->state != SSL_HANDSHAKE_OVER ) ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + /* Handshake message is complete, increment counter */ +#if defined(POLARSSL_SSL_PROTO_DTLS) + if( ssl->transport == SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + ssl->handshake->in_msg_seq++; + } +#endif + /* * For DTLS, we move data so that is looks like TLS handshake format to * other functions. @@ -4787,10 +4806,12 @@ static int ssl_start_renegotiation( ssl_context *ssl ) * the ServerHello will have message_seq = 1" */ #if defined(POLARSSL_SSL_PROTO_DTLS) if( ssl->transport == SSL_TRANSPORT_DATAGRAM && - ssl->endpoint == SSL_IS_SERVER && ssl->renegotiation == SSL_RENEGOTIATION_PENDING ) { - ssl->handshake->out_msg_seq = 1; + if( ssl->endpoint == SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; } #endif @@ -4967,6 +4988,14 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len ) } else { +#if defined(POLARSSL_SSL_PROTO_DTLS) + /* DTLS clients need to know renego is server-initiated */ + if( ssl->transport == SSL_TRANSPORT_DATAGRAM && + ssl->endpoint == SSL_IS_CLIENT ) + { + ssl->renegotiation = SSL_RENEGOTIATION_PENDING; + } +#endif ret = ssl_start_renegotiation( ssl ); if( ret == POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ) {