v23-0007-NSS-cryptohash-support.patch
application/octet-stream
Filename: v23-0007-NSS-cryptohash-support.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch v23-0007
Subject: NSS cryptohash support
| File | + | − |
|---|---|---|
| src/common/cryptohash_nss.c | 258 | 0 |
| src/tools/msvc/Mkvcbuild.pm | 4 | 0 |
From 313148be7d99d8ad7c0bf97abd9c6bee37169422 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Mon, 18 Jan 2021 13:04:49 +0100
Subject: [PATCH v23 7/8] NSS cryptohash support
---
src/common/cryptohash_nss.c | 258 ++++++++++++++++++++++++++++++++++++
src/tools/msvc/Mkvcbuild.pm | 4 +
2 files changed, 262 insertions(+)
create mode 100644 src/common/cryptohash_nss.c
diff --git a/src/common/cryptohash_nss.c b/src/common/cryptohash_nss.c
new file mode 100644
index 0000000000..d4fd2e0008
--- /dev/null
+++ b/src/common/cryptohash_nss.c
@@ -0,0 +1,258 @@
+/*-------------------------------------------------------------------------
+ *
+ * cryptohash_nss.c
+ * Set of wrapper routines on top of NSS to support cryptographic
+ * hash functions.
+ *
+ * This should only be used if code is compiled with NSS support.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/common/cryptohash_nss.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+/*
+ * BITS_PER_BYTE is also defined in the NSPR header files, so we need to undef
+ * our version to avoid compiler warnings on redefinition.
+ */
+#define pg_BITS_PER_BYTE BITS_PER_BYTE
+#undef BITS_PER_BYTE
+
+#include <nss/nss.h>
+#include <nss/hasht.h>
+#include <nss/pk11func.h>
+#include <nss/pk11pub.h>
+#include <nss/secitem.h>
+#include <nss/sechash.h>
+#include <nss/secoid.h>
+#include <nss/secerr.h>
+
+/*
+ * Ensure that the colliding definitions match, else throw an error. In case
+ * NSPR has removed the definition for some reason, make sure to put ours
+ * back again.
+ */
+#if defined(BITS_PER_BYTE)
+#if BITS_PER_BYTE != pg_BITS_PER_BYTE
+#error "incompatible byte widths between NSPR and postgres"
+#endif
+#else
+#define BITS_PER_BYTE pg_BITS_PER_BYTE
+#endif
+#undef pg_BITS_PER_BYTE
+
+#include "common/cryptohash.h"
+#ifndef FRONTEND
+#include "utils/memutils.h"
+#include "utils/resowner.h"
+#include "utils/resowner_private.h"
+#endif
+
+/*
+ * In the backend, use an allocation in TopMemoryContext to count for
+ * resowner cleanup handling. In the frontend, use malloc to be able
+ * to return a failure status back to the caller.
+ */
+#ifndef FRONTEND
+#define ALLOC(size) MemoryContextAlloc(TopMemoryContext, size)
+#define FREE(ptr) pfree(ptr)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(ptr) free(ptr)
+#endif
+
+/*
+ * Internal pg_cryptohash_ctx structure.
+ */
+struct pg_cryptohash_ctx
+{
+ pg_cryptohash_type type;
+
+ NSSInitContext *nss_context;
+ PK11Context *pk11_context;
+ HASH_HashType hash_type;
+
+#ifndef FRONTEND
+ ResourceOwner resowner;
+#endif
+};
+
+/*
+ * pg_cryptohash_create
+ *
+ * Create and allocate a new hash context. Returns NULL on failure in the
+ * frontend, and raise error without returning in the backend.
+ */
+pg_cryptohash_ctx *
+pg_cryptohash_create(pg_cryptohash_type type)
+{
+ NSSInitParameters params;
+ pg_cryptohash_ctx *ctx;
+ SECOidData *hash;
+
+#ifndef FRONTEND
+ /*
+ * Make sure that the resource owner has space to remember this reference.
+ * This can error out with "out of memory", so do this before any other
+ * allocation to avoid leaking.
+ */
+ ResourceOwnerEnlargeCryptoHash(CurrentResourceOwner);
+#endif
+
+ ctx = ALLOC(sizeof(pg_cryptohash_ctx));
+
+ if (!ctx)
+ goto error;
+
+ switch(type)
+ {
+ case PG_SHA1:
+ ctx->hash_type = SEC_OID_SHA1;
+ break;
+ case PG_MD5:
+ ctx->hash_type = SEC_OID_MD5;
+ break;
+ case PG_SHA224:
+ ctx->hash_type = SEC_OID_SHA224;
+ break;
+ case PG_SHA256:
+ ctx->hash_type = SEC_OID_SHA256;
+ break;
+ case PG_SHA384:
+ ctx->hash_type = SEC_OID_SHA384;
+ break;
+ case PG_SHA512:
+ ctx->hash_type = SEC_OID_SHA512;
+ break;
+ }
+
+ /*
+ * Initialize our own NSS context without a database backing it.
+ */
+ memset(¶ms, 0, sizeof(params));
+ params.length = sizeof(params);
+ ctx->nss_context = NSS_InitContext("", "", "", "", ¶ms,
+ NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
+ NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
+ NSS_INIT_NOROOTINIT | NSS_INIT_PK11RELOAD);
+ if (!ctx->nss_context)
+ {
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+ goto error;
+ }
+ ctx->type = type;
+ hash = SECOID_FindOIDByTag(ctx->hash_type);
+ ctx->pk11_context = PK11_CreateDigestContext(hash->offset);
+ if (!ctx->pk11_context)
+ {
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+ goto error;
+ }
+
+#ifndef FRONTEND
+ ctx->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberCryptoHash(CurrentResourceOwner,
+ PointerGetDatum(ctx));
+#endif
+
+ return ctx;
+
+error:
+#ifndef FRONTEND
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+#endif
+ return NULL;
+}
+
+/*
+ * pg_cryptohash_init
+ * Initialize the passed hash context
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+pg_cryptohash_init(pg_cryptohash_ctx *ctx)
+{
+ SECStatus status;
+
+ status = PK11_DigestBegin(ctx->pk11_context);
+
+ if (status != SECSuccess)
+ return -1;
+ return 0;
+}
+
+/*
+ * pg_cryptohash_update
+ *
+ * Update a hash context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
+{
+ SECStatus status;
+
+ if (ctx == NULL)
+ return -1;
+
+ status = PK11_DigestOp(ctx->pk11_context, data, len);
+ if (status != SECSuccess)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * pg_cryptohash_final
+ *
+ * Finalize a hash context. Returns 0 on success, -1 on failure.
+ */
+int
+pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest)
+{
+ SECStatus status;
+ unsigned int outlen;
+ const SECHashObject *object;
+
+ object = HASH_GetHashObject(ctx->hash_type);
+ status = PK11_DigestFinal(ctx->pk11_context, dest, &outlen, object->length);
+
+ if (status != SECSuccess)
+ return -1;
+ return 0;
+}
+
+/*
+ * pg_cryptohash_free
+ *
+ * Free a hash context and the associated NSS context.
+ */
+void
+pg_cryptohash_free(pg_cryptohash_ctx *ctx)
+{
+ PRBool free_context = PR_TRUE;
+ if (!ctx)
+ return;
+
+ PK11_DestroyContext(ctx->pk11_context, free_context);
+#ifndef FRONTEND
+ ResourceOwnerForgetCryptoHash(ctx->resowner, PointerGetDatum(ctx));
+#endif
+ NSS_ShutdownContext(ctx->nss_context);
+ explicit_bzero(ctx, sizeof(pg_cryptohash_ctx));
+ FREE(ctx);
+}
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 660387d0e8..180eb0aa3f 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -132,6 +132,10 @@ sub mkvcbuild
push(@pgcommonallfiles, 'cryptohash_openssl.c');
push(@pgcommonallfiles, 'protocol_openssl.c');
}
+ elsif ($solution->{options}->{nss})
+ {
+ push(@pgcommonallfiles, 'cryptohash_nss.c');
+ }
else
{
push(@pgcommonallfiles, 'cryptohash.c');
--
2.21.1 (Apple Git-122.3)