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 */
31Datum
32md5_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 */
54Datum
55md5_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
75Datum
76sha224_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
99Datum
100sha256_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
123Datum
124sha384_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
147Datum
148sha512_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