1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * cryptohashes.c |
4 | * Cryptographic hash functions |
5 | * |
6 | * Portions Copyright (c) 2018-2019, PostgreSQL Global Development Group |
7 | * |
8 | * |
9 | * IDENTIFICATION |
10 | * src/backend/utils/adt/cryptohashes.c |
11 | * |
12 | *------------------------------------------------------------------------- |
13 | */ |
14 | #include "postgres.h" |
15 | |
16 | #include "common/md5.h" |
17 | #include "common/sha2.h" |
18 | #include "utils/builtins.h" |
19 | |
20 | |
21 | /* |
22 | * MD5 |
23 | */ |
24 | |
25 | /* MD5 produces a 16 byte (128 bit) hash; double it for hex */ |
26 | #define MD5_HASH_LEN 32 |
27 | |
28 | /* |
29 | * Create an MD5 hash of a text value and return it as hex string. |
30 | */ |
31 | Datum |
32 | md5_text(PG_FUNCTION_ARGS) |
33 | { |
34 | text *in_text = PG_GETARG_TEXT_PP(0); |
35 | size_t len; |
36 | char hexsum[MD5_HASH_LEN + 1]; |
37 | |
38 | /* Calculate the length of the buffer using varlena metadata */ |
39 | len = VARSIZE_ANY_EXHDR(in_text); |
40 | |
41 | /* get the hash result */ |
42 | if (pg_md5_hash(VARDATA_ANY(in_text), len, hexsum) == false) |
43 | ereport(ERROR, |
44 | (errcode(ERRCODE_OUT_OF_MEMORY), |
45 | errmsg("out of memory" ))); |
46 | |
47 | /* convert to text and return it */ |
48 | PG_RETURN_TEXT_P(cstring_to_text(hexsum)); |
49 | } |
50 | |
51 | /* |
52 | * Create an MD5 hash of a bytea value and return it as a hex string. |
53 | */ |
54 | Datum |
55 | md5_bytea(PG_FUNCTION_ARGS) |
56 | { |
57 | bytea *in = PG_GETARG_BYTEA_PP(0); |
58 | size_t len; |
59 | char hexsum[MD5_HASH_LEN + 1]; |
60 | |
61 | len = VARSIZE_ANY_EXHDR(in); |
62 | if (pg_md5_hash(VARDATA_ANY(in), len, hexsum) == false) |
63 | ereport(ERROR, |
64 | (errcode(ERRCODE_OUT_OF_MEMORY), |
65 | errmsg("out of memory" ))); |
66 | |
67 | PG_RETURN_TEXT_P(cstring_to_text(hexsum)); |
68 | } |
69 | |
70 | |
71 | /* |
72 | * SHA-2 variants |
73 | */ |
74 | |
75 | Datum |
76 | sha224_bytea(PG_FUNCTION_ARGS) |
77 | { |
78 | bytea *in = PG_GETARG_BYTEA_PP(0); |
79 | const uint8 *data; |
80 | size_t len; |
81 | pg_sha224_ctx ctx; |
82 | unsigned char buf[PG_SHA224_DIGEST_LENGTH]; |
83 | bytea *result; |
84 | |
85 | len = VARSIZE_ANY_EXHDR(in); |
86 | data = (unsigned char *) VARDATA_ANY(in); |
87 | |
88 | pg_sha224_init(&ctx); |
89 | pg_sha224_update(&ctx, data, len); |
90 | pg_sha224_final(&ctx, buf); |
91 | |
92 | result = palloc(sizeof(buf) + VARHDRSZ); |
93 | SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); |
94 | memcpy(VARDATA(result), buf, sizeof(buf)); |
95 | |
96 | PG_RETURN_BYTEA_P(result); |
97 | } |
98 | |
99 | Datum |
100 | sha256_bytea(PG_FUNCTION_ARGS) |
101 | { |
102 | bytea *in = PG_GETARG_BYTEA_PP(0); |
103 | const uint8 *data; |
104 | size_t len; |
105 | pg_sha256_ctx ctx; |
106 | unsigned char buf[PG_SHA256_DIGEST_LENGTH]; |
107 | bytea *result; |
108 | |
109 | len = VARSIZE_ANY_EXHDR(in); |
110 | data = (unsigned char *) VARDATA_ANY(in); |
111 | |
112 | pg_sha256_init(&ctx); |
113 | pg_sha256_update(&ctx, data, len); |
114 | pg_sha256_final(&ctx, buf); |
115 | |
116 | result = palloc(sizeof(buf) + VARHDRSZ); |
117 | SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); |
118 | memcpy(VARDATA(result), buf, sizeof(buf)); |
119 | |
120 | PG_RETURN_BYTEA_P(result); |
121 | } |
122 | |
123 | Datum |
124 | sha384_bytea(PG_FUNCTION_ARGS) |
125 | { |
126 | bytea *in = PG_GETARG_BYTEA_PP(0); |
127 | const uint8 *data; |
128 | size_t len; |
129 | pg_sha384_ctx ctx; |
130 | unsigned char buf[PG_SHA384_DIGEST_LENGTH]; |
131 | bytea *result; |
132 | |
133 | len = VARSIZE_ANY_EXHDR(in); |
134 | data = (unsigned char *) VARDATA_ANY(in); |
135 | |
136 | pg_sha384_init(&ctx); |
137 | pg_sha384_update(&ctx, data, len); |
138 | pg_sha384_final(&ctx, buf); |
139 | |
140 | result = palloc(sizeof(buf) + VARHDRSZ); |
141 | SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); |
142 | memcpy(VARDATA(result), buf, sizeof(buf)); |
143 | |
144 | PG_RETURN_BYTEA_P(result); |
145 | } |
146 | |
147 | Datum |
148 | sha512_bytea(PG_FUNCTION_ARGS) |
149 | { |
150 | bytea *in = PG_GETARG_BYTEA_PP(0); |
151 | const uint8 *data; |
152 | size_t len; |
153 | pg_sha512_ctx ctx; |
154 | unsigned char buf[PG_SHA512_DIGEST_LENGTH]; |
155 | bytea *result; |
156 | |
157 | len = VARSIZE_ANY_EXHDR(in); |
158 | data = (unsigned char *) VARDATA_ANY(in); |
159 | |
160 | pg_sha512_init(&ctx); |
161 | pg_sha512_update(&ctx, data, len); |
162 | pg_sha512_final(&ctx, buf); |
163 | |
164 | result = palloc(sizeof(buf) + VARHDRSZ); |
165 | SET_VARSIZE(result, sizeof(buf) + VARHDRSZ); |
166 | memcpy(VARDATA(result), buf, sizeof(buf)); |
167 | |
168 | PG_RETURN_BYTEA_P(result); |
169 | } |
170 | |