mirror of
				https://github.com/cuberite/polarssl.git
				synced 2025-11-03 20:22:59 -05:00 
			
		
		
		
	- Sending of handshake_failures during renegotiation added
- Handle two legacy modes differently: SSL_LEGACY_BREAK_HANDSHAKE and SSL_LEGACY_NO_RENEGOTIATION
This commit is contained in:
		
							parent
							
								
									17a9790918
								
							
						
					
					
						commit
						d0f6fa7bdc
					
				@ -122,8 +122,9 @@
 | 
			
		||||
#define SSL_RENEGOTIATION_ENABLED       0
 | 
			
		||||
#define SSL_RENEGOTIATION_DISABLED      1
 | 
			
		||||
 | 
			
		||||
#define SSL_NO_LEGACY_RENEGOTIATION     0
 | 
			
		||||
#define SSL_ALLOW_LEGACY_RENEGOTIATION  1
 | 
			
		||||
#define SSL_LEGACY_NO_RENEGOTIATION     0
 | 
			
		||||
#define SSL_LEGACY_ALLOW_RENEGOTIATION  1
 | 
			
		||||
#define SSL_LEGACY_BREAK_HANDSHAKE      2
 | 
			
		||||
 | 
			
		||||
#define SSL_MAX_CONTENT_LEN         16384
 | 
			
		||||
 | 
			
		||||
@ -758,10 +759,25 @@ void ssl_set_renegotiation( ssl_context *ssl, int renegotiation );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief          Prevent or allow legacy renegotiation.
 | 
			
		||||
 *                 (Default: SSL_NO_LEGACY_RENEGOTIATION)
 | 
			
		||||
 *                 Allowing legacy renegotiation makes the connection
 | 
			
		||||
 *                 vulnerable to specific man in the middle attacks.
 | 
			
		||||
 *                 (See RFC 5746)
 | 
			
		||||
 *                 (Default: SSL_LEGACY_NO_RENEGOTIATION)
 | 
			
		||||
 *                 
 | 
			
		||||
 *                 SSL_LEGACY_NO_RENEGOTIATION allows connections to
 | 
			
		||||
 *                 be established even if the peer does not support
 | 
			
		||||
 *                 secure renegotiation, but does not allow renegotiation
 | 
			
		||||
 *                 to take place if not secure.
 | 
			
		||||
 *                 (Interoperable and secure option)
 | 
			
		||||
 *
 | 
			
		||||
 *                 SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations
 | 
			
		||||
 *                 with non-upgraded peers. Allowing legacy renegotiation
 | 
			
		||||
 *                 makes the connection vulnerable to specific man in the
 | 
			
		||||
 *                 middle attacks. (See RFC 5746)
 | 
			
		||||
 *                 (Most interoperable and least secure option)
 | 
			
		||||
 *
 | 
			
		||||
 *                 SSL_LEGACY_BREAK_HANDSHAKE breaks off connections
 | 
			
		||||
 *                 if peer does not support secure renegotiation. Results
 | 
			
		||||
 *                 in interoperability issues with non-upgraded peers
 | 
			
		||||
 *                 that do not support renegotiation altogether.
 | 
			
		||||
 *                 (Most secure option, interoperability issues)
 | 
			
		||||
 *
 | 
			
		||||
 * \param ssl      SSL context
 | 
			
		||||
 * \param allow_legacy  Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION or
 | 
			
		||||
@ -914,6 +930,8 @@ int ssl_handshake_client( ssl_context *ssl );
 | 
			
		||||
int ssl_handshake_server( ssl_context *ssl );
 | 
			
		||||
void ssl_handshake_wrapup( ssl_context *ssl );
 | 
			
		||||
 | 
			
		||||
int ssl_send_fatal_handshake_failure( ssl_context *ssl );
 | 
			
		||||
 | 
			
		||||
int ssl_derive_keys( ssl_context *ssl );
 | 
			
		||||
 | 
			
		||||
int ssl_read_record( ssl_context *ssl );
 | 
			
		||||
 | 
			
		||||
