Skip to content

Commit e413daf

Browse files
authored
gh-112454: Disable TLS-PSK if OpenSSL was built without PSK support (#112491)
If OpenSSL was built without PSK support, the python TLS-PSK methods will raise "NotImplementedError" if called. Add a constant "ssl.HAS_PSK" to check if TLS-PSK is supported
1 parent 48dfd74 commit e413daf

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

Doc/library/ssl.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,12 @@ Constants
908908

909909
.. versionadded:: 3.7
910910

911+
.. data:: HAS_PSK
912+
913+
Whether the OpenSSL library has built-in support for TLS-PSK.
914+
915+
.. versionadded:: 3.13
916+
911917
.. data:: CHANNEL_BINDING_TYPES
912918

913919
List of supported TLS channel binding types. Strings in this list
@@ -2050,6 +2056,9 @@ to speed up repeated connections from the same clients.
20502056
return 'ClientId_1', psk_table.get(hint, b'')
20512057
context.set_psk_client_callback(callback)
20522058

2059+
This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is
2060+
``False``.
2061+
20532062
.. versionadded:: 3.13
20542063

20552064
.. method:: SSLContext.set_psk_server_callback(callback, identity_hint=None)
@@ -2092,6 +2101,9 @@ to speed up repeated connections from the same clients.
20922101
return psk_table.get(identity, b'')
20932102
context.set_psk_server_callback(callback, 'ServerId_1')
20942103

2104+
This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is
2105+
``False``.
2106+
20952107
.. versionadded:: 3.13
20962108

20972109
.. index:: single: certificates

Lib/ssl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116

117117
from _ssl import (
118118
HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1,
119-
HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3
119+
HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3, HAS_PSK
120120
)
121121
from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION
122122

Lib/test/test_ssl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4259,6 +4259,7 @@ def test_session_handling(self):
42594259
'Session refers to a different SSLContext.')
42604260

42614261
@requires_tls_version('TLSv1_2')
4262+
@unittest.skipUnless(ssl.HAS_PSK, 'TLS-PSK disabled on this OpenSSL build')
42624263
def test_psk(self):
42634264
psk = bytes.fromhex('deadbeef')
42644265

@@ -4326,6 +4327,7 @@ def server_callback(identity):
43264327
s.connect((HOST, server.port))
43274328

43284329
@requires_tls_version('TLSv1_3')
4330+
@unittest.skipUnless(ssl.HAS_PSK, 'TLS-PSK disabled on this OpenSSL build')
43294331
def test_psk_tls1_3(self):
43304332
psk = bytes.fromhex('deadbeef')
43314333
identity_hint = 'identity-hint'

Modules/_ssl.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,10 @@ typedef struct {
301301
BIO *keylog_bio;
302302
/* Cached module state, also used in SSLSocket and SSLSession code. */
303303
_sslmodulestate *state;
304+
#ifndef OPENSSL_NO_PSK
304305
PyObject *psk_client_callback;
305306
PyObject *psk_server_callback;
307+
#endif
306308
} PySSLContext;
307309

