Skip to content

Commit 9b9657c

Browse files
authored
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.
1 parent a4ac244 commit 9b9657c

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
@@ -2241,8 +2241,8 @@ to speed up repeated connections from the same clients.
22412241
Client-identity is an optional string which may be used by the server to
22422242
select a corresponding PSK for the client. The string must be less than or
22432243
equal to ``256`` octets when UTF-8 encoded. PSK is a
2244-
:term:`bytes-like object` representing the pre-shared key. Return a zero
2245-
length PSK to reject the connection.
2244+
:term:`bytes-like object` representing the pre-shared key. With TLS 1.2
2245+
and earlier, return a zero length PSK to reject the connection.
22462246

22472247
Setting ``callback`` to :const:`None` removes any existing callback.
22482248

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

22522252
- the ``hint`` parameter is always :const:`None`.
22532253
- client-identity must be a non-empty string.
2254+
- the PSK is only offered to the server, which may decline it and
2255+
authenticate with a certificate instead. That certificate is checked
2256+
according to :attr:`~SSLContext.verify_mode`, so a client relying on
2257+
the PSK to authenticate the server should not set it to
2258+
:const:`CERT_NONE`, or should check :attr:`SSLSocket.session_reused`,
2259+
which is true if the PSK was used. A PSK handshake does not need any
2260+
CA certificates to be loaded when using :const:`CERT_REQUIRED`.
2261+
- a zero length PSK does not reject the connection, it only means that
2262+
no PSK is offered. An exception raised by the callback has the same
2263+
effect.
2264+
- the PSK is used with the SHA-256 handshake digest, so a server can
2265+
only accept it with a cipher suite that uses SHA-256.
22542266

22552267
Example usage::
22562268

22572269
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
22582270
context.check_hostname = False
2259-
context.verify_mode = ssl.CERT_NONE
22602271
context.maximum_version = ssl.TLSVersion.TLSv1_2
22612272
context.set_ciphers('PSK')
22622273

@@ -2288,7 +2299,7 @@ to speed up repeated connections from the same clients.
22882299
The ``identity`` parameter is an optional identity sent by the client which can
22892300
be used to select a corresponding PSK.
22902301
The return value is a :term:`bytes-like object` representing the pre-shared key.
2291-
Return a zero length PSK to reject the connection.
2302+
With TLS 1.2 and earlier, return a zero length PSK to reject the connection.
22922303

22932304
Setting ``callback`` to :const:`None` removes any existing callback.
22942305

@@ -2297,7 +2308,19 @@ to speed up repeated connections from the same clients.
22972308
UTF-8 encoded.
22982309

22992310
.. note::
2300-
When using TLS 1.3 the ``identity_hint`` parameter is not sent to the client.
2311+
When using TLS 1.3:
2312+
2313+
- the ``identity_hint`` parameter is not sent to the client.
2314+
- a zero length PSK, or an exception raised by the callback, only
2315+
declines the client's PSK. If a certificate was loaded with
2316+
:meth:`~SSLContext.load_cert_chain`, the handshake continues with
2317+
certificate authentication instead of failing, so a server relying on
2318+
the PSK to authenticate clients should not load one, or should check
2319+
:attr:`SSLSocket.session_reused`, which is true if the PSK was used.
2320+
- the PSK can only be accepted with a cipher suite that uses SHA-256.
2321+
When a certificate is loaded, OpenSSL's default TLS 1.3 cipher suite
2322+
order selects a SHA-384 suite instead, so the PSK is declined even if
2323+
it matches.
23012324

23022325
Example usage::
23032326

‎Lib/test/test_ssl.py‎

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

52175217
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
52185218
client_context.check_hostname = False
5219-
client_context.verify_mode = ssl.CERT_NONE
52205219
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
52215220
client_context.set_ciphers('PSK')
52225221
client_context.set_psk_client_callback(lambda hint: (None, psk))
@@ -5296,7 +5295,6 @@ def server_callback(identity):
52965295

52975296
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
52985297
client_context.check_hostname = False
5299-
client_context.verify_mode = ssl.CERT_NONE
53005298
client_context.minimum_version = ssl.TLSVersion.TLSv1_3
53015299
client_context.set_ciphers('PSK')
53025300
client_context.set_psk_client_callback(client_callback)
@@ -5310,6 +5308,7 @@ def server_callback(identity):
53105308
with server:
53115309
with client_context.wrap_socket(socket.socket()) as s:
53125310
s.connect((HOST, server.port))
5311+
self.assertTrue(s.session_reused)
53135312

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

0 commit comments

Comments
 (0)