mirror of
https://github.com/postgres/postgres.git
synced 2025-05-15 19:15:29 +03:00
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>
170 lines
3.6 KiB
C
170 lines
3.6 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* 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);
|
|
}
|