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-137197: Add SSLContext.set_ciphersuites to set TLS 1.3 ciphers#137198
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
5a1cc2209534fd6783fe6d3375f148e516411b760eeaae575e09017fcaf6675fe8791d4566478File 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 |
|---|---|---|
| @@ -1684,19 +1684,33 @@ to speed up repeated connections from the same clients. | ||
| .. method:: SSLContext.set_ciphers(ciphers) | ||
| Set the available ciphers for sockets created with this context. | ||
| It should be a string in the `OpenSSL cipher list format | ||
| Set the allowed ciphers for sockets created with this context when | ||
| connecting using TLS 1.2 and earlier. The *ciphers* argument should | ||
| be a string in the `OpenSSL cipher list format | ||
| <https://docs.openssl.org/master/man1/ciphers/>`_. | ||
| To set allowed TLS 1.3 ciphers, use :meth:`SSLContext.set_ciphersuites`. | ||
| If no cipher can be selected (because compile-time options or other | ||
| configuration forbids use of all the specified ciphers), an | ||
| :class:`SSLError` will be raised. | ||
| .. note:: | ||
| when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will | ||
| give the currently selected cipher. | ||
| When connected, the :meth:`SSLSocket.cipher` method of SSL sockets will | ||
| return details about the negotiated cipher. | ||
| .. method:: SSLContext.set_ciphersuites(ciphersuites) | ||
picnixz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Set the allowed ciphers for sockets created with this context when | ||
| connecting using TLS 1.3. The *ciphersuites* argument should be a | ||
| colon-separate string of TLS 1.3 cipher names. If no cipher can be | ||
| selected (because compile-time options or other configuration forbids | ||
| use of all the specified ciphers), an :class:`SSLError` will be raised. | ||
| .. note:: | ||
| When connected, the :meth:`SSLSocket.cipher` method of SSL sockets will | ||
| return details about the negotiated cipher. | ||
| TLS 1.3 cipher suites cannot be disabled with | ||
| :meth:`~SSLContext.set_ciphers`. | ||
| .. versionadded:: next | ||
| .. method:: SSLContext.set_groups(groups) | ||
| @@ -2844,10 +2858,15 @@ TLS 1.3 | ||
| The TLS 1.3 protocol behaves slightly differently than previous version | ||
| of TLS/SSL. Some new TLS 1.3 features are not yet available. | ||
| - TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and | ||
| ChaCha20 cipher suites are enabled by default. The method | ||
| :meth:`SSLContext.set_ciphers` cannot enable or disable any TLS 1.3 | ||
| ciphers yet, but :meth:`SSLContext.get_ciphers` returns them. | ||
| - TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and ChaCha20 | ||
| cipher suites are enabled by default. To restrict which TLS 1.3 ciphers | ||
| are allowed, the :meth:`SSLContext.set_ciphersuites` method should be | ||
| called instead of :meth:`SSLContext.set_ciphers`, which only affects | ||
| ciphers in older TLS versions. The :meth:`SSLContext.get_ciphers` method | ||
| returns information about ciphers for both TLS 1.3 and earlier versions | ||
| and the method :meth:`SSLSocket.cipher` returns information about the | ||
picnixz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| negotiated cipher for both TLS 1.3 and earlier versions once a connection | ||
| is established. | ||
| - Session tickets are no longer sent as part of the initial handshake and | ||
| are handled differently. :attr:`SSLSocket.session` and :class:`SSLSession` | ||
| are not compatible with TLS 1.3. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -263,7 +263,9 @@ def utc_offset(): #NOTE: ignore issues like #1647654 | ||
| def test_wrap_socket(sock, *, | ||
| cert_reqs=ssl.CERT_NONE, ca_certs=None, | ||
| ciphers=None, certfile=None, keyfile=None, | ||
| ciphers=None, ciphersuites=None, | ||
| min_version=None, max_version=None, | ||
| certfile=None, keyfile=None, | ||
| **kwargs): | ||
| if not kwargs.get("server_side"): | ||
| kwargs["server_hostname"] = SIGNED_CERTFILE_HOSTNAME | ||
| @@ -280,6 +282,12 @@ def test_wrap_socket(sock, *, | ||
| context.load_cert_chain(certfile, keyfile) | ||
| if ciphers is not None: | ||
| context.set_ciphers(ciphers) | ||
| if ciphersuites is not None: | ||
| context.set_ciphersuites(ciphersuites) | ||
| if min_version is not None: | ||
| context.minimum_version = min_version | ||
| if max_version is not None: | ||
| context.maximum_version = max_version | ||
| return context.wrap_socket(sock, **kwargs) | ||
| @@ -2238,6 +2246,68 @@ def test_transport_eof(self): | ||
| self.assertRaises(ssl.SSLEOFError, sslobj.read) | ||
| @unittest.skipUnless(has_tls_version('TLSv1_3'), "TLS 1.3 is not available") | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note to myself: change the | ||
| class SimpleBackgroundTestsTLS_1_3(unittest.TestCase): | ||
| """Tests that connect to a simple server running in the background.""" | ||
| def setUp(self): | ||
| server_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | ||
| ciphers = [cipher['name'] for cipher in server_ctx.get_ciphers() | ||
| if cipher['protocol'] == 'TLSv1.3'] | ||
| if not ciphers: | ||
| self.skipTest("No cipher supports TLSv1.3") | ||
| self.matching_cipher = ciphers[0] | ||
| # Some tests need at least two ciphers, and are responsible | ||
| # to skip themselves if matching_cipher == mismatched_cipher. | ||
| self.mismatched_cipher = ciphers[-1] | ||
| server_ctx.set_ciphersuites(self.matching_cipher) | ||
| server_ctx.load_cert_chain(SIGNED_CERTFILE) | ||
| server = ThreadedEchoServer(context=server_ctx) | ||
| self.enterContext(server) | ||
| self.server_addr = (HOST, server.port) | ||
| def test_ciphersuites(self): | ||
| # Test unrecognized TLS 1.3 cipher suite name | ||
| with ( | ||
| socket.socket(socket.AF_INET) as sock, | ||
| self.assertRaisesRegex(ssl.SSLError, | ||
| "No cipher suite can be selected") | ||
| ): | ||
| test_wrap_socket(sock, cert_reqs=ssl.CERT_NONE, | ||
| ciphersuites="XXX", | ||
| min_version=ssl.TLSVersion.TLSv1_3) | ||
| # Test successful TLS 1.3 handshake | ||
| with test_wrap_socket(socket.socket(socket.AF_INET), | ||
| cert_reqs=ssl.CERT_NONE, | ||
| ciphersuites=self.matching_cipher, | ||
| min_version=ssl.TLSVersion.TLSv1_3) as s: | ||
| s.connect(self.server_addr) | ||
| self.assertEqual(s.cipher()[0], self.matching_cipher) | ||
| def test_ciphersuite_downgrade(self): | ||
| with test_wrap_socket(socket.socket(socket.AF_INET), | ||
| cert_reqs=ssl.CERT_NONE, | ||
| ciphersuites=self.matching_cipher, | ||
| min_version=ssl.TLSVersion.TLSv1_2, | ||
| max_version=ssl.TLSVersion.TLSv1_2) as s: | ||
| s.connect(self.server_addr) | ||
| self.assertEqual(s.cipher()[1], 'TLSv1.2') | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test is asserting that the default | ||
| def test_ciphersuite_mismatch(self): | ||
| if self.matching_cipher == self.mismatched_cipher: | ||
| self.skipTest("Multiple TLS 1.3 ciphers are not available") | ||
picnixz marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| with test_wrap_socket(socket.socket(socket.AF_INET), | ||
| cert_reqs=ssl.CERT_NONE, | ||
| ciphersuites=self.mismatched_cipher, | ||
| min_version=ssl.TLSVersion.TLSv1_3) as s: | ||
| self.assertRaises(ssl.SSLError, s.connect, self.server_addr) | ||
| @support.requires_resource('network') | ||
| class NetworkedTests(unittest.TestCase): | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| :class:`~ssl.SSLContext` objects can now set TLS 1.3 cipher suites | ||
| via :meth:`~ssl.SSLContext.set_ciphersuites`. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.