From 846ba473af0af5cc4aafdc23ed1862a9d1df4da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Jan 2015 13:54:38 +0100 Subject: [PATCH 1/8] Minor refactoring --- library/ssl_srv.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 01b0aca207..a385c8939b 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -809,14 +809,13 @@ static int ssl_pick_cert( ssl_context *ssl, } #if defined(POLARSSL_ECDSA_C) - if( pk_alg == POLARSSL_PK_ECDSA ) - { - if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) ) - break; - } - else + if( pk_alg == POLARSSL_PK_ECDSA && + ! ssl_key_matches_curves( cur->key, ssl->handshake->curves ) ) + continue; #endif - break; + + /* If we get there, we got a winner */ + break; } if( cur == NULL ) From 6458e3b743ec7c15fad483d1b643709627a4bb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Jan 2015 14:16:56 +0100 Subject: [PATCH 2/8] Some more refactoring/tuning. --- library/ssl_srv.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index a385c8939b..211ab5d478 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -749,11 +749,11 @@ static int ssl_parse_alpn_ext( ssl_context *ssl, #if defined(POLARSSL_X509_CRT_PARSE_C) /* - * Return 1 if the given EC key uses the given curve, 0 otherwise + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise */ #if defined(POLARSSL_ECDSA_C) -static int ssl_key_matches_curves( pk_context *pk, - const ecp_curve_info **curves ) +static int ssl_check_key_curve( pk_context *pk, + const ecp_curve_info **curves ) { const ecp_curve_info **crv = curves; ecp_group_id grp_id = pk_ec( *pk )->grp.id; @@ -761,11 +761,11 @@ static int ssl_key_matches_curves( pk_context *pk, while( *crv != NULL ) { if( (*crv)->grp_id == grp_id ) - return( 1 ); + return( 0 ); crv++; } - return( 0 ); + return( -1 ); } #endif /* POLARSSL_ECDSA_C */ @@ -810,7 +810,7 @@ static int ssl_pick_cert( ssl_context *ssl, #if defined(POLARSSL_ECDSA_C) if( pk_alg == POLARSSL_PK_ECDSA && - ! ssl_key_matches_curves( cur->key, ssl->handshake->curves ) ) + ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) continue; #endif @@ -838,8 +838,8 @@ static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id, 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 ); + SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); } if( suite_info->min_minor_ver > ssl->minor_ver || From df331a55d2d71a9e1aed123beaf374943f97bcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Jan 2015 16:43:07 +0100 Subject: [PATCH 3/8] Prefer SHA-1 certificates for pre-1.2 clients --- ChangeLog | 6 ++++++ library/ssl_srv.c | 31 ++++++++++++++++++++++----- tests/ssl-opt.sh | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index fd83b9e608..b38d56f271 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ PolarSSL ChangeLog (Sorted per branch, date) += PolarSSL 1.3.10 released ??? + +Features + * Certificate selection based on signature hash, prefering SHA-1 over SHA-2 + for pre-1.2 clients when multiple certificates are available. + = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 211ab5d478..04608ee98e 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -776,7 +776,7 @@ static int ssl_check_key_curve( pk_context *pk, static int ssl_pick_cert( ssl_context *ssl, const ssl_ciphersuite_t * ciphersuite_info ) { - ssl_key_cert *cur, *list; + ssl_key_cert *cur, *list, *fallback = NULL; pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); #if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) @@ -814,15 +814,36 @@ static int ssl_pick_cert( ssl_context *ssl, continue; #endif + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < SSL_MINOR_VERSION_3 && + cur->cert->sig_md != POLARSSL_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + continue; + } + /* If we get there, we got a winner */ break; } - if( cur == NULL ) - return( -1 ); + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + return( 0 ); + } - ssl->handshake->key_cert = cur; - return( 0 ); + if( fallback != NULL ) + { + ssl->handshake->key_cert = fallback; + return( 0 ); + } + + return( -1 ); } #endif /* POLARSSL_X509_CRT_PARSE_C */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index f94808d2cc..2cf4b6e70f 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -956,6 +956,60 @@ run_test "Authentication: client no cert, ssl3" \ -C "! ssl_handshake returned" \ -S "X509 - Certificate verification failed" +# Tests for certificate selection based on SHA verson + +run_test "Certificate hash: client TLS 1.2 -> SHA-2" \ + "$P_SRV crt_file=data_files/server5.crt \ + key_file=data_files/server5.key \ + crt_file2=data_files/server5-sha1.crt \ + key_file2=data_files/server5.key" \ + "$P_CLI force_version=tls1_2" \ + 0 \ + -c "signed using.*ECDSA with SHA256" \ + -C "signed using.*ECDSA with SHA1" + +run_test "Certificate hash: client TLS 1.1 -> SHA-1" \ + "$P_SRV crt_file=data_files/server5.crt \ + key_file=data_files/server5.key \ + crt_file2=data_files/server5-sha1.crt \ + key_file2=data_files/server5.key" \ + "$P_CLI force_version=tls1_1" \ + 0 \ + -C "signed using.*ECDSA with SHA256" \ + -c "signed using.*ECDSA with SHA1" + +run_test "Certificate hash: client TLS 1.0 -> SHA-1" \ + "$P_SRV crt_file=data_files/server5.crt \ + key_file=data_files/server5.key \ + crt_file2=data_files/server5-sha1.crt \ + key_file2=data_files/server5.key" \ + "$P_CLI force_version=tls1" \ + 0 \ + -C "signed using.*ECDSA with SHA256" \ + -c "signed using.*ECDSA with SHA1" + +run_test "Certificate hash: client TLS 1.1, no SHA-1 -> SHA-2 (order 1)" \ + "$P_SRV crt_file=data_files/server5.crt \ + key_file=data_files/server5.key \ + crt_file2=data_files/server6.crt \ + key_file2=data_files/server6.key" \ + "$P_CLI force_version=tls1_1" \ + 0 \ + -c "serial number.*09" \ + -c "signed using.*ECDSA with SHA256" \ + -C "signed using.*ECDSA with SHA1" + +run_test "Certificate hash: client TLS 1.1, no SHA-1 -> SHA-2 (order 2)" \ + "$P_SRV crt_file=data_files/server6.crt \ + key_file=data_files/server6.key \ + crt_file2=data_files/server5.crt \ + key_file2=data_files/server5.key" \ + "$P_CLI force_version=tls1_1" \ + 0 \ + -c "serial number.*0A" \ + -c "signed using.*ECDSA with SHA256" \ + -C "signed using.*ECDSA with SHA1" + # tests for SNI run_test "SNI: no SNI callback" \ From f01768c55e60d8fa7366e8e7c6f5c71f327b1e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Jan 2015 17:06:16 +0100 Subject: [PATCH 4/8] Specific error for suites in common but none good --- ChangeLog | 5 +++++ include/polarssl/error.h | 2 +- include/polarssl/ssl.h | 1 + library/error.c | 2 ++ library/ssl_srv.c | 43 ++++++++++++++++++++++++++++++---------- tests/ssl-opt.sh | 14 ++++++------- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index b38d56f271..efaadfb42f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,11 @@ Features * Certificate selection based on signature hash, prefering SHA-1 over SHA-2 for pre-1.2 clients when multiple certificates are available. +Changes + * A specific error is now returned when there are ciphersuites in common + but none of them is usable due to external factors such as no certificate + with a suitable (extended)KeyUsage or curvem or no PSK set. + = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in diff --git a/include/polarssl/error.h b/include/polarssl/error.h index 7ce2828b27..6a1143f46c 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -91,7 +91,7 @@ * ECP 4 8 (Started from top) * MD 5 4 * CIPHER 6 6 - * SSL 6 10 (Started from top) + * SSL 6 11 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 194e944718..1e9fb39c74 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -146,6 +146,7 @@ #define POLARSSL_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ #define POLARSSL_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ #define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6A80 /**< None of the common ciphersuites is usable (eg, no suitable certificate) */ /* * Various constants diff --git a/library/error.c b/library/error.c index 73504d450d..00956360b1 100644 --- a/library/error.c +++ b/library/error.c @@ -452,6 +452,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); if( use_ret == -(POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate)" ); #endif /* POLARSSL_SSL_TLS_C */ #if defined(POLARSSL_X509_USE_C) || defined(POLARSSL_X509_CREATE_C) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 04608ee98e..384207a390 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -903,7 +903,7 @@ static int ssl_ciphersuite_match( ssl_context *ssl, int suite_id, #if defined(POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) static int ssl_parse_client_hello_v2( ssl_context *ssl ) { - int ret; + int ret, got_common_suite; unsigned int i, j; size_t n; unsigned int ciph_len, sess_len, chal_len; @@ -1072,6 +1072,7 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) } } + got_common_suite = 0; ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; ciphersuite_info = NULL; #if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) @@ -1089,6 +1090,8 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) continue; + got_common_suite = 1; + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], &ciphersuite_info ) ) != 0 ) return( ret ); @@ -1098,9 +1101,17 @@ static int ssl_parse_client_hello_v2( ssl_context *ssl ) } } - SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - - return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + if( got_common_suite ) + { + SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } have_ciphersuite_v2: ssl->session_negotiate->ciphersuite = ciphersuites[i]; @@ -1132,7 +1143,7 @@ have_ciphersuite_v2: static int ssl_parse_client_hello( ssl_context *ssl ) { - int ret; + int ret, got_common_suite; unsigned int i, j; size_t n; unsigned int ciph_len, sess_len; @@ -1552,6 +1563,7 @@ static int ssl_parse_client_hello( ssl_context *ssl ) * (At the end because we need information from the EC-based extensions * and certificate from the SNI callback triggered by the SNI extension.) */ + got_common_suite = 0; ciphersuites = ssl->ciphersuite_list[ssl->minor_ver]; ciphersuite_info = NULL; #if defined(POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) @@ -1568,6 +1580,8 @@ static int ssl_parse_client_hello( ssl_context *ssl ) p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) continue; + got_common_suite = 1; + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], &ciphersuite_info ) ) != 0 ) return( ret ); @@ -1577,12 +1591,19 @@ static int ssl_parse_client_hello( ssl_context *ssl ) } } - SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - - if( ( ret = ssl_send_fatal_handshake_failure( ssl ) ) != 0 ) - return( ret ); - - return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + if( got_common_suite ) + { + SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + ssl_send_fatal_handshake_failure( ssl ); + return( POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE ); + } + else + { + SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + ssl_send_fatal_handshake_failure( ssl ); + return( POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN ); + } have_ciphersuite: ssl->session_negotiate->ciphersuite = ciphersuites[i]; diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 2cf4b6e70f..a37ea93832 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1562,7 +1562,7 @@ run_test "PSK callback: psk, no callback" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123" \ 0 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1571,7 +1571,7 @@ run_test "PSK callback: no psk, no callback" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123" \ 1 \ - -s "SSL - The server has no ciphersuites in common" \ + -s "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1580,7 +1580,7 @@ run_test "PSK callback: callback overrides other settings" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123" \ 1 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -s "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1589,7 +1589,7 @@ run_test "PSK callback: first id matches" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=abc psk=dead" \ 0 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1598,7 +1598,7 @@ run_test "PSK callback: second id matches" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1607,7 +1607,7 @@ run_test "PSK callback: no match" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=ghi psk=beef" \ 1 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -s "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -1616,7 +1616,7 @@ run_test "PSK callback: wrong key" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=abc psk=beef" \ 1 \ - -S "SSL - The server has no ciphersuites in common" \ + -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -s "SSL - Verification of the message MAC failed" From 6f303ce19e667355c0d8af1081d61d796391b1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 8 Jan 2015 17:07:18 +0100 Subject: [PATCH 5/8] Fix portability issue in script If there was a reason for hardcoding the path, it should have been documented. --- scripts/generate_errors.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 0ee992d457..b9a8e9c0f4 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -46,7 +46,7 @@ close(FORMAT_FILE); $/ = $line_separator; -open(GREP, "/bin/grep \"define POLARSSL_ERR_\" $include_dir/* |") || die("Failure when calling grep: $!"); +open(GREP, "grep \"define POLARSSL_ERR_\" $include_dir/* |") || die("Failure when calling grep: $!"); my $ll_old_define = ""; my $hl_old_define = ""; From e117a8fc0dcdd9c2528856876748cfa8b06e4fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 9 Jan 2015 12:39:35 +0100 Subject: [PATCH 6/8] Make truncated hmac a runtime option server-side Reading the documentation of ssl_set_truncated_hmac() may give the impression I changed the default for clients but I didn't, the old documentation was wrong. --- ChangeLog | 4 ++++ include/polarssl/ssl.h | 8 ++++---- library/ssl_srv.c | 3 ++- library/ssl_tls.c | 8 +++++--- programs/ssl/ssl_server2.c | 25 +++++++++++++++++++++++++ tests/ssl-opt.sh | 37 ++++++++++++++++++++++++++++++++----- 6 files changed, 72 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89c87e0575..56436887ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,10 @@ Features * Add support for Extended Master Secret (draft-ietf-tls-session-hash) * Add support for Encrypt-then-MAC (RFC 7366) +Changes + * It is now possible to disable neogtiation of truncated HMAC server-side + at runtime with ssl_set_truncated_hmac(). + = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 82ed04e117..5849a62123 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -1487,15 +1487,15 @@ int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ); #if defined(POLARSSL_SSL_TRUNCATED_HMAC) /** - * \brief Activate negotiation of truncated HMAC (Client only) - * (Default: SSL_TRUNC_HMAC_ENABLED) + * \brief Activate negotiation of truncated HMAC + * (Default: SSL_TRUNC_HMAC_DISABLED on client, + * SSL_TRUNC_HMAC_ENABLED on server.) * * \param ssl SSL context * \param truncate Enable or disable (SSL_TRUNC_HMAC_ENABLED or * SSL_TRUNC_HMAC_DISABLED) * - * \return O if successful, - * POLARSSL_ERR_SSL_BAD_INPUT_DATA if used server-side + * \return Always 0. */ int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ); #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 6d8626cc27..534525a471 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -629,7 +629,8 @@ static int ssl_parse_truncated_hmac_ext( ssl_context *ssl, ((void) buf); - ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; + if( ssl->trunc_hmac == SSL_TRUNC_HMAC_ENABLED ) + ssl->session_negotiate->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; return( 0 ); } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ea34f66b74..eda3d6da7d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3782,6 +3782,11 @@ void ssl_set_endpoint( ssl_context *ssl, int endpoint ) if( endpoint == SSL_IS_CLIENT ) ssl->session_tickets = SSL_SESSION_TICKETS_ENABLED; #endif + +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + if( endpoint == SSL_IS_SERVER ) + ssl->trunc_hmac = SSL_TRUNC_HMAC_ENABLED; +#endif } void ssl_set_authmode( ssl_context *ssl, int authmode ) @@ -4203,9 +4208,6 @@ int ssl_set_max_frag_len( ssl_context *ssl, unsigned char mfl_code ) #if defined(POLARSSL_SSL_TRUNCATED_HMAC) int ssl_set_truncated_hmac( ssl_context *ssl, int truncate ) { - if( ssl->endpoint != SSL_IS_CLIENT ) - return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); - ssl->trunc_hmac = truncate; return( 0 ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 08f2ff8640..d962d5b9e8 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -109,6 +109,7 @@ int main( int argc, char *argv[] ) #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE +#define DFL_TRUNC_HMAC -1 #define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED #define DFL_TICKET_TIMEOUT -1 #define DFL_CACHE_MAX -1 @@ -171,6 +172,7 @@ struct options int max_version; /* maximum protocol version accepted */ int auth_mode; /* verify mode for connection */ unsigned char mfl_code; /* code for maximum fragment length */ + int trunc_hmac; /* accept truncated hmac? */ int tickets; /* enable / disable session tickets */ int ticket_timeout; /* session ticket lifetime */ int cache_max; /* max number of session cache entries */ @@ -295,6 +297,13 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) #define USAGE_MAX_FRAG_LEN "" #endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */ +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) +#define USAGE_TRUNC_HMAC \ + " trunc_hmac=%%d default: library default\n" +#else +#define USAGE_TRUNC_HMAC "" +#endif + #if defined(POLARSSL_SSL_ALPN) #define USAGE_ALPN \ " alpn=%%s default: \"\" (disabled)\n" \ @@ -341,6 +350,7 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len ) USAGE_TICKETS \ USAGE_CACHE \ USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ USAGE_ALPN \ USAGE_EMS \ USAGE_ETM \ @@ -726,6 +736,7 @@ int main( int argc, char *argv[] ) opt.max_version = DFL_MAX_VERSION; opt.auth_mode = DFL_AUTH_MODE; opt.mfl_code = DFL_MFL_CODE; + opt.trunc_hmac = DFL_TRUNC_HMAC; opt.tickets = DFL_TICKETS; opt.ticket_timeout = DFL_TICKET_TIMEOUT; opt.cache_max = DFL_CACHE_MAX; @@ -902,6 +913,15 @@ int main( int argc, char *argv[] ) { opt.alpn_string = q; } + else if( strcmp( p, "trunc_hmac" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } + } else if( strcmp( p, "extended_ms" ) == 0 ) { switch( atoi( q ) ) @@ -1297,6 +1317,11 @@ int main( int argc, char *argv[] ) }; #endif +#if defined(POLARSSL_SSL_TRUNCATED_HMAC) + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + ssl_set_truncated_hmac( &ssl, opt.trunc_hmac ); +#endif + #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) if( opt.extended_ms != DFL_EXTENDED_MS ) ssl_set_extended_master_secret( &ssl, opt.extended_ms ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 1349737f90..e4dc7ea3c7 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -428,16 +428,43 @@ run_test "SSLv2 ClientHello: actual test" \ # Tests for Truncated HMAC extension -run_test "Truncated HMAC: reference" \ +run_test "Truncated HMAC: client default, server default" \ "$P_SRV debug_level=4" \ - "$P_CLI trunc_hmac=0 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ + "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ 0 \ - -s "dumping 'computed mac' (20 bytes)" + -s "dumping 'computed mac' (20 bytes)" \ + -S "dumping 'computed mac' (10 bytes)" -run_test "Truncated HMAC: actual test" \ +run_test "Truncated HMAC: client disabled, server default" \ "$P_SRV debug_level=4" \ - "$P_CLI trunc_hmac=1 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \ + "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \ + trunc_hmac=0" \ 0 \ + -s "dumping 'computed mac' (20 bytes)" \ + -S "dumping 'computed mac' (10 bytes)" + +run_test "Truncated HMAC: client enabled, server default" \ + "$P_SRV debug_level=4" \ + "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \ + trunc_hmac=1" \ + 0 \ + -S "dumping 'computed mac' (20 bytes)" \ + -s "dumping 'computed mac' (10 bytes)" + +run_test "Truncated HMAC: client enabled, server disabled" \ + "$P_SRV debug_level=4 trunc_hmac=0" \ + "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \ + trunc_hmac=1" \ + 0 \ + -s "dumping 'computed mac' (20 bytes)" \ + -S "dumping 'computed mac' (10 bytes)" + +run_test "Truncated HMAC: client enabled, server enabled" \ + "$P_SRV debug_level=4 trunc_hmac=1" \ + "$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA \ + trunc_hmac=1" \ + 0 \ + -S "dumping 'computed mac' (20 bytes)" \ -s "dumping 'computed mac' (10 bytes)" # Tests for Encrypt-then-MAC extension From 265fe997ffab5a65c6a1746b1029e2e76cb99193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 9 Jan 2015 12:43:35 +0100 Subject: [PATCH 7/8] Use library default for trunc-hmac in ssl_client2 --- programs/ssl/ssl_client2.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index cbb46ee12a..76cc8a4cb8 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -90,7 +90,7 @@ int main( int argc, char *argv[] ) #define DFL_MAX_VERSION -1 #define DFL_AUTH_MODE SSL_VERIFY_REQUIRED #define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE -#define DFL_TRUNC_HMAC 0 +#define DFL_TRUNC_HMAC -1 #define DFL_RECONNECT 0 #define DFL_RECO_DELAY 0 #define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED @@ -262,7 +262,7 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags ) #if defined(POLARSSL_SSL_TRUNCATED_HMAC) #define USAGE_TRUNC_HMAC \ - " trunc_hmac=%%d default: 0 (disabled)\n" + " trunc_hmac=%%d default: library default\n" #else #define USAGE_TRUNC_HMAC "" #endif /* POLARSSL_SSL_TRUNCATED_HMAC */ @@ -656,9 +656,12 @@ int main( int argc, char *argv[] ) } else if( strcmp( p, "trunc_hmac" ) == 0 ) { - opt.trunc_hmac = atoi( q ); - if( opt.trunc_hmac < 0 || opt.trunc_hmac > 1 ) - goto usage; + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } } else goto usage; @@ -934,12 +937,8 @@ int main( int argc, char *argv[] ) #endif #if defined(POLARSSL_SSL_TRUNCATED_HMAC) - if( opt.trunc_hmac != 0 ) - if( ( ret = ssl_set_truncated_hmac( &ssl, SSL_TRUNC_HMAC_ENABLED ) ) != 0 ) - { - printf( " failed\n ! ssl_set_truncated_hmac returned %d\n\n", ret ); - goto exit; - } + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + ssl_set_truncated_hmac( &ssl, opt.trunc_hmac ); #endif #if defined(POLARSSL_SSL_EXTENDED_MASTER_SECRET) From 18292456c50f80ec230a8dbcb0edf35ad3465681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 9 Jan 2015 14:34:13 +0100 Subject: [PATCH 8/8] Add support for getrandom() --- ChangeLog | 6 ++++++ library/entropy_poll.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/ChangeLog b/ChangeLog index fd83b9e608..34e9d27034 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ PolarSSL ChangeLog (Sorted per branch, date) += PolarSSL 1.3.10 released ??? + +Features + * Add support for getrandom() syscall on recent Linux kernels with Glibc or + a compatible enough libc (eg uClibc). + = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 9ca9e95199..33e75bc657 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -73,6 +73,43 @@ int platform_entropy_poll( void *data, unsigned char *output, size_t len, } #else /* _WIN32 && !EFIX64 && !EFI32 */ +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#if defined(HAVE_GETRANDOM) + +#include + +int platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + int ret; + ((void) data); + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( POLARSSL_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); +} + +#else /* HAVE_GETRANDOM */ + #include int platform_entropy_poll( void *data, @@ -100,6 +137,7 @@ int platform_entropy_poll( void *data, return( 0 ); } +#endif /* HAVE_GETRANDOM */ #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !POLARSSL_NO_PLATFORM_ENTROPY */