On Wed, Aug 05, 2026 at 01:09:13PM -0700, Mark Atwood wrote: > 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.
I was looking at this patch, and the switch to EVP_MD_fetch() makes sense, based on this: https://docs.openssl.org/3.0/man7/migration_guide/#programming With this quote: "If a library context is needed then all EVP_* digest functions that return a const EVP_MD * such as EVP_sha256() should be replaced with a call to EVP_MD_fetch(3). See "ALGORITHM FETCHING" in crypto(7)." The code your agent has generated (because it's AI-generated) is not really in line with the usual PostgreSQL format. The doc addition does not bring much: the stance about MD5 and FIPS was already true: we blocked MD5 computations in cryptohash_openssl.c before this change, it's still the case after this change. I have tested the attached with 3.5 (version installed on my system), and some custom 3.0 and 1.1.1 (not interesting, legacy API) builds, and that seems to work fine. -- Michael
From 22d19ff0a54f953caee1c748d9eab96b7c1c299a Mon Sep 17 00:00:00 2001 From: Michael Paquier <[email protected]> Date: Fri, 7 Aug 2026 16:36:08 +0900 Subject: [PATCH v2] Fetch digests explicitly for cryptohash with OpenSSL 3.0 and later cryptohash_openssl.c initialized the EVP_MD_CTX with the implicit static digest objects (EVP_sha256() and friends), which do not deterministically dispatch through a loaded provider. On OpenSSL 3.0 and newer, we now fetch the digest by name with EVP_MD_fetch(), cache it in the context, and free 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. OpenSSL 3.0 recommends to switch from the older APIs to EVP_MD_fetch(). --- src/common/cryptohash_openssl.c | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/common/cryptohash_openssl.c b/src/common/cryptohash_openssl.c index 51b7e0409333..8cab239b4a18 100644 --- a/src/common/cryptohash_openssl.c +++ b/src/common/cryptohash_openssl.c @@ -67,6 +67,9 @@ struct pg_cryptohash_ctx const char *errreason; EVP_MD_CTX *evpctx; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD *algo; +#endif #ifndef FRONTEND ResourceOwner resowner; @@ -178,10 +181,49 @@ int pg_cryptohash_init(pg_cryptohash_ctx *ctx) { int status = 0; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + const char *name = NULL; +#endif if (ctx == NULL) return -1; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /* + * Fetch the digest implementation so that it is served by the loaded + * provider. + */ + switch (ctx->type) + { + case PG_MD5: + name = "MD5"; + break; + case PG_SHA1: + name = "SHA1"; + break; + case PG_SHA224: + name = "SHA224"; + break; + case PG_SHA256: + name = "SHA256"; + break; + case PG_SHA384: + name = "SHA384"; + break; + case PG_SHA512: + name = "SHA512"; + break; + } + + /* + * Call EVP_MD_fetch() only once for each context, as provider lookups + * can be expensive. + */ + if (ctx->algo == NULL) + ctx->algo = EVP_MD_fetch(NULL, name, NULL); + if (ctx->algo != NULL) + status = EVP_DigestInit_ex(ctx->evpctx, ctx->algo, NULL); +#else switch (ctx->type) { case PG_MD5: @@ -203,6 +245,7 @@ pg_cryptohash_init(pg_cryptohash_ctx *ctx) status = EVP_DigestInit_ex(ctx->evpctx, EVP_sha512(), NULL); break; } +#endif /* OpenSSL internals return 1 on success, 0 on failure */ if (status <= 0) @@ -329,6 +372,9 @@ pg_cryptohash_free(pg_cryptohash_ctx *ctx) return; EVP_MD_CTX_destroy(ctx->evpctx); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD_free(ctx->algo); +#endif #ifndef FRONTEND if (ctx->resowner) -- 2.55.0
signature.asc
Description: PGP signature
