| From: | Mark Atwood <mark(at)reviewcommit(dot)com> |
|---|---|
| To: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Fetch digests explicitly for cryptohash with OpenSSL 3.0 and later |
| Date: | 2026-08-05 20:09:13 |
| Message-ID: | 178596055358.1584287.8485463954311014881@reviewcommit.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
The attached patch makes src/common/cryptohash_openssl.c select its digest with
EVP_MD_fetch() when building against OpenSSL 3.0 or newer.
cryptohash_openssl.c initializes the EVP_MD_CTX with the implicit static digest
objects (EVP_sha256() and friends), which do not deterministically dispatch
through a loaded provider. The patch fetches the digest by name, caches it in
the context, and frees it on teardown, so hashing is served by the active
provider. The digest type is fixed for the lifetime of the context, so the
fetch is done once. The implicit path is kept 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.
All of PostgreSQL's authentication hashing (SCRAM, md5) rides pg_cryptohash, so
it follows the active provider automatically. As a consequence md5
authentication depends on MD5 being offered by the provider, and is therefore
unavailable under FIPS. That is the intended behavior, and it matches the
reasoning already given for moving MD5 to EVP: otherwise PostgreSQL would
"cheat if FIPS is enabled because MD5 should not be authorized", whereas EVP
"allows us to rely on OpenSSL to control such restrictions" [1]. Every md5
hashing call site already fails closed, so a FIPS provider rejects md5 auth
rather than silently bypassing it. The patch documents this in
client-auth.sgml and points to scram-sha-256.
I checked what these paths resolve to at run time rather than assuming. The
probe program is attached as provider_probe.c; it makes no assertions, it
prints what OpenSSL reports via EVP_MD_get0_provider(). Build it with
"cc -o provider_probe provider_probe.c -lcrypto". On OpenSSL 3.0.13:
Q1 EVP_sha256() provider : LEGACY BUILT-IN (no provider)
Q2 ctx MD after DigestInit_ex(EVP_sha256()) : LEGACY BUILT-IN (no provider)
Q3 EVP_MD_fetch(NULL,"SHA256",NULL) : default
Q4a EVP_MD_fetch(legacy-only ctx,"SHA256") : FETCH FAILED
Q4b EVP_MD_fetch(legacy-only ctx,"MD5") : FETCH FAILED
Q1/Q2 are what the backend does today; Q3 is what the patch switches to. Q4 is
the control: with a library context holding only the legacy provider, the fetch
fails rather than silently falling back to a built-in. That is the behavior
that makes a FIPS provider's restrictions actually take effect.
Details:
* Against master, tested at 8b73ceb78f. It touches
src/common/cryptohash_openssl.c and doc/src/sgml/client-auth.sgml, 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. The
digests were also checked against the NIST known-answer vectors.
* No new regression tests. This replaces the implementation behind
pg_cryptohash without changing its behavior or API, and the existing SCRAM
and md5 coverage in src/test/authentication exercises it.
* Documentation: client-auth.sgml gains a note that md5 authentication is
unavailable when the provider does not offer MD5, as under FIPS, with a
pointer to scram-sha-256.
* No performance impact expected. The fetch is a provider lookup done once
per context, and these paths run at connection time and at hash-seed setup,
not in any tight loop.
* pgcrypto is deliberately out of scope. It exposes legacy ciphers (DES,
Blowfish, CAST5) that depend on OpenSSL's legacy provider and warrant a
separate discussion.
This was previously posted as a three-patch series in a single thread [2].
Reposting as separate threads with the patch attached, per review request.
Intended for the next commitfest.
[1] https://postgr.es/m/20201106073434.GA4961@paquier.xyz
[2] https://postgr.es/m/20260805004805.1174492-1-mark%40reviewcommit.com
--
Mark
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0002-Fetch-digests-explicitly-for-cryptohash-with-Open.patch | text/x-diff | 4.5 KB |
| provider_probe.c | text/x-csrc | 2.8 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Mark Atwood | 2026-08-05 20:09:15 | Fetch channel binding digest explicitly with OpenSSL 3.0 and later |
| Previous Message | Mark Atwood | 2026-08-05 20:09:11 | Use EVP_MAC for HMAC with OpenSSL 3.0 and later |