@ -328,12 +328,17 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
 | 
			
		||||
                                         unsigned char *buf,
 | 
			
		||||
                                         size_t len )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
 | 
			
		||||
    {
 | 
			
		||||
        if( len != 1 || buf[0] != 0x0 )
 | 
			
		||||
        {
 | 
			
		||||
            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
 | 
			
		||||
            /* TODO: Send handshake failure alert */
 | 
			
		||||
 | 
			
		||||
            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
                return( ret );
 | 
			
		||||
 | 
			
		||||
            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -348,7 +353,10 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
 | 
			
		||||
                    ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
 | 
			
		||||
            /* TODO: Send handshake failure alert */
 | 
			
		||||
 | 
			
		||||
            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
                return( ret );
 | 
			
		||||
 | 
			
		||||
            return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -366,6 +374,7 @@ static int ssl_parse_server_hello( ssl_context *ssl )
 | 
			
		||||
    size_t ext_len = 0;
 | 
			
		||||
    unsigned char *buf, *ext;
 | 
			
		||||
    int renegotiation_info_seen = 0;
 | 
			
		||||
    int handshake_failure = 0;
 | 
			
		||||
 | 
			
		||||
    SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) );
 | 
			
		||||
 | 
			
		||||
@ -563,18 +572,39 @@ static int ssl_parse_server_hello( ssl_context *ssl )
 | 
			
		||||
    /*
 | 
			
		||||
     * Renegotiation security checks
 | 
			
		||||
     */
 | 
			
		||||
    if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
        ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
 | 
			
		||||
        renegotiation_info_seen == 0 )
 | 
			
		||||
    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing" ) );
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    if( !ssl->allow_legacy_renegotiation &&
 | 
			
		||||
        ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION )
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
 | 
			
		||||
             renegotiation_info_seen == 0 )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
             ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
             renegotiation_info_seen == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( handshake_failure == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
            return( ret );
 | 
			
		||||
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,12 +42,17 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
 | 
			
		||||
                                         unsigned char *buf,
 | 
			
		||||
                                         size_t len )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE )
 | 
			
		||||
    {
 | 
			
		||||
        if( len != 1 || buf[0] != 0x0 )
 | 
			
		||||
        {
 | 
			
		||||
            SSL_DEBUG_MSG( 1, ( "non-zero length renegotiated connection field" ) );
 | 
			
		||||
            /* TODO: Send handshake failure alert */
 | 
			
		||||
 | 
			
		||||
            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
                return( ret );
 | 
			
		||||
 | 
			
		||||
            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -60,7 +65,10 @@ static int ssl_parse_renegotiation_info( ssl_context *ssl,
 | 
			
		||||
            memcmp( buf + 1, ssl->peer_verify_data, ssl->verify_data_len ) != 0 )
 | 
			
		||||
        {
 | 
			
		||||
            SSL_DEBUG_MSG( 1, ( "non-matching renegotiated connection field" ) );
 | 
			
		||||
            /* TODO: Send handshake failure alert */
 | 
			
		||||
 | 
			
		||||
            if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
                return( ret );
 | 
			
		||||
 | 
			
		||||
            return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -77,7 +85,8 @@ static int ssl_parse_client_hello( ssl_context *ssl )
 | 
			
		||||
    unsigned int comp_len;
 | 
			
		||||
    unsigned int ext_len = 0;
 | 
			
		||||
    unsigned char *buf, *p, *ext;
 | 
			
		||||
    int renegotiation_info_seen;
 | 
			
		||||
    int renegotiation_info_seen = 0;
 | 
			
		||||
    int handshake_failure = 0;
 | 
			
		||||
 | 
			
		||||
    SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
 | 
			
		||||
 | 
			
		||||
@ -277,6 +286,10 @@ static int ssl_parse_client_hello( ssl_context *ssl )
 | 
			
		||||
            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;
 | 
			
		||||
@ -306,7 +319,6 @@ have_ciphersuite:
 | 
			
		||||
    ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite );
 | 
			
		||||
 | 
			
		||||
    ext = buf + 44 + sess_len + ciph_len + comp_len;
 | 
			
		||||
    renegotiation_info_seen = 0;
 | 
			
		||||
 | 
			
		||||
    while( ext_len )
 | 
			
		||||
    {
 | 
			
		||||
@ -349,26 +361,39 @@ have_ciphersuite:
 | 
			
		||||
    /*
 | 
			
		||||
     * Renegotiation security checks
 | 
			
		||||
     */
 | 
			
		||||
    if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
        ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
 | 
			
		||||
        renegotiation_info_seen == 0 )
 | 
			
		||||
    if( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
        ssl->allow_legacy_renegotiation == SSL_LEGACY_BREAK_HANDSHAKE )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_SECURE_RENEGOTIATION &&
 | 
			
		||||
             renegotiation_info_seen == 0 )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) );
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
        ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
        renegotiation_info_seen == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( !ssl->allow_legacy_renegotiation &&
 | 
			
		||||
        ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION )
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
             ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if( ssl->renegotiation == SSL_RENEGOTIATION &&
 | 
			
		||||
             ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
             renegotiation_info_seen == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) );
 | 
			
		||||
        handshake_failure = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( handshake_failure == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
            return( ret );
 | 
			
		||||
 | 
			
		||||
        return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2020,6 +2020,20 @@ int ssl_read_record( ssl_context *ssl )
 | 
			
		||||
    return( 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ssl_send_fatal_handshake_failure( ssl_context *ssl )
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if( ( ret = ssl_send_alert_message( ssl,
 | 
			
		||||
                    SSL_ALERT_LEVEL_FATAL,
 | 
			
		||||
                    SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        return( ret );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return( 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ssl_send_alert_message( ssl_context *ssl,
 | 
			
		||||
                            unsigned char level,
 | 
			
		||||
                            unsigned char message )
 | 
			
		||||
@ -3513,15 +3527,28 @@ int ssl_read( ssl_context *ssl, unsigned char *buf, size_t len )
 | 
			
		||||
                return( POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED )
 | 
			
		||||
            if( ssl->disable_renegotiation == SSL_RENEGOTIATION_DISABLED ||
 | 
			
		||||
                ( ssl->secure_renegotiation == SSL_LEGACY_RENEGOTIATION &&
 | 
			
		||||
                  ssl->allow_legacy_renegotiation == SSL_LEGACY_NO_RENEGOTIATION ) )
 | 
			
		||||
            {
 | 
			
		||||
                SSL_DEBUG_MSG( 3, ( "ignoring renegotiation, sending alert" ) );
 | 
			
		||||
 | 
			
		||||
                if( ( ret = ssl_send_alert_message( ssl,
 | 
			
		||||
                                SSL_ALERT_LEVEL_WARNING,
 | 
			
		||||
                                SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
 | 
			
		||||
                if( ssl->minor_ver == SSL_MINOR_VERSION_0 )
 | 
			
		||||
                {
 | 
			
		||||
                    return( ret );
 | 
			
		||||
                    /*
 | 
			
		||||
                     * SSLv3 does not have a "no_renegotiation" alert
 | 
			
		||||
                     */
 | 
			
		||||
                    if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
 | 
			
		||||
                        return( ret );
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if( ( ret = ssl_send_alert_message( ssl,
 | 
			
		||||
                                    SSL_ALERT_LEVEL_WARNING,
 | 
			
		||||
                                    SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
 | 
			
		||||
                    {
 | 
			
		||||
                        return( ret );
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@
 | 
			
		||||
#define DFL_KEY_FILE            ""
 | 
			
		||||
#define DFL_FORCE_CIPHER        0
 | 
			
		||||
#define DFL_RENEGOTIATION       SSL_RENEGOTIATION_ENABLED
 | 
			
		||||
#define DFL_ALLOW_LEGACY        SSL_NO_LEGACY_RENEGOTIATION
 | 
			
		||||
#define DFL_ALLOW_LEGACY        SSL_LEGACY_NO_RENEGOTIATION
 | 
			
		||||
 | 
			
		||||
#define GET_REQUEST "GET %s HTTP/1.0\r\n\r\n"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user