diff --git a/imap/tls.c b/imap/tls.c index 31de7a757f..1a0e2a50a0 100644 --- a/imap/tls.c +++ b/imap/tls.c @@ -1313,19 +1313,47 @@ EXPORTED int tls_start_servertls(int readfd, int writefd, int timeout, saslprops->ssf = (sasl_ssf_t) tls_cipher_usebits; #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) - if (SSL_session_reused(tls_conn)) { - saslprops->cbinding.len = SSL_get_finished(tls_conn, - saslprops->tls_finished, - MAX_FINISHED_LEN); + if (SSL_version(tls_conn) <= TLS1_2_VERSION) { + if (SSL_session_reused(tls_conn)) { + saslprops->cbinding.len = + SSL_get_finished(tls_conn, + saslprops->tls_finished, + MAX_FINISHED_LEN); + } + else { + saslprops->cbinding.len = + SSL_get_peer_finished(tls_conn, + saslprops->tls_finished, + MAX_FINISHED_LEN); + } + saslprops->cbinding.name = "tls-unique"; + saslprops->cbinding.data = saslprops->tls_finished; + } +#if (OPENSSL_VERSION_NUMBER >= 0x10100001L) + else { + /* see RFC 9266 Section 2, Definition of label, context, length */ + static const char label[] = "EXPORTER-Channel-Binding"; + static const size_t key_len = 32; + + assert(key_len <= sizeof(saslprops->tls_finished)); + if (1 != SSL_export_keying_material(tls_conn, + saslprops->tls_finished, key_len, + label, sizeof(label)-1, + 0, 0, 0)) { + syslog(LOG_ERR, "Error reading EKM for channel binding"); + } + else { + saslprops->cbinding.name = "tls-exporter"; + saslprops->cbinding.data = saslprops->tls_finished; + saslprops->cbinding.len = key_len; + } } +#else else { - saslprops->cbinding.len = SSL_get_peer_finished(tls_conn, - saslprops->tls_finished, - MAX_FINISHED_LEN); + /* This case should not happen. It's a strange OpenSSL variant */ + syslog(LOG_ERR, "No EKM (channel binding) for TLS 1.3 or higher"); } - - saslprops->cbinding.name = "tls-unique"; - saslprops->cbinding.data = saslprops->tls_finished; +#endif /* (OPENSSL_VERSION_NUMBER >= 0x10100001L) */ #endif /* (OPENSSL_VERSION_NUMBER >= 0x0090800fL) */ #if OPENSSL_VERSION_NUMBER >= 0x10002000L diff --git a/imtest/imtest.c b/imtest/imtest.c index fd87dc1b83..0917c1e2a3 100644 --- a/imtest/imtest.c +++ b/imtest/imtest.c @@ -791,20 +791,46 @@ static void do_starttls(int ssl, char *keyfile, unsigned *ssf) imtest_fatal("Error setting SASL property (external auth_id)"); #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) - static unsigned char finished[EVP_MAX_MD_SIZE]; static struct sasl_channel_binding cbinding; - if (SSL_session_reused(tls_conn)) { - cbinding.len = SSL_get_peer_finished(tls_conn, - finished, sizeof(finished)); + if (SSL_version(tls_conn) <= TLS1_2_VERSION) { + static unsigned char finished[EVP_MAX_MD_SIZE]; + + if (SSL_session_reused(tls_conn)) { + cbinding.len = + SSL_get_peer_finished(tls_conn, finished, sizeof(finished)); + } + else { + cbinding.len = + SSL_get_finished(tls_conn, finished, sizeof(finished)); + } + + cbinding.name = "tls-unique"; + cbinding.critical = 0; + cbinding.data = finished; } +#if (OPENSSL_VERSION_NUMBER >= 0x10100001L) else { - cbinding.len = SSL_get_finished(tls_conn, finished, sizeof(finished)); - } + /* see RFC 9266 Section 2, Definition of label, context, length */ + static const char label[] = "EXPORTER-Channel-Binding"; + static unsigned char exported_key[32]; + static const size_t key_len = sizeof(exported_key); - cbinding.name = "tls-unique"; - cbinding.critical = 0; - cbinding.data = finished; + if (1 != SSL_export_keying_material(tls_conn, exported_key, key_len, + label, sizeof(label)-1, 0, 0, 0)) { + imtest_fatal("Error reading EKM for channel binding"); + } + cbinding.name = "tls-exporter"; + cbinding.critical = 0; + cbinding.len = key_len; + cbinding.data = exported_key; + } +#else + else { + /* This case should not happen. It's a strange OpenSSL variant */ + imtest_fatal("No EKM (channel binding) for TLS 1.3 or higher"); + } +#endif /* (OPENSSL_VERSION_NUMBER >= 0x10100001L) */ result = sasl_setprop(conn, SASL_CHANNEL_BINDING, &cbinding); if (result!=SASL_OK)