diff --git a/ChangeLog.d/tls13-fix-key-usage-checks.txt b/ChangeLog.d/tls13-fix-key-usage-checks.txt new file mode 100644 index 0000000000..f19bf523eb --- /dev/null +++ b/ChangeLog.d/tls13-fix-key-usage-checks.txt @@ -0,0 +1,7 @@ +Security + * Fix check of certificate key usage in TLS 1.3. The usage of the public key + provided by a client or server certificate for authentication was not + checked properly when validating the certificate. This could cause a + client or server to be able to authenticate itself through a certificate + to an Mbed TLS TLS 1.3 server or client while it does not own a proper + certificate to do so. diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c index c48922fbf8..c7e00a98a8 100644 --- a/library/ssl_tls13_generic.c +++ b/library/ssl_tls13_generic.c @@ -546,6 +546,8 @@ static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl ) int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; mbedtls_x509_crt *ca_chain; mbedtls_x509_crl *ca_crl; + const char *ext_oid; + size_t ext_len; uint32_t verify_result = 0; /* If SNI was used, overwrite authentication mode @@ -627,12 +629,25 @@ static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl ) /* * Secondary checks: always done, but change 'ret' only if it was 0 */ - if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, - ssl->handshake->ciphersuite_info, - !ssl->conf->endpoint, - &verify_result ) != 0 ) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( usage extensions )" ) ); + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( ( mbedtls_x509_crt_check_key_usage( + ssl->session_negotiate->peer_cert, + MBEDTLS_X509_KU_DIGITAL_SIGNATURE ) != 0 ) || + ( mbedtls_x509_crt_check_extended_key_usage( + ssl->session_negotiate->peer_cert, + ext_oid, ext_len ) != 0 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); if( ret == 0 ) ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } diff --git a/programs/ssl/ssl_test_common_source.c b/programs/ssl/ssl_test_common_source.c index 0e66895dbd..511ede9cb2 100644 --- a/programs/ssl/ssl_test_common_source.c +++ b/programs/ssl/ssl_test_common_source.c @@ -285,6 +285,9 @@ uint16_t ssl_sig_algs_for_test[] = { #if defined(MBEDTLS_SHA224_C) MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA224 ) #endif +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA1_C) /* Allow SHA-1 as we use it extensively in tests. */ MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA1 ) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 9ec2ffa303..41d69a36e1 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -6016,7 +6016,6 @@ run_test "keyUsage srv: RSA, digitalSignature -> (EC)DHE-RSA" \ 0 \ -c "Ciphersuite is TLS-[EC]*DHE-RSA-WITH-" - requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "keyUsage srv: RSA, keyEncipherment -> RSA" \ "$P_SRV key_file=data_files/server2.key \ @@ -6151,6 +6150,78 @@ run_test "keyUsage cli: DigitalSignature, RSA: fail, soft" \ -c "Ciphersuite is TLS-" \ -c "! Usage does not match the keyUsage extension" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: DigitalSignature+KeyEncipherment, RSA: OK" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \ + -cert data_files/server2.ku-ds_ke.crt" \ + "$P_CLI debug_level=3" \ + 0 \ + -C "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: KeyEncipherment, RSA: fail" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \ + -cert data_files/server2.ku-ke.crt" \ + "$P_CLI debug_level=1" \ + 1 \ + -c "bad certificate (usage extensions)" \ + -c "Processing of the Certificate handshake message failed" \ + -C "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: KeyAgreement, RSA: fail" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \ + -cert data_files/server2.ku-ka.crt" \ + "$P_CLI debug_level=1" \ + 1 \ + -c "bad certificate (usage extensions)" \ + -c "Processing of the Certificate handshake message failed" \ + -C "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: DigitalSignature, ECDSA: OK" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.ku-ds.crt" \ + "$P_CLI debug_level=3" \ + 0 \ + -C "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: KeyEncipherment, ECDSA: fail" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.ku-ke.crt" \ + "$P_CLI debug_level=1" \ + 1 \ + -c "bad certificate (usage extensions)" \ + -c "Processing of the Certificate handshake message failed" \ + -C "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli 1.3: KeyAgreement, ECDSA: fail" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.ku-ka.crt" \ + "$P_CLI debug_level=1" \ + 1 \ + -c "bad certificate (usage extensions)" \ + -c "Processing of the Certificate handshake message failed" \ + -C "Ciphersuite is" + # Tests for keyUsage in leaf certificates, part 3: # server-side checking of client cert @@ -6160,6 +6231,7 @@ run_test "keyUsage cli-auth: RSA, DigitalSignature: OK" \ "$O_CLI -key data_files/server2.key \ -cert data_files/server2.ku-ds.crt" \ 0 \ + -s "Verifying peer X.509 certificate... ok" \ -S "bad certificate (usage extensions)" \ -S "Processing of the Certificate handshake message failed" @@ -6187,6 +6259,7 @@ run_test "keyUsage cli-auth: ECDSA, DigitalSignature: OK" \ "$O_CLI -key data_files/server5.key \ -cert data_files/server5.ku-ds.crt" \ 0 \ + -s "Verifying peer X.509 certificate... ok" \ -S "bad certificate (usage extensions)" \ -S "Processing of the Certificate handshake message failed" @@ -6199,6 +6272,52 @@ run_test "keyUsage cli-auth: ECDSA, KeyAgreement: fail (soft)" \ -s "bad certificate (usage extensions)" \ -S "Processing of the Certificate handshake message failed" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli-auth 1.3: RSA, DigitalSignature: OK" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \ + -cert data_files/server2.ku-ds.crt" \ + 0 \ + -s "Verifying peer X.509 certificate... ok" \ + -S "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli-auth 1.3: RSA, KeyEncipherment: fail (soft)" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \ + -cert data_files/server2.ku-ke.crt" \ + 0 \ + -s "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli-auth 1.3: ECDSA, DigitalSignature: OK" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.ku-ds.crt" \ + 0 \ + -s "Verifying peer X.509 certificate... ok" \ + -S "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "keyUsage cli-auth 1.3: ECDSA, KeyAgreement: fail (soft)" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.ku-ka.crt" \ + 0 \ + -s "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + # Tests for extendedKeyUsage, part 1: server-side certificate/suite selection requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 @@ -6271,6 +6390,54 @@ run_test "extKeyUsage cli: codeSign -> fail" \ -c "Processing of the Certificate handshake message failed" \ -C "Ciphersuite is TLS-" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli 1.3: serverAuth -> OK" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.eku-srv.crt" \ + "$P_CLI debug_level=1" \ + 0 \ + -C "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli 1.3: serverAuth,clientAuth -> OK" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.eku-srv_cli.crt" \ + "$P_CLI debug_level=1" \ + 0 \ + -C "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli 1.3: codeSign,anyEKU -> OK" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.eku-cs_any.crt" \ + "$P_CLI debug_level=1" \ + 0 \ + -C "bad certificate (usage extensions)" \ + -C "Processing of the Certificate handshake message failed" \ + -c "Ciphersuite is" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli 1.3: codeSign -> fail" \ + "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \ + -cert data_files/server5.eku-cs.crt" \ + "$P_CLI debug_level=1" \ + 1 \ + -c "bad certificate (usage extensions)" \ + -c "Processing of the Certificate handshake message failed" \ + -C "Ciphersuite is" + # Tests for extendedKeyUsage, part 3: server-side checking of client cert requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 @@ -6318,6 +6485,50 @@ run_test "extKeyUsage cli-auth: codeSign -> fail (hard)" \ -s "bad certificate (usage extensions)" \ -s "Processing of the Certificate handshake message failed" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli-auth 1.3: clientAuth -> OK" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.eku-cli.crt" \ + 0 \ + -S "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli-auth 1.3: serverAuth,clientAuth -> OK" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.eku-srv_cli.crt" \ + 0 \ + -S "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli-auth 1.3: codeSign,anyEKU -> OK" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.eku-cs_any.crt" \ + 0 \ + -S "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3 +requires_openssl_tls1_3 +requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "extKeyUsage cli-auth 1.3: codeSign -> fail (soft)" \ + "$P_SRV debug_level=1 auth_mode=optional" \ + "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \ + -cert data_files/server5.eku-cs.crt" \ + 0 \ + -s "bad certificate (usage extensions)" \ + -S "Processing of the Certificate handshake message failed" + # Tests for DHM parameters loading requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2