LCOV - code coverage report
Current view: top level - src/backend/utils/adt - cryptohashfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15beta1 Lines: 54 61 88.5 %
Date: 2022-05-18 02:09:37 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * cryptohashfuncs.c
       4             :  *    Cryptographic hash functions
       5             :  *
       6             :  * Portions Copyright (c) 2018-2022, PostgreSQL Global Development Group
       7             :  *
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/adt/cryptohashfuncs.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #include "postgres.h"
      15             : 
      16             : #include "common/cryptohash.h"
      17             : #include "common/md5.h"
      18             : #include "common/sha2.h"
      19             : #include "utils/builtins.h"
      20             : 
      21             : 
      22             : /*
      23             :  * MD5
      24             :  */
      25             : 
      26             : /* MD5 produces a 16 byte (128 bit) hash; double it for hex */
      27             : #define MD5_HASH_LEN  32
      28             : 
      29             : /*
      30             :  * Create an MD5 hash of a text value and return it as hex string.
      31             :  */
      32             : Datum
      33     1041168 : md5_text(PG_FUNCTION_ARGS)
      34             : {
      35     1041168 :     text       *in_text = PG_GETARG_TEXT_PP(0);
      36             :     size_t      len;
      37             :     char        hexsum[MD5_HASH_LEN + 1];
      38     1041168 :     const char *errstr = NULL;
      39             : 
      40             :     /* Calculate the length of the buffer using varlena metadata */
      41     1041168 :     len = VARSIZE_ANY_EXHDR(in_text);
      42             : 
      43             :     /* get the hash result */
      44     1041168 :     if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum, &errstr) == false)
      45           0 :         ereport(ERROR,
      46             :                 (errcode(ERRCODE_INTERNAL_ERROR),
      47             :                  errmsg("could not compute %s hash: %s", "MD5",
      48             :                         errstr)));
      49             : 
      50             :     /* convert to text and return it */
      51     1041168 :     PG_RETURN_TEXT_P(cstring_to_text(hexsum));
      52             : }
      53             : 
      54             : /*
      55             :  * Create an MD5 hash of a bytea value and return it as a hex string.
      56             :  */
      57             : Datum
      58          54 : md5_bytea(PG_FUNCTION_ARGS)
      59             : {
      60          54 :     bytea      *in = PG_GETARG_BYTEA_PP(0);
      61             :     size_t      len;
      62             :     char        hexsum[MD5_HASH_LEN + 1];
      63          54 :     const char *errstr = NULL;
      64             : 
      65          54 :     len = VARSIZE_ANY_EXHDR(in);
      66          54 :     if (pg_md5_hash(VARDATA_ANY(in), len, hexsum, &errstr) == false)
      67           0 :         ereport(ERROR,
      68             :                 (errcode(ERRCODE_INTERNAL_ERROR),
      69             :                  errmsg("could not compute %s hash: %s", "MD5",
      70             :                         errstr)));
      71             : 
      72          54 :     PG_RETURN_TEXT_P(cstring_to_text(hexsum));
      73             : }
      74             : 
      75             : /*
      76             :  * Internal routine to compute a cryptohash with the given bytea input.
      77             :  */
      78             : static inline bytea *
      79          48 : cryptohash_internal(pg_cryptohash_type type, bytea *input)
      80             : {
      81             :     const uint8 *data;
      82          48 :     const char *typestr = NULL;
      83          48 :     int         digest_len = 0;
      84             :     size_t      len;
      85             :     pg_cryptohash_ctx *ctx;
      86             :     bytea      *result;
      87             : 
      88          48 :     switch (type)
      89             :     {
      90          12 :         case PG_SHA224:
      91          12 :             typestr = "SHA224";
      92          12 :             digest_len = PG_SHA224_DIGEST_LENGTH;
      93          12 :             break;
      94          12 :         case PG_SHA256:
      95          12 :             typestr = "SHA256";
      96          12 :             digest_len = PG_SHA256_DIGEST_LENGTH;
      97          12 :             break;
      98          12 :         case PG_SHA384:
      99          12 :             typestr = "SHA384";
     100          12 :             digest_len = PG_SHA384_DIGEST_LENGTH;
     101          12 :             break;
     102          12 :         case PG_SHA512:
     103          12 :             typestr = "SHA512";
     104          12 :             digest_len = PG_SHA512_DIGEST_LENGTH;
     105          12 :             break;
     106           0 :         case PG_MD5:
     107             :         case PG_SHA1:
     108           0 :             elog(ERROR, "unsupported cryptohash type %d", type);
     109             :             break;
     110             :     }
     111             : 
     112          48 :     result = palloc0(digest_len + VARHDRSZ);
     113          48 :     len = VARSIZE_ANY_EXHDR(input);
     114          48 :     data = (unsigned char *) VARDATA_ANY(input);
     115             : 
     116          48 :     ctx = pg_cryptohash_create(type);
     117          48 :     if (pg_cryptohash_init(ctx) < 0)
     118           0 :         elog(ERROR, "could not initialize %s context: %s", typestr,
     119             :              pg_cryptohash_error(ctx));
     120          48 :     if (pg_cryptohash_update(ctx, data, len) < 0)
     121           0 :         elog(ERROR, "could not update %s context: %s", typestr,
     122             :              pg_cryptohash_error(ctx));
     123          48 :     if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result),
     124             :                             digest_len) < 0)
     125           0 :         elog(ERROR, "could not finalize %s context: %s", typestr,
     126             :              pg_cryptohash_error(ctx));
     127          48 :     pg_cryptohash_free(ctx);
     128             : 
     129          48 :     SET_VARSIZE(result, digest_len + VARHDRSZ);
     130             : 
     131          48 :     return result;
     132             : }
     133             : 
     134             : /*
     135             :  * SHA-2 variants
     136             :  */
     137             : 
     138             : Datum
     139          12 : sha224_bytea(PG_FUNCTION_ARGS)
     140             : {
     141          12 :     bytea      *result = cryptohash_internal(PG_SHA224, PG_GETARG_BYTEA_PP(0));
     142             : 
     143          12 :     PG_RETURN_BYTEA_P(result);
     144             : }
     145             : 
     146             : Datum
     147          12 : sha256_bytea(PG_FUNCTION_ARGS)
     148             : {
     149          12 :     bytea      *result = cryptohash_internal(PG_SHA256, PG_GETARG_BYTEA_PP(0));
     150             : 
     151          12 :     PG_RETURN_BYTEA_P(result);
     152             : }
     153             : 
     154             : Datum
     155          12 : sha384_bytea(PG_FUNCTION_ARGS)
     156             : {
     157          12 :     bytea      *result = cryptohash_internal(PG_SHA384, PG_GETARG_BYTEA_PP(0));
     158             : 
     159          12 :     PG_RETURN_BYTEA_P(result);
     160             : }
     161             : 
     162             : Datum
     163          12 : sha512_bytea(PG_FUNCTION_ARGS)
     164             : {
     165          12 :     bytea      *result = cryptohash_internal(PG_SHA512, PG_GETARG_BYTEA_PP(0));
     166             : 
     167          12 :     PG_RETURN_BYTEA_P(result);
     168             : }

Generated by: LCOV version 1.14