From 22d19ff0a54f953caee1c748d9eab96b7c1c299a Mon Sep 17 00:00:00 2001 From: Michael Paquier 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