Fetch channel binding digest explicitly with OpenSSL 3.0 and later

From: Mark Atwood <mark(at)reviewcommit(dot)com>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Fetch channel binding digest explicitly with OpenSSL 3.0 and later
Date: 2026-08-05 20:09:15
Message-ID: 178596055550.1584328.5465570319340175126@reviewcommit.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

The attached patch makes the tls-server-end-point channel binding hash
(RFC 5929) select its digest with EVP_MD_fetch() when building against OpenSSL
3.0 or newer.

be_tls_get_certificate_hash() and pgtls_get_peer_certificate_hash() compute the
certificate hash using the implicit EVP_sha256() / EVP_get_digestbynid()
digests, which do not deterministically dispatch through a loaded provider.
The patch selects the digest by name and fetches it, so the certificate hash is
computed by the active provider. The implicit path is retained for older
OpenSSL and for LibreSSL, guarded by OPENSSL_VERSION_NUMBER >= 0x30000000L.

The fetch uses the default library context and a NULL property query, so no
dependency is added and no particular provider is required.

The fetched EVP_MD is freed on every path, including the error paths: it is not
tracked by a resource owner, and the backend raises errors with elog(ERROR),
which does not return. That is the part of this patch most worth a careful
look.

I checked what the digest path resolves to at run time using
EVP_MD_get0_provider(). On OpenSSL 3.0.13, EVP_sha256() and the MD a context
ends up with after EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) both report no
provider (the legacy built-in), while EVP_MD_fetch(NULL, "SHA256", NULL)
reports the default provider. The probe program that prints this is attached
to the related cryptohash thread.

Details:

* Against master, tested at 8b73ceb78f. It touches
src/backend/libpq/be-secure-openssl.c and
src/interfaces/libpq/fe-secure-openssl.c, and applies on its own; there is
no dependency on the two related patches I am posting in separate threads.

* Built and tested with OpenSSL 3.0.13 on Ubuntu 24.04 (x86-64): clean build,
src/test/regress, src/test/ssl and src/test/authentication all pass.
src/test/ssl covers tls-server-end-point channel binding in 002_scram.pl,
which is the path this patch changes on both the server and libpq side.

* No new regression tests. This changes how an existing hash is computed
without changing the result or any API, and 002_scram.pl already exercises
both sides.

* No documentation change.

* No performance impact expected. The fetch is a provider lookup done at
connection setup, not in any tight loop.

This was previously posted as a three-patch series in a single thread [1].
Reposting as separate threads with the patch attached, per review request.

Intended for the next commitfest.

[1] https://postgr.es/m/20260805004805.1174492-1-mark%40reviewcommit.com

--
Mark

Attachment Content-Type Size
v1-0003-Fetch-the-channel-binding-digest-explicitly-with-.patch text/x-diff 6.6 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Ilia Evdokimov 2026-08-05 20:12:19 Re: Fold NOT IN / <> ALL expressions containing NULL to FALSE
Previous Message Mark Atwood 2026-08-05 20:09:13 Fetch digests explicitly for cryptohash with OpenSSL 3.0 and later