Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-138252: Add support in SSL module for getting and setting TLS signature algorithms#138269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
7361440c58c025761be4cc045a2c2b336ed1a549b4b659110bc845992d47a6c0c07131aad7d472ec62c036733b9e43b937File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -51,6 +51,10 @@ | ||
| CAN_GET_SELECTED_OPENSSL_GROUP = ssl.OPENSSL_VERSION_INFO >= (3, 2) | ||
| CAN_IGNORE_UNKNOWN_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 3) | ||
| CAN_GET_AVAILABLE_OPENSSL_GROUPS = ssl.OPENSSL_VERSION_INFO >= (3, 5) | ||
| CAN_GET_AVAILABLE_OPENSSL_SIGALGS = ssl.OPENSSL_VERSION_INFO >= (3, 4) | ||
| CAN_SET_CLIENT_SIGALGS = "AWS-LC" not in ssl.OPENSSL_VERSION | ||
| CAN_IGNORE_UNKNOWN_OPENSSL_SIGALGS = ssl.OPENSSL_VERSION_INFO >= (3, 3) | ||
| CAN_GET_SELECTED_OPENSSL_SIGALG = ssl.OPENSSL_VERSION_INFO >= (3, 5) | ||
| PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') | ||
| PROTOCOL_TO_TLS_VERSION = {} | ||
| @@ -294,7 +298,8 @@ def test_wrap_socket(sock, *, | ||
| USE_SAME_TEST_CONTEXT = False | ||
| _TEST_CONTEXT = None | ||
| def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True): | ||
| def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True, | ||
| client_cert=None): | ||
| """Create context | ||
| client_context, server_context, hostname = testing_context() | ||
| @@ -321,6 +326,10 @@ def testing_context(server_cert=SIGNED_CERTFILE, *, server_chain=True): | ||
| if server_chain: | ||
| server_context.load_verify_locations(SIGNING_CA) | ||
| if client_cert: | ||
| client_context.load_cert_chain(client_cert) | ||
| server_context.verify_mode = ssl.CERT_REQUIRED | ||
| if USE_SAME_TEST_CONTEXT: | ||
| if _TEST_CONTEXT is not None: | ||
| _TEST_CONTEXT = client_context, server_context, hostname | ||
| @@ -990,6 +999,37 @@ def test_get_groups(self): | ||
| self.assertNotIn('P-256', ctx.get_groups()) | ||
| self.assertIn('P-256', ctx.get_groups(include_aliases=True)) | ||
| @unittest.skipUnless(CAN_GET_AVAILABLE_OPENSSL_SIGALGS, | ||
| "SSL library doesn't support getting sigalgs") | ||
| def test_get_sigalgs(self): | ||
| self.assertIn('rsa_pss_rsae_sha256', ssl.get_sigalgs()) | ||
| @unittest.skipUnless(CAN_SET_CLIENT_SIGALGS, | ||
| "SSL library doesn't support setting client sigalgs") | ||
| def test_set_client_sigalgs(self): | ||
| ctx = ssl.create_default_context() | ||
| self.assertIsNone(ctx.set_client_sigalgs('rsa_pss_rsae_sha256')) | ||
| self.assertRaises(ssl.SSLError, ctx.set_client_sigalgs, | ||
| 'rsa_pss_rsae_sha256:foo') | ||
| # Ignoring unknown sigalgs is only supported since OpenSSL 3.3. | ||
| if CAN_IGNORE_UNKNOWN_OPENSSL_SIGALGS: | ||
| self.assertIsNone(ctx.set_client_sigalgs('rsa_pss_rsae_sha256:?foo')) | ||
| def test_set_server_sigalgs(self): | ||
| ctx = ssl.create_default_context() | ||
| self.assertIsNone(ctx.set_server_sigalgs('rsa_pss_rsae_sha256')) | ||
| self.assertRaises(ssl.SSLError, ctx.set_server_sigalgs, | ||
| 'rsa_pss_rsae_sha256:foo') | ||
| # Ignoring unknown sigalgs is only supported since OpenSSL 3.3. | ||
| if CAN_IGNORE_UNKNOWN_OPENSSL_SIGALGS: | ||
| self.assertIsNone(ctx.set_server_sigalgs('rsa_pss_rsae_sha256:?foo')) | ||
| def test_options(self): | ||
| # Test default SSLContext options | ||
| ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) | ||
| @@ -2814,6 +2854,9 @@ def server_params_test(client_context, server_context, indata=b"FOO\n", | ||
| }) | ||
| if CAN_GET_SELECTED_OPENSSL_GROUP: | ||
| stats.update({'group': s.group()}) | ||
| if CAN_GET_SELECTED_OPENSSL_SIGALG: | ||
| stats.update({'client_sigalg': s.client_sigalg()}) | ||
| stats.update({'server_sigalg': s.server_sigalg()}) | ||
| s.close() | ||
| stats['server_alpn_protocols'] = server.selected_alpn_protocols | ||
| stats['server_shared_ciphers'] = server.shared_ciphers | ||
| @@ -4273,6 +4316,71 @@ def test_groups(self): | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| @unittest.skipUnless(CAN_SET_CLIENT_SIGALGS, | ||
| "SSL library doesn't support setting client sigalgs") | ||
| def test_client_sigalgs(self): | ||
| # no mutual auth, so cient_sigalg should be None | ||
| client_context, server_context, hostname = testing_context() | ||
| stats = server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| if CAN_GET_SELECTED_OPENSSL_SIGALG: | ||
| self.assertIsNone(stats['client_sigalg']) | ||
| # server auto, client rsa_pss_rsae_sha384 | ||
| sigalg = "rsa_pss_rsae_sha384" | ||
| client_context, server_context, hostname = \ | ||
| testing_context(client_cert=SIGNED_CERTFILE) | ||
| client_context.set_client_sigalgs(sigalg) | ||
| stats = server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| if CAN_GET_SELECTED_OPENSSL_SIGALG: | ||
| self.assertEqual(stats['client_sigalg'], sigalg) | ||
| @unittest.skipUnless(CAN_SET_CLIENT_SIGALGS, | ||
| "SSL library doesn't support setting client sigalgs") | ||
| def test_client_sigalgs_mismatch(self): | ||
| client_context, server_context, hostname = \ | ||
| testing_context(client_cert=SIGNED_CERTFILE) | ||
| client_context.set_client_sigalgs("rsa_pss_rsae_sha256") | ||
| server_context.set_client_sigalgs("rsa_pss_rsae_sha384") | ||
| # Some systems return ConnectionResetError on handshake failures | ||
| with self.assertRaises((ssl.SSLError, ConnectionResetError)): | ||
| server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| def test_server_sigalgs(self): | ||
| # server rsa_pss_rsae_sha384, client auto | ||
| sigalg = "rsa_pss_rsae_sha384" | ||
| client_context, server_context, hostname = testing_context() | ||
| server_context.set_server_sigalgs(sigalg) | ||
| stats = server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| if CAN_GET_SELECTED_OPENSSL_SIGALG: | ||
| self.assertEqual(stats['server_sigalg'], sigalg) | ||
| # server auto, client rsa_pss_rsae_sha384 | ||
| client_context, server_context, hostname = testing_context() | ||
| client_context.set_server_sigalgs(sigalg) | ||
| stats = server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| if CAN_GET_SELECTED_OPENSSL_SIGALG: | ||
| self.assertEqual(stats['server_sigalg'], sigalg) | ||
| def test_server_sigalgs_mismatch(self): | ||
| client_context, server_context, hostname = testing_context() | ||
picnixz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| client_context.set_server_sigalgs("rsa_pss_rsae_sha256") | ||
| server_context.set_server_sigalgs("rsa_pss_rsae_sha384") | ||
| with self.assertRaises(ssl.SSLError): | ||
| server_params_test(client_context, server_context, | ||
| chatty=True, connectionchatty=True, | ||
| sni_name=hostname) | ||
| def test_selected_alpn_protocol(self): | ||
| # selected_alpn_protocol() is None unless ALPN is used. | ||
| client_context, server_context, hostname = testing_context() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| :mod:`ssl`: :class:`~ssl.SSLContext` objects can now set client and server | ||
| TLS signature algorithms. If Python has been built with OpenSSL 3.5 or later, | ||
| :class:`~ssl.SSLSocket` objects can return the signature algorithms selected | ||
| on a connection. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.