1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Use EVP_MAC for HMAC (OpenSSL >= 3.0)

The legacy HMAC_CTX interface (HMAC_CTX_new(), HMAC_Init_ex(), etc.) has
been deprecated since OpenSSL 3.0.  The legacy routines do not dispatch
through the provider framework, so a loaded provider's HMAC
implementation could be bypassed.

This commit updates hmac_openssl.c to use EVP_MAC when building with
OpenSSL 3.0 or newer versions.  OpenSSL 1.1.1 is the oldest version
supported on HEAD, so the legacy routines need to be kept.  Note that
LibreSSL uses the legacy routines.

Like b91f79cd08, no backpatch is done.

Author: Mark Atwood <mark@reviewcommit.com>
Co-authored-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/178596055149.1584250.13974609482797470185@reviewcommit.com
This commit is contained in:
Michael Paquier
2026-08-10 14:53:03 +09:00
parent b91f79cd08
commit 1f3b9bb109

View File

@@ -22,7 +22,13 @@
#include <openssl/err.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#else
#include <openssl/hmac.h>
#endif
#include "common/hmac.h"
#include "common/md5.h"
@@ -58,7 +64,12 @@ typedef enum pg_hmac_errno
/* Internal pg_hmac_ctx structure */
struct pg_hmac_ctx
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MAC *mac;
EVP_MAC_CTX *hmacctx;
#else
HMAC_CTX *hmacctx;
#endif
pg_cryptohash_type type;
pg_hmac_errno error;
const char *errreason;
@@ -139,10 +150,24 @@ pg_hmac_create(pg_cryptohash_type type)
ResourceOwnerEnlarge(CurrentResourceOwner);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/*
* Fetch the HMAC implementation so that it is served by the loaded
* provider.
*/
ctx->mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
if (ctx->mac != NULL)
ctx->hmacctx = EVP_MAC_CTX_new(ctx->mac);
#else
ctx->hmacctx = HMAC_CTX_new();
#endif
if (ctx->hmacctx == NULL)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MAC_free(ctx->mac);
#endif
explicit_bzero(ctx, sizeof(pg_hmac_ctx));
FREE(ctx);
#ifndef FRONTEND
@@ -153,7 +178,6 @@ pg_hmac_create(pg_cryptohash_type type)
return NULL;
}
#ifdef USE_RESOWNER_FOR_HMAC
ctx->resowner = CurrentResourceOwner;
ResourceOwnerRememberHMAC(CurrentResourceOwner, ctx);
@@ -171,10 +195,43 @@ int
pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
{
int status = 0;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
const char *digest = NULL;
OSSL_PARAM params[2];
#endif
if (ctx == NULL)
return -1;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
switch (ctx->type)
{
case PG_MD5:
digest = "MD5";
break;
case PG_SHA1:
digest = "SHA1";
break;
case PG_SHA224:
digest = "SHA224";
break;
case PG_SHA256:
digest = "SHA256";
break;
case PG_SHA384:
digest = "SHA384";
break;
case PG_SHA512:
digest = "SHA512";
break;
}
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
unconstify(char *, digest), 0);
params[1] = OSSL_PARAM_construct_end();
status = EVP_MAC_init(ctx->hmacctx, key, len, params);
#else
switch (ctx->type)
{
case PG_MD5:
@@ -196,6 +253,7 @@ pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha512(), NULL);
break;
}
#endif
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
@@ -221,7 +279,11 @@ pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
if (ctx == NULL)
return -1;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
status = EVP_MAC_update(ctx->hmacctx, data, len);
#else
status = HMAC_Update(ctx->hmacctx, data, len);
#endif
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
@@ -242,7 +304,11 @@ int
pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
{
int status = 0;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
size_t outlen;
#else
uint32 outlen;
#endif
if (ctx == NULL)
return -1;
@@ -293,7 +359,11 @@ pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
break;
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
status = EVP_MAC_final(ctx->hmacctx, dest, &outlen, len);
#else
status = HMAC_Final(ctx->hmacctx, dest, &outlen);
#endif
/* OpenSSL internals return 1 on success, 0 on failure */
if (status <= 0)
@@ -316,7 +386,13 @@ pg_hmac_free(pg_hmac_ctx *ctx)
if (ctx == NULL)
return;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_MAC_CTX_free(ctx->hmacctx);
EVP_MAC_free(ctx->mac);
#else
HMAC_CTX_free(ctx->hmacctx);
#endif
#ifdef USE_RESOWNER_FOR_HMAC
if (ctx->resowner)
ResourceOwnerForgetHMAC(ctx->resowner, ctx);