Refactor SQL functions of SHA-2 in cryptohashfuncs.c
authorMichael Paquier <[email protected]>
Thu, 28 Jan 2021 07:13:26 +0000 (16:13 +0900)
committerMichael Paquier <[email protected]>
Thu, 28 Jan 2021 07:13:26 +0000 (16:13 +0900)
The same code pattern was repeated four times when compiling a SHA-2
hash.  This refactoring has the advantage to issue a compilation warning
if a new value is added to pg_cryptohash_type, so as anybody doing an
addition in this area would need to consider if support for a new SQL
function is needed or not.

Author: Sehrope Sarkuni, Michael Paquier
Discussion: https://postgr.es/m/[email protected]

src/backend/utils/adt/cryptohashfuncs.c

index d99485f4c6dd4748a9eda68d42109d7643233329..152adcbfb4ad090c0c3bd63d5d351d80d351377a 100644 (file)
@@ -68,65 +68,77 @@ md5_bytea(PG_FUNCTION_ARGS)
    PG_RETURN_TEXT_P(cstring_to_text(hexsum));
 }
 
-
 /*
- * SHA-2 variants
+ * Internal routine to compute a cryptohash with the given bytea input.
  */
-
-Datum
-sha224_bytea(PG_FUNCTION_ARGS)
+static inline bytea *
+cryptohash_internal(pg_cryptohash_type type, bytea *input)
 {
-   bytea      *in = PG_GETARG_BYTEA_PP(0);
    const uint8 *data;
+   const char *typestr = NULL;
+   int         digest_len = 0;
    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);
+   switch (type)
+   {
+       case PG_SHA224:
+           typestr = "SHA224";
+           digest_len = PG_SHA224_DIGEST_LENGTH;
+           break;
+       case PG_SHA256:
+           typestr = "SHA256";
+           digest_len = PG_SHA256_DIGEST_LENGTH;
+           break;
+       case PG_SHA384:
+           typestr = "SHA384";
+           digest_len = PG_SHA384_DIGEST_LENGTH;
+           break;
+       case PG_SHA512:
+           typestr = "SHA512";
+           digest_len = PG_SHA512_DIGEST_LENGTH;
+           break;
+       case PG_MD5:
+       case PG_SHA1:
+           elog(ERROR, "unsupported cryptohash type %d", type);
+           break;
+   }
+
+   result = palloc0(digest_len + VARHDRSZ);
+   len = VARSIZE_ANY_EXHDR(input);
+   data = (unsigned char *) VARDATA_ANY(input);
+
+   ctx = pg_cryptohash_create(type);
    if (pg_cryptohash_init(ctx) < 0)
-       elog(ERROR, "could not initialize %s context", "SHA224");
+       elog(ERROR, "could not initialize %s context", typestr);
    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");
+       elog(ERROR, "could not update %s context", typestr);
+   if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result)) < 0)
+       elog(ERROR, "could not finalize %s context", typestr);
    pg_cryptohash_free(ctx);
 
-   result = palloc(sizeof(buf) + VARHDRSZ);
-   SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
-   memcpy(VARDATA(result), buf, sizeof(buf));
+   SET_VARSIZE(result, digest_len + VARHDRSZ);
 
-   PG_RETURN_BYTEA_P(result);
+   return result;
 }
 
+/*
+ * SHA-2 variants
+ */
+
 Datum
-sha256_bytea(PG_FUNCTION_ARGS)
+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_SHA256_DIGEST_LENGTH];
-   bytea      *result;
+   bytea      *result = cryptohash_internal(PG_SHA224, PG_GETARG_BYTEA_PP(0));
 
-   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);
+   PG_RETURN_BYTEA_P(result);
+}
 
-   result = palloc(sizeof(buf) + VARHDRSZ);
-   SET_VARSIZE(result, sizeof(buf) + VARHDRSZ);
-   memcpy(VARDATA(result), buf, sizeof(buf));
+Datum
+sha256_bytea(PG_FUNCTION_ARGS)
+{
+   bytea      *result = cryptohash_internal(PG_SHA256, PG_GETARG_BYTEA_PP(0));
 
    PG_RETURN_BYTEA_P(result);
 }
@@ -134,28 +146,7 @@ sha256_bytea(PG_FUNCTION_ARGS)
 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));
+   bytea      *result = cryptohash_internal(PG_SHA384, PG_GETARG_BYTEA_PP(0));
 
    PG_RETURN_BYTEA_P(result);
 }
@@ -163,28 +154,7 @@ sha384_bytea(PG_FUNCTION_ARGS)
 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));
+   bytea      *result = cryptohash_internal(PG_SHA512, PG_GETARG_BYTEA_PP(0));
 
    PG_RETURN_BYTEA_P(result);
 }