aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/cryptohashes.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2018-02-06 21:46:46 -0500
committerPeter Eisentraut <peter_e@gmx.net>2018-02-22 11:34:53 -0500
commit10cfce34c0fe20d2caed5750bbc5c315c0e4cc63 (patch)
treebad5c503278b81c77080c534a882a93c2bcb952b /src/backend/utils/adt/cryptohashes.c
parentedd44738bc88148784899a8949519364d81d9ea8 (diff)
downloadpostgresql-10cfce34c0fe20d2caed5750bbc5c315c0e4cc63.tar.gz
postgresql-10cfce34c0fe20d2caed5750bbc5c315c0e4cc63.zip
Add user-callable SHA-2 functions
Add the user-callable functions sha224, sha256, sha384, sha512. We already had these in the C code to support SCRAM, but there was no test coverage outside of the SCRAM tests. Adding these as user-callable functions allows writing some tests. Also, we have a user-callable md5 function but no more modern alternative, which led to wide use of md5 as a general-purpose hash function, which leads to occasional complaints about using md5. Also mark the existing md5 functions as leak-proof. Reviewed-by: Michael Paquier <michael@paquier.xyz>
Diffstat (limited to 'src/backend/utils/adt/cryptohashes.c')
-rw-r--r--src/backend/utils/adt/cryptohashes.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/backend/utils/adt/cryptohashes.c b/src/backend/utils/adt/cryptohashes.c
new file mode 100644
index 00000000000..e1ff17590ea
--- /dev/null
+++ b/src/backend/utils/adt/cryptohashes.c
@@ -0,0 +1,169 @@
+/*-------------------------------------------------------------------------
+ *
+ * cryptohashes.c
+ * Cryptographic hash functions
+ *
+ * Portions Copyright (c) 2018, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/adt/cryptohashes.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "common/md5.h"
+#include "common/sha2.h"
+#include "utils/builtins.h"
+
+
+/*
+ * MD5
+ */
+
+/* MD5 produces a 16 byte (128 bit) hash; double it for hex */
+#define MD5_HASH_LEN 32
+
+/*
+ * Create an MD5 hash of a text value and return it as hex string.
+ */
+Datum
+md5_text(PG_FUNCTION_ARGS)
+{
+ text *in_text = PG_GETARG_TEXT_PP(0);
+ size_t len;
+ char hexsum[MD5_HASH_LEN + 1];
+
+ /* Calculate the length of the buffer using varlena metadata */
+ len = VARSIZE_ANY_EXHDR(in_text);
+
+ /* get the hash result */
+ if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum) == false)
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+
+ /* convert to text and return it */
+ PG_RETURN_TEXT_P(cstring_to_text(hexsum));
+}
+
+/*
+ * Create an MD5 hash of a bytea value and return it as a hex string.
+ */
+Datum
+md5_bytea(PG_FUNCTION_ARGS)
+{
+ bytea *in = PG_GETARG_BYTEA_PP(0);
+ size_t len;
+ char hexsum[MD5_HASH_LEN + 1];
+
+ len = VARSIZE_ANY_EXHDR(in);
+ if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false)
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory")));
+
+ PG_RETURN_TEXT_P(cstring_to_text(hexsum));
+}
+
+
+/*
+ * SHA-2 variants
+ */
+
+Datum
+sha224_bytea(PG_FUNCTION_ARGS)
+{
+ bytea *in = PG_GETARG_BYTEA_PP(0);
+ const uint8 *data;
+ size_t len;
+ pg_sha224_ctx ctx;
+ unsigned char buf[PG_SHA224_DIGEST_LENGTH];
+ bytea *result;
+
+ len = VARSIZE_ANY_EXHDR(in);
+ data = (unsigned char *) VARDATA_ANY(in);
+
+ pg_sha224_init(&ctx);
+ pg_sha224_update(&ctx, data, len);
+ pg_sha224_final(&ctx, buf);
+
+ result = palloc(sizeof(buf) + VARHDRSZ);
+ SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
+ memcpy(VARDATA(result), buf, sizeof(buf));
+
+ PG_RETURN_BYTEA_P(result);
+}
+
+Datum
+sha256_bytea(PG_FUNCTION_ARGS)
+{
+ bytea *in = PG_GETARG_BYTEA_PP(0);
+ const uint8 *data;
+ size_t len;
+ pg_sha256_ctx ctx;
+ unsigned char buf[PG_SHA256_DIGEST_LENGTH];
+ bytea *result;
+
+ len = VARSIZE_ANY_EXHDR(in);
+ data = (unsigned char *) VARDATA_ANY(in);
+
+ pg_sha256_init(&ctx);
+ pg_sha256_update(&ctx, data, len);
+ pg_sha256_final(&ctx, buf);
+
+ result = palloc(sizeof(buf) + VARHDRSZ);
+ SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
+ memcpy(VARDATA(result), buf, sizeof(buf));
+
+ PG_RETURN_BYTEA_P(result);
+}
+
+Datum
+sha384_bytea(PG_FUNCTION_ARGS)
+{
+ bytea *in = PG_GETARG_BYTEA_PP(0);
+ const uint8 *data;
+ size_t len;
+ pg_sha384_ctx ctx;
+ unsigned char buf[PG_SHA384_DIGEST_LENGTH];
+ bytea *result;
+
+ len = VARSIZE_ANY_EXHDR(in);
+ data = (unsigned char *) VARDATA_ANY(in);
+
+ pg_sha384_init(&ctx);
+ pg_sha384_update(&ctx, data, len);
+ pg_sha384_final(&ctx, buf);
+
+ result = palloc(sizeof(buf) + VARHDRSZ);
+ SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
+ memcpy(VARDATA(result), buf, sizeof(buf));
+
+ PG_RETURN_BYTEA_P(result);
+}
+
+Datum
+sha512_bytea(PG_FUNCTION_ARGS)
+{
+ bytea *in = PG_GETARG_BYTEA_PP(0);
+ const uint8 *data;
+ size_t len;
+ pg_sha512_ctx ctx;
+ unsigned char buf[PG_SHA512_DIGEST_LENGTH];
+ bytea *result;
+
+ len = VARSIZE_ANY_EXHDR(in);
+ data = (unsigned char *) VARDATA_ANY(in);
+
+ pg_sha512_init(&ctx);
+ pg_sha512_update(&ctx, data, len);
+ pg_sha512_final(&ctx, buf);
+
+ result = palloc(sizeof(buf) + VARHDRSZ);
+ SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
+ memcpy(VARDATA(result), buf, sizeof(buf));
+
+ PG_RETURN_BYTEA_P(result);
+}