From 59b81d73b4aae1a2f4414cf2a3457a788fb138df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Sat, 30 Nov 2013 17:46:04 +0100 Subject: [PATCH] Refactor ciphersuite selection for version > 2 --- library/ssl_srv.c | 101 +++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 530c86653..ffd73e2fc 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -974,6 +974,59 @@ static int ssl_pick_cert( ssl_context *ssl, } #endif /* POLARSSL_X509_CRT_PARSE_C */ +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id, + const ssl_ciphersuite_t **ciphersuite_info ) +{ + const ssl_ciphersuite_t *suite_info; + + suite_info = ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", suite_id ) ); + return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); + } + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + return( 0 ); + +#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) + if( ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + return( 0 ); +#endif + +#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( ssl_ciphersuite_uses_psk( suite_info ) && + ssl->f_psk == NULL && + ( ssl->psk == NULL || ssl->psk_identity == NULL || + ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) + return( 0 ); +#endif + +#if defined(POLARSSL_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + return( 0 ); +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + static int ssl_parse_client_hello( ssl_context *ssl ) { int ret; @@ -1372,6 +1425,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) * and certificate from the SNI callback triggered by the SNI extension.) */ ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; + ciphersuite_info = NULL; for( i = 0; ciphersuites[i] != 0; i++ ) { for( j = 0, p = buf + 41 + sess_len; j < ciph_len; @@ -1380,49 +1434,12 @@ static int ssl_parse_client_hello( ssl_context *ssl ) if( p[0] == ( ( ciphersuites[i] >> 8 ) & 0xFF ) && p[1] == ( ( ciphersuites[i] ) & 0xFF ) ) { - ciphersuite_info = ssl_ciphersuite_from_id( ciphersuites[i] ); + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); - if( ciphersuite_info == NULL ) - { - SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", - ciphersuites[i] ) ); - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ciphersuite_info->min_minor_ver > ssl->minor_ver || - ciphersuite_info->max_minor_ver < ssl->minor_ver ) - continue; - -#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) - if( ssl_ciphersuite_uses_ec( ciphersuite_info ) && - ( ssl->handshake->curves == NULL || - ssl->handshake->curves[0] == NULL ) ) - continue; -#endif - -#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED) - /* If the ciphersuite requires a pre-shared key and we don't - * have one, skip it now rather than failing later */ - if( ssl_ciphersuite_uses_psk( ciphersuite_info ) && - ssl->f_psk == NULL && - ( ssl->psk == NULL || ssl->psk_identity == NULL || - ssl->psk_identity_len == 0 || ssl->psk_len == 0 ) ) - continue; -#endif - -#if defined(POLARSSL_X509_CRT_PARSE_C) - /* - * Final check: if ciphersuite requires us to have a - * certificate/key of a particular type: - * - select the appropriate certificate if we have one, or - * - try the next ciphersuite if we don't - * This must be done last since we modify the key_cert list. - */ - if( ssl_pick_cert( ssl, ciphersuite_info ) != 0 ) - continue; -#endif - - goto have_ciphersuite; + if( ciphersuite_info != NULL ) + goto have_ciphersuite; } } }