From bc70a1836ba1e9f51ca5f4dec33a221bbc6548a4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 9 May 2017 15:59:24 +0200 Subject: [PATCH] Test that SHA-1 defaults off Added tests to validate that certificates signed using SHA-1 are rejected by default, but accepted if SHA-1 is explicitly enabled. --- programs/ssl/ssl_client2.c | 22 ++++++++++++++++--- programs/ssl/ssl_server2.c | 20 +++++++++++++++-- tests/data_files/.gitignore | 1 + tests/data_files/Makefile | 8 +++++++ tests/data_files/server2-sha256.crt | 21 ++++++++++++++++++ tests/ssl-opt.sh | 34 +++++++++++++++++++++++++++++ 6 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 tests/data_files/server2-sha256.crt diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index c8eb14553..212f47a6c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -87,6 +87,7 @@ int main( void ) #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_ARC4 -1 +#define DFL_SHA1 -1 #define DFL_AUTH_MODE -1 #define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE #define DFL_TRUNC_HMAC -1 @@ -263,6 +264,7 @@ int main( void ) USAGE_DHMLEN \ "\n" \ " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ " min_version=%%s default: (library default: tls1)\n" \ " max_version=%%s default: (library default: tls1_2)\n" \ " force_version=%%s default: \"\" (none)\n" \ @@ -301,6 +303,7 @@ struct options int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ int auth_mode; /* verify mode for connection */ unsigned char mfl_code; /* code for maximum fragment length */ int trunc_hmac; /* negotiate truncated hmac or not */ @@ -510,6 +513,7 @@ int main( int argc, char *argv[] ) opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; opt.auth_mode = DFL_AUTH_MODE; opt.mfl_code = DFL_MFL_CODE; opt.trunc_hmac = DFL_TRUNC_HMAC; @@ -724,6 +728,15 @@ int main( int argc, char *argv[] ) default: goto usage; } } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } else if( strcmp( p, "force_version" ) == 0 ) { if( strcmp( q, "ssl3" ) == 0 ) @@ -1110,9 +1123,12 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_X509_CRT_PARSE_C) /* The default algorithms profile disables SHA-1, but our tests still rely on it heavily. */ - crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); - mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); - mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + } if( opt.debug_level > 0 ) mbedtls_ssl_conf_verify( &conf, my_verify, NULL ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index b5e6305a7..e14a7578f 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -123,6 +123,7 @@ int main( void ) #define DFL_MIN_VERSION -1 #define DFL_MAX_VERSION -1 #define DFL_ARC4 -1 +#define DFL_SHA1 -1 #define DFL_AUTH_MODE -1 #define DFL_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED #define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE @@ -348,6 +349,7 @@ int main( void ) USAGE_ETM \ "\n" \ " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ " min_version=%%s default: (library default: tls1)\n" \ " max_version=%%s default: (library default: tls1_2)\n" \ " force_version=%%s default: \"\" (none)\n" \ @@ -403,6 +405,7 @@ struct options int min_version; /* minimum protocol version accepted */ int max_version; /* maximum protocol version accepted */ int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ int auth_mode; /* verify mode for connection */ int cert_req_ca_list; /* should we send the CA list? */ unsigned char mfl_code; /* code for maximum fragment length */ @@ -950,6 +953,7 @@ int main( int argc, char *argv[] ) opt.min_version = DFL_MIN_VERSION; opt.max_version = DFL_MAX_VERSION; opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; opt.auth_mode = DFL_AUTH_MODE; opt.cert_req_ca_list = DFL_CERT_REQ_CA_LIST; opt.mfl_code = DFL_MFL_CODE; @@ -1121,6 +1125,15 @@ int main( int argc, char *argv[] ) default: goto usage; } } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } else if( strcmp( p, "force_version" ) == 0 ) { if( strcmp( q, "ssl3" ) == 0 ) @@ -1649,8 +1662,11 @@ int main( int argc, char *argv[] ) /* The default algorithms profile disables SHA-1, but our tests still rely on it heavily. Hence we allow it here. A real-world server should use the default profile unless there is a good reason not to. */ - crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); - mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + } #endif /* MBEDTLS_X509_CRT_PARSE_C */ if( opt.auth_mode != DFL_AUTH_MODE ) diff --git a/tests/data_files/.gitignore b/tests/data_files/.gitignore index 7611e9bc9..d16c04c49 100644 --- a/tests/data_files/.gitignore +++ b/tests/data_files/.gitignore @@ -1,2 +1,3 @@ cli-rsa.csr +server2-rsa.csr test-ca.csr diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index e419ce9fe..9604b0568 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -31,6 +31,14 @@ cli-rsa-sha256.crt: $(cli_crt_key_file_rsa) test-ca-sha256.crt cli-rsa.csr $(OPENSSL) x509 -req -extfile $(cli_crt_extensions_file) -extensions cli-rsa -CA test-ca-sha256.crt -CAkey $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 4 -days 3653 -sha256 -in cli-rsa.csr -out $@ all_final += cli-rsa-sha256.crt +server2-rsa.csr: server2.key + $(OPENSSL) req -new -key server2.key -passin "pass:$(test_ca_pwd_rsa)" -subj "/C=NL/O=PolarSSL/CN=localhost" -out $@ +all_intermediate += server2-rsa.csr +server2-sha256.crt: server2-rsa.csr + $(OPENSSL) x509 -req -extfile $(cli_crt_extensions_file) -extensions cli-rsa -CA test-ca-sha256.crt -CAkey $(test_ca_key_file_rsa) -passin "pass:$(test_ca_pwd_rsa)" -set_serial 4 -days 3653 -sha256 -in server2-rsa.csr -out $@ +all_final += server2-sha256.crt + + all_final: $(all_final) all: $(all_intermediate) $(all_final) diff --git a/tests/data_files/server2-sha256.crt b/tests/data_files/server2-sha256.crt new file mode 100644 index 000000000..006d9dbed --- /dev/null +++ b/tests/data_files/server2-sha256.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER +MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN +MTcwNTA5MTM1MTA1WhcNMjcwNTEwMTM1MTA1WjA0MQswCQYDVQQGEwJOTDERMA8G +A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN +owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz +NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM +tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P +hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya +HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaOBkjCBjzAd +BgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwYwYDVR0jBFwwWoAUtFrkpbPe +0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNVBAYTAk5MMREwDwYDVQQKDAhQb2xh +clNTTDEZMBcGA1UEAwwQUG9sYXJTU0wgVGVzdCBDQYIBADAJBgNVHRMEAjAAMA0G +CSqGSIb3DQEBCwUAA4IBAQAQf85QSjAeP+l6hirPorUL+k/3BznAh/6RXdveBO3K +uwtqK5qI59+3N+ZLXP7fr2Z5eO8qpchRgNNwT0LKglAEXGWn30PYI1GKSiqAaK0X +CUNIrxV3qKqOLbtqP1dMdiwsmiHYrN8E9UdysObedE2yDNLpTMHPJBZ+k6FowTyZ +IpUuabkxMBFxmLv+nOBDOiaCzintEcdJdY4F6p5j8jwMvVNVAXNfxAEwa0MoVRTt +/GORvq4ZEfsatVA+HRi602m+dZETTWKSODrj8AuQcG8/i1AOhk3C1WNOFKj/ZSfB +2P6EQmhLeRp4bO+3rG73T3R2yn0PZYQ7ZrjFPPKqgu+n +-----END CERTIFICATE----- diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 6bd787328..c6bf0a16a 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -699,6 +699,40 @@ run_test "RC4: both enabled" \ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - The server has no ciphersuites in common" +# Tests for SHA-1 support + +run_test "SHA-1 forbidden by default in server certificate" \ + "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \ + "$P_CLI debug_level=2 allow_sha1=0" \ + 1 \ + -c "The certificate is signed with an unacceptable hash" + +run_test "SHA-1 explicitly allowed in server certificate" \ + "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \ + "$P_CLI allow_sha1=1" \ + 0 + +run_test "SHA-256 allowed by default in server certificate" \ + "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2-sha256.crt" \ + "$P_CLI allow_sha1=0" \ + 0 + +run_test "SHA-1 forbidden by default in client certificate" \ + "$P_SRV auth_mode=required allow_sha1=0" \ + "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \ + 1 \ + -s "The certificate is signed with an unacceptable hash" + +run_test "SHA-1 explicitly allowed in client certificate" \ + "$P_SRV auth_mode=required allow_sha1=1" \ + "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \ + 0 + +run_test "SHA-256 allowed by default in client certificate" \ + "$P_SRV auth_mode=required allow_sha1=0" \ + "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha256.crt" \ + 0 + # Tests for Truncated HMAC extension run_test "Truncated HMAC: client default, server default" \