1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-28 00:21:48 +03:00

Re-added support for parsing and handling SSLv2 Client Hello messages

If the define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is enabled,
the SSL Server module can handle the old SSLv2 Client Hello messages.

It has been updated to deny SSLv2 Client Hello messages during
renegotiation.
This commit is contained in:
Paul Bakker
2013-03-06 17:01:52 +01:00
parent 37286a573b
commit 78a8c71993
3 changed files with 227 additions and 0 deletions

View File

@ -191,6 +191,216 @@ static int ssl_parse_signature_algorithms_ext( ssl_context *ssl,
return( 0 );
}
#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
static int ssl_parse_client_hello_v2( ssl_context *ssl )
{
int ret;
unsigned int i, j;
size_t n;
unsigned int ciph_len, sess_len, chal_len;
unsigned char *buf, *p;
SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) );
if( ssl->renegotiation != SSL_INITIAL_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) );
if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
return( ret );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
buf = ssl->in_hdr;
SSL_DEBUG_BUF( 4, "record header", buf, 5 );
SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d",
buf[2] ) );
SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d",
( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) );
SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]",
buf[3], buf[4] ) );
/*
* SSLv2 Client Hello
*
* Record layer:
* 0 . 1 message length
*
* SSL layer:
* 2 . 2 message type
* 3 . 4 protocol version
*/
if( buf[2] != SSL_HS_CLIENT_HELLO ||
buf[3] != SSL_MAJOR_VERSION_3 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF;
if( n < 17 || n > 512 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->major_ver = SSL_MAJOR_VERSION_3;
ssl->minor_ver = ( buf[4] <= SSL_MINOR_VERSION_3 )
? buf[4] : SSL_MINOR_VERSION_3;
if( ssl->minor_ver < ssl->min_minor_ver )
{
SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum"
" [%d:%d] < [%d:%d]", ssl->major_ver, ssl->minor_ver,
ssl->min_major_ver, ssl->min_minor_ver ) );
ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
SSL_ALERT_MSG_PROTOCOL_VERSION );
return( POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION );
}
ssl->max_major_ver = buf[3];
ssl->max_minor_ver = buf[4];
if( ( ret = ssl_fetch_input( ssl, 2 + n ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_fetch_input", ret );
return( ret );
}
ssl->handshake->update_checksum( ssl, buf + 2, n );
buf = ssl->in_msg;
n = ssl->in_left - 5;
/*
* 0 . 1 ciphersuitelist length
* 2 . 3 session id length
* 4 . 5 challenge length
* 6 . .. ciphersuitelist
* .. . .. session id
* .. . .. challenge
*/
SSL_DEBUG_BUF( 4, "record contents", buf, n );
ciph_len = ( buf[0] << 8 ) | buf[1];
sess_len = ( buf[2] << 8 ) | buf[3];
chal_len = ( buf[4] << 8 ) | buf[5];
SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d",
ciph_len, sess_len, chal_len ) );
/*
* Make sure each parameter length is valid
*/
if( ciph_len < 3 || ( ciph_len % 3 ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( sess_len > 32 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( chal_len < 8 || chal_len > 32 )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
if( n != 6 + ciph_len + sess_len + chal_len )
{
SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist",
buf + 6, ciph_len );
SSL_DEBUG_BUF( 3, "client hello, session id",
buf + 6 + ciph_len, sess_len );
SSL_DEBUG_BUF( 3, "client hello, challenge",
buf + 6 + ciph_len + sess_len, chal_len );
p = buf + 6 + ciph_len;
ssl->session_negotiate->length = sess_len;
memset( ssl->session_negotiate->id, 0, sizeof( ssl->session_negotiate->id ) );
memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->length );
p += sess_len;
memset( ssl->handshake->randbytes, 0, 64 );
memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len );
/*
* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV
*/
for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 )
{
if( p[0] == 0 && p[1] == 0 && p[2] == SSL_EMPTY_RENEGOTIATION_INFO )
{
SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) );
if( ssl->renegotiation == SSL_RENEGOTIATION )
{
SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV during renegotiation" ) );
if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
return( ret );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->secure_renegotiation = SSL_SECURE_RENEGOTIATION;
break;
}
}
for( i = 0; ssl->ciphersuites[i] != 0; i++ )
{
for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 )
{
if( p[0] == 0 &&
p[1] == 0 &&
p[2] == ssl->ciphersuites[i] )
goto have_ciphersuite_v2;
}
}
SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) );
return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN );
have_ciphersuite_v2:
ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i];
ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite );
/*
* SSLv2 Client Hello relevant renegotiation security checks
*/
if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
{
SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
return( ret );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
ssl->in_left = 0;
ssl->state++;
SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) );
return( 0 );
}
#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
static int ssl_parse_client_hello( ssl_context *ssl )
{
int ret;
@ -214,6 +424,11 @@ static int ssl_parse_client_hello( ssl_context *ssl )
buf = ssl->in_hdr;
#if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
if( ( buf[0] & 0x80 ) != 0 )
return ssl_parse_client_hello_v2( ssl );
#endif
SSL_DEBUG_BUF( 4, "record header", buf, 5 );
SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d",