Age Owner Branch data TLA 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
2259 peter_e@gmx.net 34 :CBC 4503 : md5_text(PG_FUNCTION_ARGS)
35 : : {
36 : 4503 : text *in_text = PG_GETARG_TEXT_PP(0);
37 : : size_t len;
38 : : char hexsum[MD5_HASH_LEN + 1];
824 michael@paquier.xyz 39 : 4503 : const char *errstr = NULL;
40 : :
41 : : /* Calculate the length of the buffer using varlena metadata */
2259 peter_e@gmx.net 42 [ - + - - : 4503 : len = VARSIZE_ANY_EXHDR(in_text);
- - - - -
+ ]
43 : :
44 : : /* get the hash result */
824 michael@paquier.xyz 45 [ - + - + ]: 4503 : if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum, &errstr) == false)
2259 peter_e@gmx.net 46 [ # # ]:UBC 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 */
2259 peter_e@gmx.net 52 :CBC 4503 : 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];
824 michael@paquier.xyz 64 : 21 : const char *errstr = NULL;
65 : :
2259 peter_e@gmx.net 66 [ - + - - : 21 : len = VARSIZE_ANY_EXHDR(in);
- - - - -
+ ]
824 michael@paquier.xyz 67 [ - + - + ]: 21 : if (pg_md5_hash(VARDATA_ANY(in), len, hexsum, &errstr) == false)
2259 peter_e@gmx.net 68 [ # # ]:UBC 0 : ereport(ERROR,
69 : : (errcode(ERRCODE_INTERNAL_ERROR),
70 : : errmsg("could not compute %s hash: %s", "MD5",
71 : : errstr)));
72 : :
2259 peter_e@gmx.net 73 :CBC 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 *
1172 michael@paquier.xyz 80 : 421659 : cryptohash_internal(pg_cryptohash_type type, bytea *input)
81 : : {
82 : : const uint8 *data;
83 : 421659 : const char *typestr = NULL;
84 : 421659 : int digest_len = 0;
85 : : size_t len;
86 : : pg_cryptohash_ctx *ctx;
87 : : bytea *result;
88 : :
89 [ + + + + : 421659 : switch (type)
- - ]
90 : : {
91 : 6 : case PG_SHA224:
92 : 6 : typestr = "SHA224";
93 : 6 : digest_len = PG_SHA224_DIGEST_LENGTH;
94 : 6 : break;
95 : 421641 : case PG_SHA256:
96 : 421641 : typestr = "SHA256";
97 : 421641 : digest_len = PG_SHA256_DIGEST_LENGTH;
98 : 421641 : 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;
1172 michael@paquier.xyz 107 :UBC 0 : case PG_MD5:
108 : : case PG_SHA1:
109 [ # # ]: 0 : elog(ERROR, "unsupported cryptohash type %d", type);
110 : : break;
111 : : }
112 : :
1172 michael@paquier.xyz 113 :CBC 421659 : result = palloc0(digest_len + VARHDRSZ);
114 [ - + - - : 421659 : len = VARSIZE_ANY_EXHDR(input);
- - - - +
+ ]
115 [ + + ]: 421659 : data = (unsigned char *) VARDATA_ANY(input);
116 : :
117 : 421659 : ctx = pg_cryptohash_create(type);
1229 118 [ - + ]: 421659 : if (pg_cryptohash_init(ctx) < 0)
824 michael@paquier.xyz 119 [ # # ]:UBC 0 : elog(ERROR, "could not initialize %s context: %s", typestr,
120 : : pg_cryptohash_error(ctx));
1229 michael@paquier.xyz 121 [ - + ]:CBC 421659 : if (pg_cryptohash_update(ctx, data, len) < 0)
824 michael@paquier.xyz 122 [ # # ]:UBC 0 : elog(ERROR, "could not update %s context: %s", typestr,
123 : : pg_cryptohash_error(ctx));
1154 michael@paquier.xyz 124 [ - + ]:CBC 421659 : if (pg_cryptohash_final(ctx, (unsigned char *) VARDATA(result),
125 : : digest_len) < 0)
824 michael@paquier.xyz 126 [ # # ]:UBC 0 : elog(ERROR, "could not finalize %s context: %s", typestr,
127 : : pg_cryptohash_error(ctx));
1229 michael@paquier.xyz 128 :CBC 421659 : pg_cryptohash_free(ctx);
129 : :
1172 130 : 421659 : SET_VARSIZE(result, digest_len + VARHDRSZ);
131 : :
132 : 421659 : 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 : 421641 : sha256_bytea(PG_FUNCTION_ARGS)
149 : : {
150 : 421641 : bytea *result = cryptohash_internal(PG_SHA256, PG_GETARG_BYTEA_PP(0));
151 : :
2259 peter_e@gmx.net 152 : 421641 : PG_RETURN_BYTEA_P(result);
153 : : }
154 : :
155 : : Datum
156 : 6 : sha384_bytea(PG_FUNCTION_ARGS)
157 : : {
1172 michael@paquier.xyz 158 : 6 : bytea *result = cryptohash_internal(PG_SHA384, PG_GETARG_BYTEA_PP(0));
159 : :
2259 peter_e@gmx.net 160 : 6 : PG_RETURN_BYTEA_P(result);
161 : : }
162 : :
163 : : Datum
164 : 6 : sha512_bytea(PG_FUNCTION_ARGS)
165 : : {
1172 michael@paquier.xyz 166 : 6 : bytea *result = cryptohash_internal(PG_SHA512, PG_GETARG_BYTEA_PP(0));
167 : :
2259 peter_e@gmx.net 168 : 6 : PG_RETURN_BYTEA_P(result);
169 : : }
|