Skip to content

Commit

Permalink
pythongh-112454: Disable TLS-PSK if OpenSSL was built without PSK sup…
Browse files Browse the repository at this point in the history
…port (python#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
  • Loading branch information
grantramsay authored Nov 29, 2023
1 parent 48dfd74 commit e413daf
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 1 deletion.
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

0 comments on commit e413daf

Please sign in to comment.