Skip to content

gh-112454: Disable TLS-PSK if OpenSSL was built without PSK support #112491

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

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Doc/library/ssl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,12 @@ Constants

.. versionadded:: 3.7

.. data:: HAS_PSK

Whether the OpenSSL library has built-in support for TLS-PSK.

.. versionadded:: 3.13

.. data:: CHANNEL_BINDING_TYPES

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

This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is
``False``.

.. versionadded:: 3.13

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

This method will raise :exc:`NotImplementedError` if :data:`HAS_PSK` is
``False``.

.. versionadded:: 3.13

.. index:: single: certificates
Expand Down
2 changes: 1 addition & 1 deletion Lib/ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@

from _ssl import (
HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1,
HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3
HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3, HAS_PSK
)
from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION

Expand Down
2 changes: 2 additions & 0 deletions Lib/test/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4259,6 +4259,7 @@ def test_session_handling(self):
'Session refers to a different SSLContext.')

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

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

@requires_tls_version('TLSv1_3')
@unittest.skipUnless(ssl.HAS_PSK, 'TLS-PSK disabled on this OpenSSL build')
def test_psk_tls1_3(self):
psk = bytes.fromhex('deadbeef')
identity_hint = 'identity-hint'
Expand Down
28 changes: 28 additions & 0 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,10 @@ typedef struct {
BIO *keylog_bio;
/* Cached module state, also used in SSLSocket and SSLSession code. */
_sslmodulestate *state;
#ifndef OPENSSL_NO_PSK
PyObject *psk_client_callback;
PyObject *psk_server_callback;
#endif
} PySSLContext;

typedef struct {
Expand Down Expand Up @@ -3125,8 +3127,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version)
self->alpn_protocols = NULL;
self->set_sni_cb = NULL;
self->state = get_ssl_state(module);
#ifndef OPENSSL_NO_PSK
self->psk_client_callback = NULL;
self->psk_server_callback = NULL;
#endif

/* Don't check host name by default */
if (proto_version == PY_SSL_VERSION_TLS_CLIENT) {
Expand Down Expand Up @@ -3239,8 +3243,10 @@ context_clear(PySSLContext *self)
Py_CLEAR(self->set_sni_cb);
Py_CLEAR(self->msg_cb);
Py_CLEAR(self->keylog_filename);
#ifndef OPENSSL_NO_PSK
Py_CLEAR(self->psk_client_callback);
Py_CLEAR(self->psk_server_callback);
#endif
if (self->keylog_bio != NULL) {
PySSL_BEGIN_ALLOW_THREADS
BIO_free_all(self->keylog_bio);
Expand Down Expand Up @@ -4668,6 +4674,7 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form)
return NULL;
}

#ifndef OPENSSL_NO_PSK
static unsigned int psk_client_callback(SSL *s,
const char *hint,
char *identity,
Expand Down Expand Up @@ -4735,6 +4742,7 @@ static unsigned int psk_client_callback(SSL *s,
PyGILState_Release(gstate);
return 0;
}
#endif

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

Py_RETURN_NONE;
#else
PyErr_SetString(PyExc_NotImplementedError,
"TLS-PSK is not supported by your OpenSSL version.");
return NULL;
#endif
}

#ifndef OPENSSL_NO_PSK
static unsigned int psk_server_callback(SSL *s,
const char *identity,
unsigned char *psk,
Expand Down Expand Up @@ -4835,6 +4850,7 @@ static unsigned int psk_server_callback(SSL *s,
PyGILState_Release(gstate);
return 0;
}
#endif

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

Py_RETURN_NONE;
#else
PyErr_SetString(PyExc_NotImplementedError,
"TLS-PSK is not supported by your OpenSSL version.");
return NULL;
#endif
}


Expand Down Expand Up @@ -6243,6 +6265,12 @@ sslmodule_init_constants(PyObject *m)
addbool(m, "HAS_TLSv1_3", 0);
#endif

#ifdef OPENSSL_NO_PSK
addbool(m, "HAS_PSK", 0);
#else
addbool(m, "HAS_PSK", 1);
#endif

#undef addbool
#undef ADD_INT_CONST

Expand Down