From a62729888b9d8eafbfa952fca63a04100ed90f69 Mon Sep 17 00:00:00 2001 From: Paul Bakker Date: Fri, 12 Apr 2013 13:13:43 +0200 Subject: [PATCH] Ability to specify allowed ciphersuites based on the protocol version. The ciphersuites parameter in the ssl_session structure changed from 'int *' to 'int **' and is now malloced in ssl_init() and freed in ssl_free(). The new function ssl_set_ciphersuite_for_version() sets specific entries inside this array. ssl_set_ciphersuite() sets all entries to the same value. --- ChangeLog | 3 +++ include/polarssl/ssl.h | 20 +++++++++++++++++++- library/ssl_cli.c | 12 ++++++------ library/ssl_srv.c | 12 ++++++------ library/ssl_tls.c | 22 ++++++++++++++++++++-- 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 18be08ab7..e007de42e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ PolarSSL ChangeLog = Branch 1.2 +Features + * Ability to specify allowed ciphersuites based on the protocol version. + Bugfix * Fix for MPI assembly for ARM diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 9746e276b..d5e8e1b45 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -491,7 +491,7 @@ struct _ssl_context int verify_result; /*!< verification result */ int disable_renegotiation; /*!< enable/disable renegotiation */ int allow_legacy_renegotiation; /*!< allow legacy renegotiation */ - const int *ciphersuites; /*!< allowed ciphersuites */ + const int **ciphersuites; /*!< allowed ciphersuites / version */ #if defined(POLARSSL_DHM_C) mpi dhm_P; /*!< prime modulus for DHM */ @@ -718,12 +718,30 @@ void ssl_set_session( ssl_context *ssl, const ssl_session *session ); /** * \brief Set the list of allowed ciphersuites + * (Overrides all version specific lists) * * \param ssl SSL context * \param ciphersuites 0-terminated list of allowed ciphersuites */ void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ); +/** + * \brief Set the list of allowed ciphersuites for a specific + * version of the protocol. + * (Only useful on the server side) + * + * \param ssl SSL context + * \param ciphersuites 0-terminated list of allowed ciphersuites + * \param major Major version number (only SSL_MAJOR_VERSION_3 + * supported) + * \param minor Minor version number (SSL_MINOR_VERSION_0, + * SSL_MINOR_VERSION_1 and SSL_MINOR_VERSION_2, + * SSL_MINOR_VERSION_3 supported) + */ +void ssl_set_ciphersuites_for_version( ssl_context *ssl, + const int *ciphersuites, + int major, int minor ); + /** * \brief Set the data required to verify peer certificate * diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 545906a2a..7019ed07b 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -119,7 +119,7 @@ static int ssl_write_client_hello( ssl_context *ssl ) SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); - for( n = 0; ssl->ciphersuites[n] != 0; n++ ); + for( n = 0; ssl->ciphersuites[ssl->minor_ver][n] != 0; n++ ); if( ssl->renegotiation == SSL_INITIAL_HANDSHAKE ) n++; *p++ = (unsigned char)( n >> 7 ); *p++ = (unsigned char)( n << 1 ); @@ -139,10 +139,10 @@ static int ssl_write_client_hello( ssl_context *ssl ) for( i = 0; i < n; i++ ) { SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %2d", - ssl->ciphersuites[i] ) ); + ssl->ciphersuites[ssl->minor_ver][i] ) ); - *p++ = (unsigned char)( ssl->ciphersuites[i] >> 8 ); - *p++ = (unsigned char)( ssl->ciphersuites[i] ); + *p++ = (unsigned char)( ssl->ciphersuites[ssl->minor_ver][i] >> 8 ); + *p++ = (unsigned char)( ssl->ciphersuites[ssl->minor_ver][i] ); } #if defined(POLARSSL_ZLIB_SUPPORT) @@ -515,13 +515,13 @@ static int ssl_parse_server_hello( ssl_context *ssl ) i = 0; while( 1 ) { - if( ssl->ciphersuites[i] == 0 ) + if( ssl->ciphersuites[ssl->minor_ver][i] == 0 ) { SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); return( POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO ); } - if( ssl->ciphersuites[i++] == ssl->session_negotiate->ciphersuite ) + if( ssl->ciphersuites[ssl->minor_ver][i++] == ssl->session_negotiate->ciphersuite ) break; } diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 325440d9d..1678e3146 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -359,13 +359,13 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) } } - for( i = 0; ssl->ciphersuites[i] != 0; i++ ) + for( i = 0; ssl->ciphersuites[ssl->minor_ver][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] ) + p[2] == ssl->ciphersuites[ssl->minor_ver][i] ) goto have_ciphersuite_v2; } } @@ -375,7 +375,7 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); have_ciphersuite_v2: - ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; + ssl->session_negotiate->ciphersuite = ssl->ciphersuites[ssl->minor_ver][i]; ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite ); /* @@ -642,12 +642,12 @@ static int ssl_parse_client_hello( ssl_context *ssl ) /* * Search for a matching ciphersuite */ - for( i = 0; ssl->ciphersuites[i] != 0; i++ ) + for( i = 0; ssl->ciphersuites[ssl->minor_ver][i] != 0; i++ ) { for( j = 0, p = buf + 41 + sess_len; j < ciph_len; j += 2, p += 2 ) { - if( p[0] == 0 && p[1] == ssl->ciphersuites[i] ) + if( p[0] == 0 && p[1] == ssl->ciphersuites[ssl->minor_ver][i] ) goto have_ciphersuite; } } @@ -657,7 +657,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); have_ciphersuite: - ssl->session_negotiate->ciphersuite = ssl->ciphersuites[i]; + ssl->session_negotiate->ciphersuite = ssl->ciphersuites[ssl->minor_ver][i]; ssl_optimize_checksum( ssl, ssl->session_negotiate->ciphersuite ); ext = buf + 44 + sess_len + ciph_len + comp_len; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index dde0155cb..9455ae2ec 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2952,7 +2952,8 @@ int ssl_init( ssl_context *ssl ) ssl->min_major_ver = SSL_MAJOR_VERSION_3; ssl->min_minor_ver = SSL_MINOR_VERSION_0; - ssl->ciphersuites = ssl_default_ciphersuites; + ssl->ciphersuites = malloc( sizeof(int *) * 4 ); + ssl_set_ciphersuites( ssl, ssl_default_ciphersuites ); #if defined(POLARSSL_DHM_C) if( ( ret = mpi_read_string( &ssl->dhm_P, 16, @@ -3133,7 +3134,22 @@ void ssl_set_session( ssl_context *ssl, const ssl_session *session ) void ssl_set_ciphersuites( ssl_context *ssl, const int *ciphersuites ) { - ssl->ciphersuites = ciphersuites; + ssl->ciphersuites[SSL_MINOR_VERSION_0] = ciphersuites; + ssl->ciphersuites[SSL_MINOR_VERSION_1] = ciphersuites; + ssl->ciphersuites[SSL_MINOR_VERSION_2] = ciphersuites; + ssl->ciphersuites[SSL_MINOR_VERSION_3] = ciphersuites; +} + +void ssl_set_ciphersuites_for_version( ssl_context *ssl, const int *ciphersuites, + int major, int minor ) +{ + if( major != SSL_MAJOR_VERSION_3 ) + return; + + if( minor < SSL_MINOR_VERSION_0 || minor > SSL_MINOR_VERSION_3 ) + return; + + ssl->ciphersuites[minor] = ciphersuites; } void ssl_set_ca_chain( ssl_context *ssl, x509_cert *ca_chain, @@ -3897,6 +3913,8 @@ void ssl_free( ssl_context *ssl ) { SSL_DEBUG_MSG( 2, ( "=> free" ) ); + free( ssl->ciphersuites ); + if( ssl->out_ctr != NULL ) { memset( ssl->out_ctr, 0, SSL_BUFFER_LEN );