LCOV - code coverage report
Current view: top level - src/backend/utils/adt - cryptohashfuncs.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 88.5 % 61 54
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * cryptohashfuncs.c
       4              :  *    Cryptographic hash functions
       5              :  *
       6              :  * Portions Copyright (c) 2018-2026, 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           23 : md5_text(PG_FUNCTION_ARGS)
      35              : {
      36           23 :     text       *in_text = PG_GETARG_TEXT_PP(0);
      37              :     size_t      len;
      38              :     char        hexsum[MD5_HASH_LEN + 1];
      39           23 :     const char *errstr = NULL;
      40              : 
      41              :     /* Calculate the length of the buffer using varlena metadata */
      42           23 :     len = VARSIZE_ANY_EXHDR(in_text);
      43              : 
      44              :     /* get the hash result */
      45           23 :     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           23 :     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           21 : md5_bytea(PG_FUNCTION_ARGS)
      60              : {
      61           21 :     bytea      *in = PG_GETARG_BYTEA_PP(0);
      62              :     size_t      len;
      63              :     char        hexsum[MD5_HASH_LEN + 1];
      64           21 :     const char *errstr = NULL;
      65              : 
      66           21 :     len = VARSIZE_ANY_EXHDR(in);
      67           21 :     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           21 :     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       642610 : cryptohash_internal(pg_cryptohash_type type, bytea *input)
      81              : {
      82              :     const uint8 *data;
      83       642610 :     const char *typestr = NULL;
      84       642610 :     int         digest_len = 0;
      85              :     size_t      len;
      86              :     pg_cryptohash_ctx *ctx;
      87              :     bytea      *result;
      88              : 
      89       642610 :     switch (type)
      90              :     {
      91            6 :         case PG_SHA224:
      92            6 :             typestr = "SHA224";
      93            6 :             digest_len = PG_SHA224_DIGEST_LENGTH;
      94            6 :             break;
      95       642592 :         case PG_SHA256:
      96       642592 :             typestr = "SHA256";
      97       642592 :             digest_len = PG_SHA256_DIGEST_LENGTH;
      98       642592 :             break;
      99            6 :         case PG_SHA384:
     100            6 :             typestr = "SHA384";
     101            6 :             digest_len = PG_SHA384_DIGEST_LENGTH;
     102            6 :             break;
     103            6 :         case PG_SHA512:
     104            6 :             typestr = "SHA512";
     105            6 :             digest_len = PG_SHA512_DIGEST_LENGTH;
     106            6 :             break;
     107            0 :         case PG_MD5:
     108              :         case PG_SHA1:
     109            0 :             elog(ERROR, "unsupported cryptohash type %d", type);
     110              :             break;
     111              :     }
     112              : 
     113       642610 :     result = palloc0(digest_len + VARHDRSZ);
     114       642610 :     len = VARSIZE_ANY_EXHDR(input);
     115       642610 :     data = (unsigned char *) VARDATA_ANY(input);
     116              : 
     117       642610 :     ctx = pg_cryptohash_create(type);
     118       642610 :     if (pg_cryptohash_init(ctx) < 0)
     119            0 :         elog(ERROR, "could not initialize %s context: %s", typestr,
     120              :              pg_cryptohash_error(ctx));
     121       642610 :     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       642610 :     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       642610 :     pg_cryptohash_free(ctx);
     129              : 
     130       642610 :     SET_VARSIZE(result, digest_len + VARHDRSZ);
     131              : 
     132       642610 :     return result;
     133              : }
     134              : 
     135              : /*
     136              :  * SHA-2 variants
     137              :  */
     138              : 
     139              : Datum
     140            6 : sha224_bytea(PG_FUNCTION_ARGS)
     141              : {
     142            6 :     bytea      *result = cryptohash_internal(PG_SHA224, PG_GETARG_BYTEA_PP(0));
     143              : 
     144            6 :     PG_RETURN_BYTEA_P(result);
     145              : }
     146              : 
     147              : Datum
     148       642592 : sha256_bytea(PG_FUNCTION_ARGS)
     149              : {
     150       642592 :     bytea      *result = cryptohash_internal(PG_SHA256, PG_GETARG_BYTEA_PP(0));
     151              : 
     152       642592 :     PG_RETURN_BYTEA_P(result);
     153              : }
     154              : 
     155              : Datum
     156            6 : sha384_bytea(PG_FUNCTION_ARGS)
     157              : {
     158            6 :     bytea      *result = cryptohash_internal(PG_SHA384, PG_GETARG_BYTEA_PP(0));
     159              : 
     160            6 :     PG_RETURN_BYTEA_P(result);
     161              : }
     162              : 
     163              : Datum
     164            6 : sha512_bytea(PG_FUNCTION_ARGS)
     165              : {
     166            6 :     bytea      *result = cryptohash_internal(PG_SHA512, PG_GETARG_BYTEA_PP(0));
     167              : 
     168            6 :     PG_RETURN_BYTEA_P(result);
     169              : }
        

Generated by: LCOV version 2.0-1