1/*-------------------------------------------------------------------------
4 * Implementation of HMAC with OpenSSL.
6 * This should only be used if code is compiled with OpenSSL support.
8 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/common/hmac_openssl.c
14 *-------------------------------------------------------------------------
24#include <openssl/err.h>
25#include <openssl/hmac.h>
37 * In backend, use an allocation in TopMemoryContext to count for resowner
38 * cleanup handling if necessary. In frontend, use malloc to be able to return
39 * a failure status back to the caller.
42 #define USE_RESOWNER_FOR_HMAC
43 #define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
44 #define FREE(ptr) pfree(ptr)
46#define ALLOC(size) malloc(size)
47#define FREE(ptr) free(ptr)
50/* Set of error states */
58/* Internal pg_hmac_ctx structure */
66#ifdef USE_RESOWNER_FOR_HMAC
71/* ResourceOwner callbacks to hold HMAC contexts */
72#ifdef USE_RESOWNER_FOR_HMAC
77 .
name =
"OpenSSL HMAC context",
81 .DebugPrint = NULL
/* the default message is fine */
84/* Convenience wrappers over ResourceOwnerRemember/Forget */
104 * This may return NULL, but we would fall back to a default error path if
105 * that were the case.
107 return ERR_reason_error_string(ecode);
113 * Allocate a hash context. Returns NULL on failure for an OOM. The
114 * backend issues an error, without returning.
132 * Initialization takes care of assigning the correct type for OpenSSL.
133 * Also ensure that there aren't any unconsumed errors in the queue from
138#ifdef USE_RESOWNER_FOR_HMAC
150 (
errcode(ERRCODE_OUT_OF_MEMORY),
151 errmsg(
"out of memory")));
157#ifdef USE_RESOWNER_FOR_HMAC
168 * Initialize a HMAC context. Returns 0 on success, -1 on failure.
181 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_md5(), NULL);
184 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_sha1(), NULL);
187 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_sha224(), NULL);
190 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_sha256(), NULL);
193 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_sha384(), NULL);
196 status = HMAC_Init_ex(ctx->
hmacctx,
key,
len, EVP_sha512(), NULL);
200 /* OpenSSL internals return 1 on success, 0 on failure */
214 * Update a HMAC context. Returns 0 on success, -1 on failure.
226 /* OpenSSL internals return 1 on success, 0 on failure */
239 * Finalize a HMAC context. Returns 0 on success, -1 on failure.
298 /* OpenSSL internals return 1 on success, 0 on failure */
311 * Free a HMAC context.
320#ifdef USE_RESOWNER_FOR_HMAC
332 * Returns a static string providing details about an error that happened
333 * during a HMAC computation.
339 return _(
"out of memory");
342 * If a reason is provided, rely on it, else fallback to any error code
353 return _(
"destination buffer too small");
355 return _(
"OpenSSL failure");
358 Assert(
false);
/* cannot be reached */
362/* ResourceOwner callbacks */
364#ifdef USE_RESOWNER_FOR_HMAC
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
static void ResOwnerReleaseHMAC(Datum res)
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
static const ResourceOwnerDesc hmac_resowner_desc
static void ResourceOwnerForgetHMAC(ResourceOwner owner, pg_hmac_ctx *ctx)
static const char * SSLerrmessage(unsigned long ecode)
static void ResourceOwnerRememberHMAC(ResourceOwner owner, pg_hmac_ctx *ctx)
void pg_hmac_free(pg_hmac_ctx *ctx)
const char * pg_hmac_error(pg_hmac_ctx *ctx)
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
#define MD5_DIGEST_LENGTH
void explicit_bzero(void *buf, size_t len)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
ResourceOwner CurrentResourceOwner
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerEnlarge(ResourceOwner owner)
#define RELEASE_PRIO_HMAC_CONTEXTS
@ RESOURCE_RELEASE_BEFORE_LOCKS
#define SHA1_DIGEST_LENGTH
#define PG_SHA256_DIGEST_LENGTH
#define PG_SHA384_DIGEST_LENGTH
#define PG_SHA512_DIGEST_LENGTH
#define PG_SHA224_DIGEST_LENGTH