1 /*-------------------------------------------------------------------------
2  *
3  * cryptohashes.c
4  *	  Cryptographic hash functions
5  *
6  * Portions Copyright (c) 2018, 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
md5_text(PG_FUNCTION_ARGS)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
md5_bytea(PG_FUNCTION_ARGS)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
sha224_bytea(PG_FUNCTION_ARGS)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
sha256_bytea(PG_FUNCTION_ARGS)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
sha384_bytea(PG_FUNCTION_ARGS)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
sha512_bytea(PG_FUNCTION_ARGS)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