Skip to content

Commit fdf88ed

Browse files
[3.15] Clarify TLS 1.3 behavior of the SSLContext PSK callbacks (GH-160159) (#160422)
Clarify TLS 1.3 behavior of the SSLContext PSK callbacks (GH-160159) Under TLS 1.3 a PSK is only offered and may be declined, and both sides fall back to certificate authentication when one is available, so CERT_NONE leaves the server unauthenticated and a zero length PSK does not reject the connection. Drop CERT_NONE from the example and the PSK tests. A callback that raises is treated like one returning a zero length PSK, so under TLS 1.3 it also falls back to certificate authentication. A server with a certificate loaded declines even a matching PSK with OpenSSL's default TLS 1.3 cipher suite order, which selects a SHA-384 suite. Mention checking session_reused as the client side alternative to not using CERT_NONE. (cherry picked from commit 9b9657c) Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
1 parent 9a6143b commit fdf88ed

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

‎Doc/library/ssl.rst‎

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,8 +2221,8 @@ to speed up repeated connections from the same clients.
22212221
Client-identity is an optional string which may be used by the server to
22222222
select a corresponding PSK for the client. The string must be less than or
22232223
equal to ``256`` octets when UTF-8 encoded. PSK is a
2224-
:term:`bytes-like object` representing the pre-shared key. Return a zero
2225-
length PSK to reject the connection.
2224+
:term:`bytes-like object` representing the pre-shared key. With TLS 1.2
2225+
and earlier, return a zero length PSK to reject the connection.
22262226

22272227
Setting ``callback`` to :const:`None` removes any existing callback.
22282228

@@ -2231,12 +2231,23 @@ to speed up repeated connections from the same clients.
22312231

22322232
- the ``hint`` parameter is always :const:`None`.
22332233
- client-identity must be a non-empty string.
2234+
- the PSK is only offered to the server, which may decline it and
2235+
authenticate with a certificate instead. That certificate is checked
2236+
according to :attr:`~SSLContext.verify_mode`, so a client relying on
2237+
the PSK to authenticate the server should not set it to
2238+
:const:`CERT_NONE`, or should check :attr:`SSLSocket.session_reused`,
2239+
which is true if the PSK was used. A PSK handshake does not need any
2240+
CA certificates to be loaded when using :const:`CERT_REQUIRED`.
2241+
- a zero length PSK does not reject the connection, it only means that
2242+
no PSK is offered. An exception raised by the callback has the same
2243+
effect.
2244+
- the PSK is used with the SHA-256 handshake digest, so a server can
2245+
only accept it with a cipher suite that uses SHA-256.
22342246

22352247
Example usage::
22362248

22372249
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
22382250
context.check_hostname = False
2239-
context.verify_mode = ssl.CERT_NONE
22402251
context.maximum_version = ssl.TLSVersion.TLSv1_2
22412252
context.set_ciphers('PSK')
22422253

@@ -2268,7 +2279,7 @@ to speed up repeated connections from the same clients.
22682279
The ``identity`` parameter is an optional identity sent by the client which can
22692280
be used to select a corresponding PSK.
22702281
The return value is a :term:`bytes-like object` representing the pre-shared key.
2271-
Return a zero length PSK to reject the connection.
2282+
With TLS 1.2 and earlier, return a zero length PSK to reject the connection.
22722283

22732284
Setting ``callback`` to :const:`None` removes any existing callback.
22742285

@@ -2277,7 +2288,19 @@ to speed up repeated connections from the same clients.
22772288
UTF-8 encoded.
22782289

22792290
.. note::
2280-
When using TLS 1.3 the ``identity_hint`` parameter is not sent to the client.
2291+
When using TLS 1.3:
2292+
2293+
- the ``identity_hint`` parameter is not sent to the client.
2294+
- a zero length PSK, or an exception raised by the callback, only
2295+
declines the client's PSK. If a certificate was loaded with
2296+
:meth:`~SSLContext.load_cert_chain`, the handshake continues with
2297+
certificate authentication instead of failing, so a server relying on
2298+
the PSK to authenticate clients should not load one, or should check
2299+
:attr:`SSLSocket.session_reused`, which is true if the PSK was used.
2300+
- the PSK can only be accepted with a cipher suite that uses SHA-256.
2301+
When a certificate is loaded, OpenSSL's default TLS 1.3 cipher suite
2302+
order selects a SHA-384 suite instead, so the PSK is declined even if
2303+
it matches.
22812304

22822305
Example usage::
22832306

‎Lib/test/test_ssl.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5198,7 +5198,6 @@ def test_psk(self):
51985198

51995199
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
52005200
client_context.check_hostname = False
5201-
client_context.verify_mode = ssl.CERT_NONE
52025201
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
52035202
client_context.set_ciphers('PSK')
52045203
client_context.set_psk_client_callback(lambda hint: (None, psk))
@@ -5278,7 +5277,6 @@ def server_callback(identity):
52785277

52795278
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
52805279
client_context.check_hostname = False
5281-
client_context.verify_mode = ssl.CERT_NONE
52825280
client_context.minimum_version = ssl.TLSVersion.TLSv1_3
52835281
client_context.set_ciphers('PSK')
52845282
client_context.set_psk_client_callback(client_callback)
@@ -5292,6 +5290,7 @@ def server_callback(identity):
52925290
with server:
52935291
with client_context.wrap_socket(socket.socket()) as s:
52945292
s.connect((HOST, server.port))
5293+
self.assertTrue(s.session_reused)
52955294

52965295
@support.skip_if_sanitizer("gh-150191: OpenSSL races on SSL->rwstate and "
52975296
"the socket BIO flags with concurrent read "

0 commit comments

Comments
 (0)