308310
typedef struct {
@@ -3125,8 +3127,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
31253127
self->alpn_protocols = NULL;
31263128
self->set_sni_cb = NULL;
31273129
self->state = get_ssl_state(module);
3130+
#ifndef OPENSSL_NO_PSK
31283131
self->psk_client_callback = NULL;
31293132
self->psk_server_callback = NULL;
3133+
#endif
31303134

31313135
/* Don't check host name by default */
31323136
if (proto_version == PY_SSL_VERSION_TLS_CLIENT) {
@@ -3239,8 +3243,10 @@ context_clear(PySSLContext *self)
32393243
Py_CLEAR(self->set_sni_cb);
32403244
Py_CLEAR(self->msg_cb);
32413245
Py_CLEAR(self->keylog_filename);
3246+
#ifndef OPENSSL_NO_PSK
32423247
Py_CLEAR(self->psk_client_callback);
32433248
Py_CLEAR(self->psk_server_callback);
3249+
#endif
32443250
if (self->keylog_bio != NULL) {
32453251
PySSL_BEGIN_ALLOW_THREADS
32463252
BIO_free_all(self->keylog_bio);
@@ -4668,6 +4674,7 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
46684674
return NULL;
46694675
}
46704676

4677+
#ifndef OPENSSL_NO_PSK
46714678
static unsigned int psk_client_callback(SSL *s,
46724679
const char *hint,
46734680
char *identity,
@@ -4735,6 +4742,7 @@ static unsigned int psk_client_callback(SSL *s,
47354742
PyGILState_Release(gstate);
47364743
return 0;
47374744
}
4745+
#endif
47384746

47394747
/*[clinic input]
47404748
_ssl._SSLContext.set_psk_client_callback
@@ -4747,6 +4755,7 @@ _ssl__SSLContext_set_psk_client_callback_impl(PySSLContext *self,
47474755
PyObject *callback)
47484756
/*[clinic end generated code: output=0aba86f6ed75119e input=7627bae0e5ee7635]*/
47494757
{
4758+
#ifndef OPENSSL_NO_PSK
47504759
if (self->protocol == PY_SSL_VERSION_TLS_SERVER) {
47514760
_setSSLError(get_state_ctx(self),
47524761
"Cannot add PSK client callback to a "
@@ -4774,8 +4783,14 @@ _ssl__SSLContext_set_psk_client_callback_impl(PySSLContext *self,
47744783
SSL_CTX_set_psk_client_callback(self->ctx, ssl_callback);
47754784

47764785
Py_RETURN_NONE;
4786+
#else
4787+
PyErr_SetString(PyExc_NotImplementedError,
4788+
"TLS-PSK is not supported by your OpenSSL version.");
4789+
return NULL;
4790+
#endif
47774791
}
47784792

4793+
#ifndef OPENSSL_NO_PSK
47794794
static unsigned int psk_server_callback(SSL *s,
47804795
const char *identity,
47814796
unsigned char *psk,
@@ -4835,6 +4850,7 @@ static unsigned int psk_server_callback(SSL *s,
48354850
PyGILState_Release(gstate);
48364851
return 0;
48374852
}
4853+
#endif
48384854

48394855
/*[clinic input]
48404856
_ssl._SSLContext.set_psk_server_callback
@@ -4849,6 +4865,7 @@ _ssl__SSLContext_set_psk_server_callback_impl(PySSLContext *self,
48494865
const char *identity_hint)
48504866
/*[clinic end generated code: output=1f4d6a4e09a92b03 input=65d4b6022aa85ea3]*/
48514867
{
4868+
#ifndef OPENSSL_NO_PSK
48524869
if (self->protocol == PY_SSL_VERSION_TLS_CLIENT) {
48534870
_setSSLError(get_state_ctx(self),
48544871
"Cannot add PSK server callback to a "
@@ -4882,6 +4899,11 @@ _ssl__SSLContext_set_psk_server_callback_impl(PySSLContext *self,
48824899
SSL_CTX_set_psk_server_callback(self->ctx, ssl_callback);
48834900

48844901
Py_RETURN_NONE;
4902+
#else
4903+
PyErr_SetString(PyExc_NotImplementedError,
4904+
"TLS-PSK is not supported by your OpenSSL version.");
4905+
return NULL;
4906+
#endif
48854907
}
48864908

48874909

@@ -6243,6 +6265,12 @@ sslmodule_init_constants(PyObject *m)
62436265
addbool(m, "HAS_TLSv1_3", 0);
62446266
#endif
62456267

6268+
#ifdef OPENSSL_NO_PSK
6269+
addbool(m, "HAS_PSK", 0);
6270+
#else
6271+
addbool(m, "HAS_PSK", 1);
6272+
#endif
6273+
62466274
#undef addbool
62476275
#undef ADD_INT_CONST
62486276

0 commit comments

Comments
 (0)