aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure2
-rw-r--r--configure.ac2
-rw-r--r--src/backend/libpq/auth-scram.c61
-rw-r--r--src/backend/utils/resowner/resowner.c61
-rw-r--r--src/common/Makefile4
-rw-r--r--src/common/hmac.c263
-rw-r--r--src/common/hmac_openssl.c256
-rw-r--r--src/common/scram-common.c158
-rw-r--r--src/include/common/hmac.h29
-rw-r--r--src/include/common/md5.h2
-rw-r--r--src/include/common/scram-common.h13
-rw-r--r--src/include/common/sha1.h2
-rw-r--r--src/include/pg_config.h.in6
-rw-r--r--src/include/utils/resowner_private.h7
-rw-r--r--src/interfaces/libpq/fe-auth-scram.c75
-rw-r--r--src/tools/msvc/Mkvcbuild.pm2
-rw-r--r--src/tools/msvc/Solution.pm4
-rw-r--r--src/tools/pgindent/typedefs.list2
18 files changed, 749 insertions, 200 deletions
diff --git a/configure b/configure
index 06ad9aeb714..70f45552643 100755
--- a/configure
+++ b/configure
@@ -12642,7 +12642,7 @@ done
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data
+ for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.ac b/configure.ac
index 92193f35fb2..ba67c95bcc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1258,7 +1258,7 @@ if test "$with_ssl" = openssl ; then
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
# functions.
- AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data])
+ AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
# OpenSSL versions before 1.1.0 required setting callback functions, for
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
# function was removed.
diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index b9b6d464a05..f9e1026a12c 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -95,6 +95,7 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_control.h"
#include "common/base64.h"
+#include "common/hmac.h"
#include "common/saslprep.h"
#include "common/scram-common.h"
#include "common/sha2.h"
@@ -1100,7 +1101,7 @@ verify_client_proof(scram_state *state)
uint8 ClientSignature[SCRAM_KEY_LEN];
uint8 ClientKey[SCRAM_KEY_LEN];
uint8 client_StoredKey[SCRAM_KEY_LEN];
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256);
int i;
/*
@@ -1108,23 +1109,25 @@ verify_client_proof(scram_state *state)
* here even when processing the calculations as this could involve a mock
* authentication.
*/
- if (scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof)) < 0 ||
- scram_HMAC_final(ClientSignature, &ctx) < 0)
+ if (pg_hmac_init(ctx, state->StoredKey, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, ClientSignature, sizeof(ClientSignature)) < 0)
{
elog(ERROR, "could not calculate client signature");
}
+ pg_hmac_free(ctx);
+
/* Extract the ClientKey that the client calculated from the proof */
for (i = 0; i < SCRAM_KEY_LEN; i++)
ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i];
@@ -1359,26 +1362,28 @@ build_server_final_message(scram_state *state)
uint8 ServerSignature[SCRAM_KEY_LEN];
char *server_signature_base64;
int siglen;
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256);
/* calculate ServerSignature */
- if (scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof)) < 0 ||
- scram_HMAC_final(ServerSignature, &ctx) < 0)
+ if (pg_hmac_init(ctx, state->ServerKey, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, ServerSignature, sizeof(ServerSignature)) < 0)
{
elog(ERROR, "could not calculate server signature");
}
+ pg_hmac_free(ctx);
+
siglen = pg_b64_enc_len(SCRAM_KEY_LEN);
/* don't forget the zero-terminator */
server_signature_base64 = palloc(siglen + 1);
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index a171df573ce..e24f00f0601 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -22,6 +22,7 @@
#include "common/cryptohash.h"
#include "common/hashfn.h"
+#include "common/hmac.h"
#include "jit/jit.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
@@ -130,6 +131,7 @@ typedef struct ResourceOwnerData
ResourceArray dsmarr; /* dynamic shmem segments */
ResourceArray jitarr; /* JIT contexts */
ResourceArray cryptohasharr; /* cryptohash contexts */
+ ResourceArray hmacarr; /* HMAC contexts */
/* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
int nlocks; /* number of owned locks */
@@ -178,6 +180,7 @@ static void PrintSnapshotLeakWarning(Snapshot snapshot);
static void PrintFileLeakWarning(File file);
static void PrintDSMLeakWarning(dsm_segment *seg);
static void PrintCryptoHashLeakWarning(Datum handle);
+static void PrintHMACLeakWarning(Datum handle);
/*****************************************************************************
@@ -448,6 +451,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name)
ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL));
ResourceArrayInit(&(owner->cryptohasharr), PointerGetDatum(NULL));
+ ResourceArrayInit(&(owner->hmacarr), PointerGetDatum(NULL));
return owner;
}
@@ -568,6 +572,16 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
PrintCryptoHashLeakWarning(foundres);
pg_cryptohash_free(context);
}
+
+ /* Ditto for HMAC contexts */
+ while (ResourceArrayGetAny(&(owner->hmacarr), &foundres))
+ {
+ pg_hmac_ctx *context = (pg_hmac_ctx *) PointerGetDatum(foundres);
+
+ if (isCommit)
+ PrintHMACLeakWarning(foundres);
+ pg_hmac_free(context);
+ }
}
else if (phase == RESOURCE_RELEASE_LOCKS)
{
@@ -737,6 +751,7 @@ ResourceOwnerDelete(ResourceOwner owner)
Assert(owner->dsmarr.nitems == 0);
Assert(owner->jitarr.nitems == 0);
Assert(owner->cryptohasharr.nitems == 0);
+ Assert(owner->hmacarr.nitems == 0);
Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
/*
@@ -765,6 +780,7 @@ ResourceOwnerDelete(ResourceOwner owner)
ResourceArrayFree(&(owner->dsmarr));
ResourceArrayFree(&(owner->jitarr));
ResourceArrayFree(&(owner->cryptohasharr));
+ ResourceArrayFree(&(owner->hmacarr));
pfree(owner);
}
@@ -1428,3 +1444,48 @@ PrintCryptoHashLeakWarning(Datum handle)
elog(WARNING, "cryptohash context reference leak: context %p still referenced",
DatumGetPointer(handle));
}
+
+/*
+ * Make sure there is room for at least one more entry in a ResourceOwner's
+ * hmac context reference array.
+ *
+ * This is separate from actually inserting an entry because if we run out of
+ * memory, it's critical to do so *before* acquiring the resource.
+ */
+void
+ResourceOwnerEnlargeHMAC(ResourceOwner owner)
+{
+ ResourceArrayEnlarge(&(owner->hmacarr));
+}
+
+/*
+ * Remember that a HMAC context is owned by a ResourceOwner
+ *
+ * Caller must have previously done ResourceOwnerEnlargeHMAC()
+ */
+void
+ResourceOwnerRememberHMAC(ResourceOwner owner, Datum handle)
+{
+ ResourceArrayAdd(&(owner->hmacarr), handle);
+}
+
+/*
+ * Forget that a HMAC context is owned by a ResourceOwner
+ */
+void
+ResourceOwnerForgetHMAC(ResourceOwner owner, Datum handle)
+{
+ if (!ResourceArrayRemove(&(owner->hmacarr), handle))
+ elog(ERROR, "HMAC context %p is not owned by resource owner %s",
+ DatumGetPointer(handle), owner->name);
+}
+
+/*
+ * Debugging subroutine
+ */
+static void
+PrintHMACLeakWarning(Datum handle)
+{
+ elog(WARNING, "HMAC context reference leak: context %p still referenced",
+ DatumGetPointer(handle));
+}
diff --git a/src/common/Makefile b/src/common/Makefile
index 5422579a6a2..38a85993370 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -83,10 +83,12 @@ OBJS_COMMON = \
ifeq ($(with_ssl),openssl)
OBJS_COMMON += \
protocol_openssl.o \
- cryptohash_openssl.o
+ cryptohash_openssl.o \
+ hmac_openssl.o
else
OBJS_COMMON += \
cryptohash.o \
+ hmac.o \
md5.o \
sha1.o \
sha2.o
diff --git a/src/common/hmac.c b/src/common/hmac.c
new file mode 100644
index 00000000000..f1b8555143a
--- /dev/null
+++ b/src/common/hmac.c
@@ -0,0 +1,263 @@
+/*-------------------------------------------------------------------------
+ *
+ * hmac.c
+ * Implements Keyed-Hashing for Message Authentication (HMAC)
+ *
+ * Fallback implementation of HMAC, as specified in RFC 2104.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/hmac.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/cryptohash.h"
+#include "common/hmac.h"
+#include "common/md5.h"
+#include "common/sha1.h"
+#include "common/sha2.h"
+
+/*
+ * In backend, use palloc/pfree to ease the error handling. In frontend,
+ * use malloc to be able to return a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#define ALLOC(size) palloc(size)
+#define FREE(ptr) pfree(ptr)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif
+
+/*
+ * Internal structure for pg_hmac_ctx->data with this implementation.
+ */
+struct pg_hmac_ctx
+{
+ pg_cryptohash_ctx *hash;
+ pg_cryptohash_type type;
+ int block_size;
+ int digest_size;
+
+ /*
+ * Use the largest block size among supported options. This wastes some
+ * memory but simplifies the allocation logic.
+ */
+ uint8 k_ipad[PG_SHA512_BLOCK_LENGTH];
+ uint8 k_opad[PG_SHA512_BLOCK_LENGTH];
+};
+
+#define HMAC_IPAD 0x36
+#define HMAC_OPAD 0x5C
+
+/*
+ * pg_hmac_create
+ *
+ * Allocate a hash context. Returns NULL on failure for an OOM. The
+ * backend issues an error, without returning.
+ */
+pg_hmac_ctx *
+pg_hmac_create(pg_cryptohash_type type)
+{
+ pg_hmac_ctx *ctx;
+
+ ctx = ALLOC(sizeof(pg_hmac_ctx));
+ if (ctx == NULL)
+ return NULL;
+ memset(ctx, 0, sizeof(pg_hmac_ctx));
+ ctx->type = type;
+
+ /*
+ * Initialize the context data. This requires to know the digest and
+ * block lengths, that depend on the type of hash used.
+ */
+ switch (type)
+ {
+ case PG_MD5:
+ ctx->digest_size = MD5_DIGEST_LENGTH;
+ ctx->block_size = MD5_BLOCK_SIZE;
+ break;
+ case PG_SHA1:
+ ctx->digest_size = SHA1_DIGEST_LENGTH;
+ ctx->block_size = SHA1_BLOCK_SIZE;
+ break;
+ case PG_SHA224:
+ ctx->digest_size = PG_SHA224_DIGEST_LENGTH;
+ ctx->block_size = PG_SHA224_BLOCK_LENGTH;
+ break;
+ case PG_SHA256:
+ ctx->digest_size = PG_SHA256_DIGEST_LENGTH;
+ ctx->block_size = PG_SHA256_BLOCK_LENGTH;
+ break;
+ case PG_SHA384:
+ ctx->digest_size = PG_SHA384_DIGEST_LENGTH;
+ ctx->block_size = PG_SHA384_BLOCK_LENGTH;
+ break;
+ case PG_SHA512:
+ ctx->digest_size = PG_SHA512_DIGEST_LENGTH;
+ ctx->block_size = PG_SHA512_BLOCK_LENGTH;
+ break;
+ }
+
+ ctx->hash = pg_cryptohash_create(type);
+ if (ctx->hash == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+/*
+ * pg_hmac_init
+ *
+ * Initialize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
+{
+ int i;
+ int digest_size;
+ int block_size;
+ uint8 *shrinkbuf = NULL;
+
+ if (ctx == NULL)
+ return -1;
+
+ digest_size = ctx->digest_size;
+ block_size = ctx->block_size;
+
+ memset(ctx->k_opad, HMAC_OPAD, ctx->block_size);
+ memset(ctx->k_ipad, HMAC_IPAD, ctx->block_size);
+
+ /*
+ * If the key is longer than the block size, pass it through the hash once
+ * to shrink it down.
+ */
+ if (len > block_size)
+ {
+ pg_cryptohash_ctx *hash_ctx;
+
+ /* temporary buffer for one-time shrink */
+ shrinkbuf = ALLOC(digest_size);
+ if (shrinkbuf == NULL)
+ return -1;
+ memset(shrinkbuf, 0, digest_size);
+
+ hash_ctx = pg_cryptohash_create(ctx->type);
+ if (hash_ctx == NULL)
+ {
+ FREE(shrinkbuf);
+ return -1;
+ }
+
+ if (pg_cryptohash_init(hash_ctx) < 0 ||
+ pg_cryptohash_update(hash_ctx, key, len) < 0 ||
+ pg_cryptohash_final(hash_ctx, shrinkbuf, digest_size) < 0)
+ {
+ pg_cryptohash_free(hash_ctx);
+ FREE(shrinkbuf);
+ return -1;
+ }
+
+ key = shrinkbuf;
+ len = digest_size;
+ pg_cryptohash_free(hash_ctx);
+ }
+
+ for (i = 0; i < len; i++)
+ {
+ ctx->k_ipad[i] ^= key[i];
+ ctx->k_opad[i] ^= key[i];
+ }
+
+ /* tmp = H(K XOR ipad, text) */
+ if (pg_cryptohash_init(ctx->hash) < 0 ||
+ pg_cryptohash_update(ctx->hash, ctx->k_ipad, ctx->block_size) < 0)
+ {
+ if (shrinkbuf)
+ FREE(shrinkbuf);
+ return -1;
+ }
+
+ if (shrinkbuf)
+ FREE(shrinkbuf);
+ return 0;
+}
+
+/*
+ * pg_hmac_update
+ *
+ * Update a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
+{
+ if (ctx == NULL)
+ return -1;
+
+ if (pg_cryptohash_update(ctx->hash, data, len) < 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * pg_hmac_final
+ *
+ * Finalize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
+{
+ uint8 *h;
+
+ if (ctx == NULL)
+ return -1;
+
+ h = ALLOC(ctx->digest_size);
+ if (h == NULL)
+ return -1;
+ memset(h, 0, ctx->digest_size);
+
+ if (pg_cryptohash_final(ctx->hash, h, ctx->digest_size) < 0)
+ return -1;
+
+ /* H(K XOR opad, tmp) */
+ if (pg_cryptohash_init(ctx->hash) < 0 ||
+ pg_cryptohash_update(ctx->hash, ctx->k_opad, ctx->block_size) < 0 ||
+ pg_cryptohash_update(ctx->hash, h, ctx->digest_size) < 0 ||
+ pg_cryptohash_final(ctx->hash, dest, len) < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * pg_hmac_free
+ *
+ * Free a HMAC context.
+ */
+void
+pg_hmac_free(pg_hmac_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ pg_cryptohash_free(ctx->hash);
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+}
diff --git a/src/common/hmac_openssl.c b/src/common/hmac_openssl.c
new file mode 100644
index 00000000000..b5e3065d1a9
--- /dev/null
+++ b/src/common/hmac_openssl.c
@@ -0,0 +1,256 @@
+/*-------------------------------------------------------------------------
+ *
+ * hmac_openssl.c
+ * Implementation of HMAC with OpenSSL.
+ *
+ * This should only be used if code is compiled with OpenSSL support.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/hmac_openssl.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include <openssl/hmac.h>
+
+#include "common/hmac.h"
+#include "common/md5.h"
+#include "common/sha1.h"
+#include "common/sha2.h"
+#ifndef FRONTEND
+#include "utils/memutils.h"
+#include "utils/resowner.h"
+#include "utils/resowner_private.h"
+#endif
+
+/*
+ * In backend, use an allocation in TopMemoryContext to count for resowner
+ * cleanup handling if necesary. For versions of OpenSSL where HMAC_CTX is
+ * known, just use palloc(). In frontend, use malloc to be able to return
+ * a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#ifdef HAVE_HMAC_CTX_NEW
+#define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
+#else
+#define ALLOC(size) palloc(size)
+#endif
+#define FREE(ptr) pfree(ptr)
+#else /* FRONTEND */
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif /* FRONTEND */
+
+/*
+ * Internal structure for pg_hmac_ctx->data with this implementation.
+ */
+struct pg_hmac_ctx
+{
+ HMAC_CTX *hmacctx;
+ pg_cryptohash_type type;
+
+#ifndef FRONTEND
+ ResourceOwner resowner;
+#endif
+};
+
+/*
+ * pg_hmac_create
+ *
+ * Allocate a hash context. Returns NULL on failure for an OOM. The
+ * backend issues an error, without returning.
+ */
+pg_hmac_ctx *
+pg_hmac_create(pg_cryptohash_type type)
+{
+ pg_hmac_ctx *ctx;
+
+ ctx = ALLOC(sizeof(pg_hmac_ctx));
+ if (ctx == NULL)
+ return NULL;
+ memset(ctx, 0, sizeof(pg_hmac_ctx));
+
+ ctx->type = type;
+
+ /*
+ * Initialization takes care of assigning the correct type for OpenSSL.
+ */
+#ifdef HAVE_HMAC_CTX_NEW
+#ifndef FRONTEND
+ ResourceOwnerEnlargeHMAC(CurrentResourceOwner);
+#endif
+ ctx->hmacctx = HMAC_CTX_new();
+#else
+ ctx->hmacctx = ALLOC(sizeof(HMAC_CTX));
+#endif
+
+ if (ctx->hmacctx == NULL)
+ {
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#endif
+ return NULL;
+ }
+
+#ifdef HAVE_HMAC_CTX_NEW
+#ifndef FRONTEND
+ ctx->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberHMAC(CurrentResourceOwner, PointerGetDatum(ctx));
+#endif
+#else
+ memset(ctx->hmacctx, 0, sizeof(HMAC_CTX));
+#endif /* HAVE_HMAC_CTX_NEW */
+
+ return ctx;
+}
+
+/*
+ * pg_hmac_init
+ *
+ * Initialize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_md5(), NULL);
+ break;
+ case PG_SHA1:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha1(), NULL);
+ break;
+ case PG_SHA224:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha224(), NULL);
+ break;
+ case PG_SHA256:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha256(), NULL);
+ break;
+ case PG_SHA384:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha384(), NULL);
+ break;
+ case PG_SHA512:
+ status = HMAC_Init_ex(ctx->hmacctx, key, len, EVP_sha512(), NULL);
+ break;
+ }
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * pg_hmac_update
+ *
+ * Update a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
+{
+ int status = 0;
+
+ if (ctx == NULL)
+ return -1;
+
+ status = HMAC_Update(ctx->hmacctx, data, len);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * pg_hmac_final
+ *
+ * Finalize a HMAC context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
+{
+ int status = 0;
+ uint32 outlen;
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (ctx->type)
+ {
+ case PG_MD5:
+ if (len < MD5_DIGEST_LENGTH)
+ return -1;
+ break;
+ case PG_SHA1:
+ if (len < SHA1_DIGEST_LENGTH)
+ return -1;
+ break;
+ case PG_SHA224:
+ if (len < PG_SHA224_DIGEST_LENGTH)
+ return -1;
+ break;
+ case PG_SHA256:
+ if (len < PG_SHA256_DIGEST_LENGTH)
+ return -1;
+ break;
+ case PG_SHA384:
+ if (len < PG_SHA384_DIGEST_LENGTH)
+ return -1;
+ break;
+ case PG_SHA512:
+ if (len < PG_SHA512_DIGEST_LENGTH)
+ return -1;
+ break;
+ }
+
+ status = HMAC_Final(ctx->hmacctx, dest, &outlen);
+
+ /* OpenSSL internals return 1 on success, 0 on failure */
+ if (status <= 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * pg_hmac_free
+ *
+ * Free a HMAC context.
+ */
+void
+pg_hmac_free(pg_hmac_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+#ifdef HAVE_HMAC_CTX_FREE
+ HMAC_CTX_free(ctx->hmacctx);
+#ifndef FRONTEND
+ ResourceOwnerForgetHMAC(ctx->resowner, PointerGetDatum(ctx));
+#endif
+#else
+ explicit_bzero(ctx->hmacctx, sizeof(HMAC_CTX));
+ FREE(ctx->hmacctx);
+#endif
+
+ explicit_bzero(ctx, sizeof(pg_hmac_ctx));
+ FREE(ctx);
+}
diff --git a/src/common/scram-common.c b/src/common/scram-common.c
index 0b9557376e9..69a96f65f65 100644
--- a/src/common/scram-common.c
+++ b/src/common/scram-common.c
@@ -20,118 +20,10 @@
#endif
#include "common/base64.h"
+#include "common/hmac.h"
#include "common/scram-common.h"
#include "port/pg_bswap.h"
-#define HMAC_IPAD 0x36
-#define HMAC_OPAD 0x5C
-
-/*
- * Calculate HMAC per RFC2104.
- *
- * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
- */
-int
-scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
-{
- uint8 k_ipad[SHA256_HMAC_B];
- int i;
- uint8 keybuf[SCRAM_KEY_LEN];
-
- /*
- * If the key is longer than the block size (64 bytes for SHA-256), pass
- * it through SHA-256 once to shrink it down.
- */
- if (keylen > SHA256_HMAC_B)
- {
- pg_cryptohash_ctx *sha256_ctx;
-
- sha256_ctx = pg_cryptohash_create(PG_SHA256);
- if (sha256_ctx == NULL)
- return -1;
- if (pg_cryptohash_init(sha256_ctx) < 0 ||
- pg_cryptohash_update(sha256_ctx, key, keylen) < 0 ||
- pg_cryptohash_final(sha256_ctx, keybuf, sizeof(keybuf)) < 0)
- {
- pg_cryptohash_free(sha256_ctx);
- return -1;
- }
- key = keybuf;
- keylen = SCRAM_KEY_LEN;
- pg_cryptohash_free(sha256_ctx);
- }
-
- memset(k_ipad, HMAC_IPAD, SHA256_HMAC_B);
- memset(ctx->k_opad, HMAC_OPAD, SHA256_HMAC_B);
-
- for (i = 0; i < keylen; i++)
- {
- k_ipad[i] ^= key[i];
- ctx->k_opad[i] ^= key[i];
- }
-
- ctx->sha256ctx = pg_cryptohash_create(PG_SHA256);
- if (ctx->sha256ctx == NULL)
- return -1;
-
- /* tmp = H(K XOR ipad, text) */
- if (pg_cryptohash_init(ctx->sha256ctx) < 0 ||
- pg_cryptohash_update(ctx->sha256ctx, k_ipad, SHA256_HMAC_B) < 0)
- {
- pg_cryptohash_free(ctx->sha256ctx);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Update HMAC calculation
- * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
- */
-int
-scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen)
-{
- Assert(ctx->sha256ctx != NULL);
- if (pg_cryptohash_update(ctx->sha256ctx, (const uint8 *) str, slen) < 0)
- {
- pg_cryptohash_free(ctx->sha256ctx);
- return -1;
- }
- return 0;
-}
-
-/*
- * Finalize HMAC calculation.
- * The hash function used is SHA-256. Returns 0 on success, -1 on failure.
- */
-int
-scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx)
-{
- uint8 h[SCRAM_KEY_LEN];
-
- Assert(ctx->sha256ctx != NULL);
-
- if (pg_cryptohash_final(ctx->sha256ctx, h, sizeof(h)) < 0)
- {
- pg_cryptohash_free(ctx->sha256ctx);
- return -1;
- }
-
- /* H(K XOR opad, tmp) */
- if (pg_cryptohash_init(ctx->sha256ctx) < 0 ||
- pg_cryptohash_update(ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B) < 0 ||
- pg_cryptohash_update(ctx->sha256ctx, h, SCRAM_KEY_LEN) < 0 ||
- pg_cryptohash_final(ctx->sha256ctx, result, SCRAM_KEY_LEN) < 0)
- {
- pg_cryptohash_free(ctx->sha256ctx);
- return -1;
- }
-
- pg_cryptohash_free(ctx->sha256ctx);
- return 0;
-}
-
/*
* Calculate SaltedPassword.
*
@@ -149,7 +41,10 @@ scram_SaltedPassword(const char *password,
j;
uint8 Ui[SCRAM_KEY_LEN];
uint8 Ui_prev[SCRAM_KEY_LEN];
- scram_HMAC_ctx hmac_ctx;
+ pg_hmac_ctx *hmac_ctx = pg_hmac_create(PG_SHA256);
+
+ if (hmac_ctx == NULL)
+ return -1;
/*
* Iterate hash calculation of HMAC entry using given salt. This is
@@ -158,11 +53,12 @@ scram_SaltedPassword(const char *password,
*/
/* First iteration */
- if (scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len) < 0 ||
- scram_HMAC_update(&hmac_ctx, salt, saltlen) < 0 ||
- scram_HMAC_update(&hmac_ctx, (char *) &one, sizeof(uint32)) < 0 ||
- scram_HMAC_final(Ui_prev, &hmac_ctx) < 0)
+ if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) salt, saltlen) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) &one, sizeof(uint32)) < 0 ||
+ pg_hmac_final(hmac_ctx, Ui_prev, sizeof(Ui_prev)) < 0)
{
+ pg_hmac_free(hmac_ctx);
return -1;
}
@@ -171,10 +67,11 @@ scram_SaltedPassword(const char *password,
/* Subsequent iterations */
for (i = 2; i <= iterations; i++)
{
- if (scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len) < 0 ||
- scram_HMAC_update(&hmac_ctx, (const char *) Ui_prev, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_final(Ui, &hmac_ctx) < 0)
+ if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
+ pg_hmac_update(hmac_ctx, (uint8 *) Ui_prev, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_final(hmac_ctx, Ui, sizeof(Ui)) < 0)
{
+ pg_hmac_free(hmac_ctx);
return -1;
}
@@ -183,6 +80,7 @@ scram_SaltedPassword(const char *password,
memcpy(Ui_prev, Ui, SCRAM_KEY_LEN);
}
+ pg_hmac_free(hmac_ctx);
return 0;
}
@@ -218,15 +116,20 @@ scram_H(const uint8 *input, int len, uint8 *result)
int
scram_ClientKey(const uint8 *salted_password, uint8 *result)
{
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256);
+
+ if (ctx == NULL)
+ return -1;
- if (scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx, "Client Key", strlen("Client Key")) < 0 ||
- scram_HMAC_final(result, &ctx) < 0)
+ if (pg_hmac_init(ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) "Client Key", strlen("Client Key")) < 0 ||
+ pg_hmac_final(ctx, result, SCRAM_KEY_LEN) < 0)
{
+ pg_hmac_free(ctx);
return -1;
}
+ pg_hmac_free(ctx);
return 0;
}
@@ -236,15 +139,20 @@ scram_ClientKey(const uint8 *salted_password, uint8 *result)
int
scram_ServerKey(const uint8 *salted_password, uint8 *result)
{
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx = pg_hmac_create(PG_SHA256);
+
+ if (ctx == NULL)
+ return -1;
- if (scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx, "Server Key", strlen("Server Key")) < 0 ||
- scram_HMAC_final(result, &ctx) < 0)
+ if (pg_hmac_init(ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) "Server Key", strlen("Server Key")) < 0 ||
+ pg_hmac_final(ctx, result, SCRAM_KEY_LEN) < 0)
{
+ pg_hmac_free(ctx);
return -1;
}
+ pg_hmac_free(ctx);
return 0;
}
diff --git a/src/include/common/hmac.h b/src/include/common/hmac.h
new file mode 100644
index 00000000000..ea0343a9da7
--- /dev/null
+++ b/src/include/common/hmac.h
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * hmac.h
+ * Generic headers for HMAC
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/common/hmac.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef PG_HMAC_H
+#define PG_HMAC_H
+
+#include "common/cryptohash.h"
+
+/* opaque context, private to each HMAC implementation */
+typedef struct pg_hmac_ctx pg_hmac_ctx;
+
+extern pg_hmac_ctx *pg_hmac_create(pg_cryptohash_type type);
+extern int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len);
+extern int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len);
+extern int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len);
+extern void pg_hmac_free(pg_hmac_ctx *ctx);
+
+#endif /* PG_HMAC_H */
diff --git a/src/include/common/md5.h b/src/include/common/md5.h
index 6d100f5cfc2..62a31e6ed4e 100644
--- a/src/include/common/md5.h
+++ b/src/include/common/md5.h
@@ -18,6 +18,8 @@
/* Size of result generated by MD5 computation */
#define MD5_DIGEST_LENGTH 16
+/* Block size for MD5 */
+#define MD5_BLOCK_SIZE 64
/* password-related data */
#define MD5_PASSWD_CHARSET "0123456789abcdef"
diff --git a/src/include/common/scram-common.h b/src/include/common/scram-common.h
index 9d684b41e8e..5777ce9fe33 100644
--- a/src/include/common/scram-common.h
+++ b/src/include/common/scram-common.h
@@ -46,19 +46,6 @@
*/
#define SCRAM_DEFAULT_ITERATIONS 4096
-/*
- * Context data for HMAC used in SCRAM authentication.
- */
-typedef struct
-{
- pg_cryptohash_ctx *sha256ctx;
- uint8 k_opad[SHA256_HMAC_B];
-} scram_HMAC_ctx;
-
-extern int scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen);
-extern int scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen);
-extern int scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx);
-
extern int scram_SaltedPassword(const char *password, const char *salt,
int saltlen, int iterations, uint8 *result);
extern int scram_H(const uint8 *str, int len, uint8 *result);
diff --git a/src/include/common/sha1.h b/src/include/common/sha1.h
index a61bc47deda..b1ee36f8eaf 100644
--- a/src/include/common/sha1.h
+++ b/src/include/common/sha1.h
@@ -15,5 +15,7 @@
/* Size of result generated by SHA1 computation */
#define SHA1_DIGEST_LENGTH 20
+/* Block size for SHA1 */
+#define SHA1_BLOCK_SIZE 64
#endif /* PG_SHA1_H */
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 5e2255a2f53..783b8fc1ba7 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -268,6 +268,12 @@
/* Define to 1 if you have the `history_truncate_file' function. */
#undef HAVE_HISTORY_TRUNCATE_FILE
+/* Define to 1 if you have the `HMAC_CTX_free' function. */
+#undef HAVE_HMAC_CTX_FREE
+
+/* Define to 1 if you have the `HMAC_CTX_new' function. */
+#undef HAVE_HMAC_CTX_NEW
+
/* Define to 1 if you have the <ifaddrs.h> header file. */
#undef HAVE_IFADDRS_H
diff --git a/src/include/utils/resowner_private.h b/src/include/utils/resowner_private.h
index c480a1a24be..6dafc87e28c 100644
--- a/src/include/utils/resowner_private.h
+++ b/src/include/utils/resowner_private.h
@@ -102,4 +102,11 @@ extern void ResourceOwnerRememberCryptoHash(ResourceOwner owner,
extern void ResourceOwnerForgetCryptoHash(ResourceOwner owner,
Datum handle);
+/* support for HMAC context management */
+extern void ResourceOwnerEnlargeHMAC(ResourceOwner owner);
+extern void ResourceOwnerRememberHMAC(ResourceOwner owner,
+ Datum handle);
+extern void ResourceOwnerForgetHMAC(ResourceOwner owner,
+ Datum handle);
+
#endif /* RESOWNER_PRIVATE_H */
diff --git a/src/interfaces/libpq/fe-auth-scram.c b/src/interfaces/libpq/fe-auth-scram.c
index 002469540a9..5881386e374 100644
--- a/src/interfaces/libpq/fe-auth-scram.c
+++ b/src/interfaces/libpq/fe-auth-scram.c
@@ -15,6 +15,7 @@
#include "postgres_fe.h"
#include "common/base64.h"
+#include "common/hmac.h"
#include "common/saslprep.h"
#include "common/scram-common.h"
#include "fe-auth.h"
@@ -776,7 +777,11 @@ calculate_client_proof(fe_scram_state *state,
uint8 ClientKey[SCRAM_KEY_LEN];
uint8 ClientSignature[SCRAM_KEY_LEN];
int i;
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx;
+
+ ctx = pg_hmac_create(PG_SHA256);
+ if (ctx == NULL)
+ return false;
/*
* Calculate SaltedPassword, and store it in 'state' so that we can reuse
@@ -786,26 +791,28 @@ calculate_client_proof(fe_scram_state *state,
state->iterations, state->SaltedPassword) < 0 ||
scram_ClientKey(state->SaltedPassword, ClientKey) < 0 ||
scram_H(ClientKey, SCRAM_KEY_LEN, StoredKey) < 0 ||
- scram_HMAC_init(&ctx, StoredKey, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- client_final_message_without_proof,
- strlen(client_final_message_without_proof)) < 0 ||
- scram_HMAC_final(ClientSignature, &ctx) < 0)
- {
+ pg_hmac_init(ctx, StoredKey, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) client_final_message_without_proof,
+ strlen(client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, ClientSignature, sizeof(ClientSignature)) < 0)
+ {
+ pg_hmac_free(ctx);
return false;
}
for (i = 0; i < SCRAM_KEY_LEN; i++)
result[i] = ClientKey[i] ^ ClientSignature[i];
+ pg_hmac_free(ctx);
return true;
}
@@ -820,27 +827,35 @@ verify_server_signature(fe_scram_state *state, bool *match)
{
uint8 expected_ServerSignature[SCRAM_KEY_LEN];
uint8 ServerKey[SCRAM_KEY_LEN];
- scram_HMAC_ctx ctx;
+ pg_hmac_ctx *ctx;
+
+ ctx = pg_hmac_create(PG_SHA256);
+ if (ctx == NULL)
+ return false;
if (scram_ServerKey(state->SaltedPassword, ServerKey) < 0 ||
/* calculate ServerSignature */
- scram_HMAC_init(&ctx, ServerKey, SCRAM_KEY_LEN) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_first_message_bare,
- strlen(state->client_first_message_bare)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->server_first_message,
- strlen(state->server_first_message)) < 0 ||
- scram_HMAC_update(&ctx, ",", 1) < 0 ||
- scram_HMAC_update(&ctx,
- state->client_final_message_without_proof,
- strlen(state->client_final_message_without_proof)) < 0 ||
- scram_HMAC_final(expected_ServerSignature, &ctx) < 0)
- {
+ pg_hmac_init(ctx, ServerKey, SCRAM_KEY_LEN) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_first_message_bare,
+ strlen(state->client_first_message_bare)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->server_first_message,
+ strlen(state->server_first_message)) < 0 ||
+ pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
+ pg_hmac_update(ctx,
+ (uint8 *) state->client_final_message_without_proof,
+ strlen(state->client_final_message_without_proof)) < 0 ||
+ pg_hmac_final(ctx, expected_ServerSignature,
+ sizeof(expected_ServerSignature)) < 0)
+ {
+ pg_hmac_free(ctx);
return false;
}
+ pg_hmac_free(ctx);
+
/* signature processed, so now check after it */
if (memcmp(expected_ServerSignature, state->ServerSignature, SCRAM_KEY_LEN) != 0)
*match = false;
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index bc651851307..58a99e4f104 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -132,11 +132,13 @@ sub mkvcbuild
if ($solution->{options}->{openssl})
{
push(@pgcommonallfiles, 'cryptohash_openssl.c');
+ push(@pgcommonallfiles, 'hmac_openssl.c');
push(@pgcommonallfiles, 'protocol_openssl.c');
}
else
{
push(@pgcommonallfiles, 'cryptohash.c');
+ push(@pgcommonallfiles, 'hmac.c');
push(@pgcommonallfiles, 'md5.c');
push(@pgcommonallfiles, 'sha1.c');
push(@pgcommonallfiles, 'sha2.c');
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 710f26f8ab3..d2bc7abef0d 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -279,6 +279,8 @@ sub GenerateFiles
HAVE_GETTIMEOFDAY => undef,
HAVE_GSSAPI_GSSAPI_H => undef,
HAVE_GSSAPI_H => undef,
+ HAVE_HMAC_CTX_FREE => undef,
+ HAVE_HMAC_CTX_NEW => undef,
HAVE_HISTORY_H => undef,
HAVE_HISTORY_TRUNCATE_FILE => undef,
HAVE_IFADDRS_H => undef,
@@ -542,6 +544,8 @@ sub GenerateFiles
$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
$define{HAVE_BIO_GET_DATA} = 1;
$define{HAVE_BIO_METH_NEW} = 1;
+ $define{HAVE_HMAC_CTX_FREE} = 1;
+ $define{HAVE_HMAC_CTX_NEW} = 1;
$define{HAVE_OPENSSL_INIT_SSL} = 1;
}
}
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 9e6777e9d07..6a98064b2bd 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3215,6 +3215,7 @@ pg_enc2gettext
pg_enc2name
pg_encname
pg_gssinfo
+pg_hmac_ctx
pg_int64
pg_local_to_utf_combined
pg_locale_t
@@ -3361,7 +3362,6 @@ role_auth_extra
row_security_policy_hook_type
rsv_callback
save_buffer
-scram_HMAC_ctx
scram_state
scram_state_enum
sem_t