diff --git a/Lib/ssl.py b/Lib/ssl.py index 62e5585714..7c64318053 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -267,7 +267,7 @@ class _TLSMessageType: socket_error = OSError # keep that public name in module namespace -CHANNEL_BINDING_TYPES = ['tls-unique'] +CHANNEL_BINDING_TYPES = ['tls-unique', 'tls-exporter'] HAS_NEVER_CHECK_COMMON_NAME = hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT') diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7bc30cb352..a0bd0a7d1b 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2746,10 +2746,11 @@ _ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, const char *cb_type) /*[clinic end generated code: output=34bac9acb6a61d31 input=08b7e43b99c17d41]*/ { + int version = SSL_version(self->ssl); char buf[PySSL_CB_MAXLEN]; size_t len; - if (strcmp(cb_type, "tls-unique") == 0) { + if (version < TLS1_3_VERSION && strcmp(cb_type, "tls-unique") == 0) { if (SSL_session_reused(self->ssl) ^ !self->socket_type) { /* if session is resumed XOR we are the client */ len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); @@ -2759,6 +2760,18 @@ _ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); } } + else if (version >= TLS1_3_VERSION || + (SSL_get_options(self->ssl) & SSL_OP_NO_RENEGOTIATION) != 0) { + static const char literal[] = "EXPORTER-Channel-Binding"; + + if (SSL_export_keying_material(self->ssl, (unsigned char *)buf, 32, + literal, sizeof(literal) - 1, + NULL, 0, 0) != 1) { + _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); + return NULL; + } + len = 32; + } else { PyErr_Format( PyExc_ValueError,