Skip to content

Commit 2ae9141

Browse files
[3.14] Clarify TLS 1.3 behavior of the SSLContext PSK callbacks (GH-160159) (#160423)
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 05d366d commit 2ae9141

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

21012101
Setting ``callback`` to :const:`None` removes any existing callback.
21022102

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

21062106
- the ``hint`` parameter is always :const:`None`.
21072107
- client-identity must be a non-empty string.
2108+
- the PSK is only offered to the server, which may decline it and
2109+
authenticate with a certificate instead. That certificate is checked
2110+
according to :attr:`~SSLContext.verify_mode`, so a client relying on
2111+
the PSK to authenticate the server should not set it to
2112+
:const:`CERT_NONE`, or should check :attr:`SSLSocket.session_reused`,
2113+
which is true if the PSK was used. A PSK handshake does not need any
2114+
CA certificates to be loaded when using :const:`CERT_REQUIRED`.
2115+
- a zero length PSK does not reject the connection, it only means that
2116+
no PSK is offered. An exception raised by the callback has the same
2117+
effect.
2118+
- the PSK is used with the SHA-256 handshake digest, so a server can
2119+
only accept it with a cipher suite that uses SHA-256.
21082120

21092121
Example usage::
21102122

21112123
context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
21122124
context.check_hostname = False
2113-
context.verify_mode = ssl.CERT_NONE
21142125
context.maximum_version = ssl.TLSVersion.TLSv1_2
21152126
context.set_ciphers('PSK')
21162127

@@ -2142,7 +2153,7 @@ to speed up repeated connections from the same clients.
21422153
The ``identity`` parameter is an optional identity sent by the client which can
21432154
be used to select a corresponding PSK.
21442155
The return value is a :term:`bytes-like object` representing the pre-shared key.
2145-
Return a zero length PSK to reject the connection.
2156+
With TLS 1.2 and earlier, return a zero length PSK to reject the connection.
21462157

21472158
Setting ``callback`` to :const:`None` removes any existing callback.
21482159

@@ -2151,7 +2162,19 @@ to speed up repeated connections from the same clients.
21512162
UTF-8 encoded.
21522163

21532164
.. note::
2154-
When using TLS 1.3 the ``identity_hint`` parameter is not sent to the client.
2165+
When using TLS 1.3:
2166+
2167+
- the ``identity_hint`` parameter is not sent to the client.
2168+
- a zero length PSK, or an exception raised by the callback, only
2169+
declines the client's PSK. If a certificate was loaded with
2170+
:meth:`~SSLContext.load_cert_chain`, the handshake continues with
2171+
certificate authentication instead of failing, so a server relying on
2172+
the PSK to authenticate clients should not load one, or should check
2173+
:attr:`SSLSocket.session_reused`, which is true if the PSK was used.
2174+
- the PSK can only be accepted with a cipher suite that uses SHA-256.
2175+
When a certificate is loaded, OpenSSL's default TLS 1.3 cipher suite
2176+
order selects a SHA-384 suite instead, so the PSK is declined even if
2177+
it matches.
21552178

21562179
Example usage::
21572180

‎Lib/test/test_ssl.py‎

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

48994899
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
49004900
client_context.check_hostname = False
4901-
client_context.verify_mode = ssl.CERT_NONE
49024901
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
49034902
client_context.set_ciphers('PSK')
49044903
client_context.set_psk_client_callback(lambda hint: (None, psk))
@@ -4977,7 +4976,6 @@ def server_callback(identity):
49774976

49784977
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
49794978
client_context.check_hostname = False
4980-
client_context.verify_mode = ssl.CERT_NONE
49814979
client_context.minimum_version = ssl.TLSVersion.TLSv1_3
49824980
client_context.set_ciphers('PSK')
49834981
client_context.set_psk_client_callback(client_callback)
@@ -4991,6 +4989,7 @@ def server_callback(identity):
49914989
with server:
49924990
with client_context.wrap_socket(socket.socket()) as s:
49934991
s.connect((HOST, server.port))
4992+
self.assertTrue(s.session_reused)
49944993

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

0 commit comments

Comments
 (0)