mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 00:03:09 -04:00
87ae969 has created two new files called cryptohash{_openssl}.c in src/common/, whose names overlap with the existing backend file called cryptohashes.c dedicated to the SQL wrappers for SHA2 and MD5. This file is renamed to cryptohashfuncs.c to be more consistent with the surroundings and reduce the confusion with the new cryptohash interface of src/common/. Author: Michael Paquier Reviewed-by: Daniel Gustafsson Discussion: https://postgr.es/m/X8hHhaQgbMbW+aGU@paquier.xyz
191 lines
4.7 KiB
C
191 lines
4.7 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* cryptohashfuncs.c
|
|
* Cryptographic hash functions
|
|
*
|
|
* Portions Copyright (c) 2018-2020, PostgreSQL Global Development Group
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/backend/utils/adt/cryptohashfuncs.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "common/cryptohash.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_cryptohash_ctx *ctx;
|
|
unsigned char buf[PG_SHA224_DIGEST_LENGTH];
|
|
bytea *result;
|
|
|
|
len = VARSIZE_ANY_EXHDR(in);
|
|
data = (unsigned char *) VARDATA_ANY(in);
|
|
|
|
ctx = pg_cryptohash_create(PG_SHA224);
|
|
if (pg_cryptohash_init(ctx) < 0)
|
|
elog(ERROR, "could not initialize %s context", "SHA224");
|
|
if (pg_cryptohash_update(ctx, data, len) < 0)
|
|
elog(ERROR, "could not update %s context", "SHA224");
|
|
if (pg_cryptohash_final(ctx, buf) < 0)
|
|
elog(ERROR, "could not finalize %s context", "SHA224");
|
|
pg_cryptohash_free(ctx);
|
|
|
|
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_cryptohash_ctx *ctx;
|
|
unsigned char buf[PG_SHA256_DIGEST_LENGTH];
|
|
bytea *result;
|
|
|
|
len = VARSIZE_ANY_EXHDR(in);
|
|
data = (unsigned char *) VARDATA_ANY(in);
|
|
|
|
ctx = pg_cryptohash_create(PG_SHA256);
|
|
if (pg_cryptohash_init(ctx) < 0)
|
|
elog(ERROR, "could not initialize %s context", "SHA256");
|
|
if (pg_cryptohash_update(ctx, data, len) < 0)
|
|
elog(ERROR, "could not update %s context", "SHA256");
|
|
if (pg_cryptohash_final(ctx, buf) < 0)
|
|
elog(ERROR, "could not finalize %s context", "SHA256");
|
|
pg_cryptohash_free(ctx);
|
|
|
|
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_cryptohash_ctx *ctx;
|
|
unsigned char buf[PG_SHA384_DIGEST_LENGTH];
|
|
bytea *result;
|
|
|
|
len = VARSIZE_ANY_EXHDR(in);
|
|
data = (unsigned char *) VARDATA_ANY(in);
|
|
|
|
ctx = pg_cryptohash_create(PG_SHA384);
|
|
if (pg_cryptohash_init(ctx) < 0)
|
|
elog(ERROR, "could not initialize %s context", "SHA384");
|
|
if (pg_cryptohash_update(ctx, data, len) < 0)
|
|
elog(ERROR, "could not update %s context", "SHA384");
|
|
if (pg_cryptohash_final(ctx, buf) < 0)
|
|
elog(ERROR, "could not finalize %s context", "SHA384");
|
|
pg_cryptohash_free(ctx);
|
|
|
|
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_cryptohash_ctx *ctx;
|
|
unsigned char buf[PG_SHA512_DIGEST_LENGTH];
|
|
bytea *result;
|
|
|
|
len = VARSIZE_ANY_EXHDR(in);
|
|
data = (unsigned char *) VARDATA_ANY(in);
|
|
|
|
ctx = pg_cryptohash_create(PG_SHA512);
|
|
if (pg_cryptohash_init(ctx) < 0)
|
|
elog(ERROR, "could not initialize %s context", "SHA512");
|
|
if (pg_cryptohash_update(ctx, data, len) < 0)
|
|
elog(ERROR, "could not update %s context", "SHA512");
|
|
if (pg_cryptohash_final(ctx, buf) < 0)
|
|
elog(ERROR, "could not finalize %s context", "SHA512");
|
|
pg_cryptohash_free(ctx);
|
|
|
|
result = palloc(sizeof(buf) + VARHDRSZ);
|
|
SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
|
|
memcpy(VARDATA(result), buf, sizeof(buf));
|
|
|
|
PG_RETURN_BYTEA_P(result);
|
|
}
|