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

Generated by: LCOV version 1.14