Line data Source code
1 : /*
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 : *
6 : * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
7 : */
8 :
9 : #include "monetdb_config.h"
10 : #include "mcrypt.h"
11 : #include <string.h>
12 :
13 : /* only provide digest functions if not embedded */
14 : #include "sha.h"
15 : #include "ripemd160.h"
16 : #include "md5.h"
17 :
18 : /**
19 : * Returns a comma separated list of supported hash algorithms suitable
20 : * for final hashing by the client. This list contains the smaller
21 : * (in char size) hashes.
22 : * The returned string is malloced and should be freed.
23 : */
24 : const char *
25 5455 : mcrypt_getHashAlgorithms(void)
26 : {
27 : /* Currently, four "hashes" are available, RIPEMD160, SHA-2, SHA-1
28 : * and MD5. Previous versions supported UNIX crypt and plain text
29 : * login, but those were removed when SHA-1 became mandatory for
30 : * hashing the plain password in wire protocol version 9.
31 : * Better/stronger/faster algorithms can be added in the future upon
32 : * desire.
33 : */
34 : static const char *algorithms =
35 : "INVALID"
36 : ",RIPEMD160"
37 : ",SHA512"
38 : ",SHA384"
39 : ",SHA256"
40 : ",SHA224"
41 : ",SHA1"
42 : #ifdef HAVE_SNAPPY
43 : ",COMPRESSION_SNAPPY"
44 : #endif
45 : #ifdef HAVE_LIBLZ4
46 : ",COMPRESSION_LZ4"
47 : #endif
48 : ;
49 5455 : return algorithms;
50 : }
51 :
52 : /**
53 : * Returns a malloced string representing the hex representation of
54 : * the MD5 hash of the given string.
55 : */
56 : char *
57 12 : mcrypt_MD5Sum(const char *string, size_t len)
58 : {
59 : MD5_CTX c;
60 : uint8_t md[MD5_DIGEST_LENGTH];
61 : char *ret;
62 :
63 : static_assert(MD5_DIGEST_LENGTH == 16, "MD5_DIGEST_LENGTH should be 16");
64 12 : MD5Init(&c);
65 12 : MD5Update(&c, (const uint8_t *) string, (unsigned int) len);
66 12 : MD5Final(md, &c);
67 :
68 12 : ret = malloc(MD5_DIGEST_LENGTH * 2 + 1);
69 12 : if(ret) {
70 12 : snprintf(ret, MD5_DIGEST_LENGTH * 2 + 1,
71 : "%02x%02x%02x%02x%02x%02x%02x%02x"
72 : "%02x%02x%02x%02x%02x%02x%02x%02x",
73 12 : md[0], md[1], md[2], md[3],
74 12 : md[4], md[5], md[6], md[7],
75 12 : md[8], md[9], md[10], md[11],
76 12 : md[12], md[13], md[14], md[15]);
77 : }
78 :
79 12 : return ret;
80 : }
81 :
82 : /**
83 : * Returns a malloced string representing the hex representation of
84 : * the SHA-1 hash of the given string.
85 : */
86 : char *
87 4 : mcrypt_SHA1Sum(const char *string, size_t len)
88 : {
89 : SHA1Context c;
90 : uint8_t md[SHA_DIGEST_LENGTH];
91 : char *ret;
92 :
93 : static_assert(SHA_DIGEST_LENGTH == SHA1HashSize, "SHA_DIGEST_LENGTH should be 20");
94 4 : SHA1Reset(&c);
95 4 : SHA1Input(&c, (const uint8_t *) string, (unsigned int) len);
96 4 : SHA1Result(&c, md);
97 :
98 4 : ret = malloc(SHA_DIGEST_LENGTH * 2 + 1);
99 4 : if(ret) {
100 4 : snprintf(ret, SHA_DIGEST_LENGTH * 2 + 1,
101 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
102 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
103 4 : md[0], md[1], md[2], md[3], md[4],
104 4 : md[5], md[6], md[7], md[8], md[9],
105 4 : md[10], md[11], md[12], md[13], md[14],
106 4 : md[15], md[16], md[17], md[18], md[19]);
107 : }
108 :
109 4 : return ret;
110 : }
111 :
112 : /**
113 : * Returns a malloced string representing the hex representation of
114 : * the SHA-224 hash of the given string.
115 : */
116 : char *
117 1 : mcrypt_SHA224Sum(const char *string, size_t len)
118 : {
119 : SHA224Context c;
120 : uint8_t md[SHA224_DIGEST_LENGTH];
121 : char *ret;
122 :
123 : static_assert(SHA224_DIGEST_LENGTH == SHA224HashSize, "SHA224_DIGEST_LENGTH should be 28");
124 1 : SHA224Reset(&c);
125 1 : SHA224Input(&c, (const uint8_t *) string, (unsigned int) len);
126 1 : SHA224Result(&c, md);
127 :
128 1 : ret = malloc(SHA224_DIGEST_LENGTH * 2 + 1);
129 1 : if(ret) {
130 1 : snprintf(ret, SHA224_DIGEST_LENGTH * 2 + 1,
131 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
132 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
133 : "%02x%02x%02x%02x%02x%02x%02x%02x",
134 1 : md[0], md[1], md[2], md[3], md[4],
135 1 : md[5], md[6], md[7], md[8], md[9],
136 1 : md[10], md[11], md[12], md[13], md[14],
137 1 : md[15], md[16], md[17], md[18], md[19],
138 1 : md[20], md[21], md[22], md[23], md[24],
139 1 : md[25], md[26], md[27]);
140 : }
141 :
142 1 : return ret;
143 : }
144 :
145 : /**
146 : * Returns a malloced string representing the hex representation of
147 : * the SHA-256 hash of the given string.
148 : */
149 : char *
150 1 : mcrypt_SHA256Sum(const char *string, size_t len)
151 : {
152 : SHA256Context c;
153 : uint8_t md[SHA256_DIGEST_LENGTH];
154 : char *ret;
155 :
156 : static_assert(SHA256_DIGEST_LENGTH == SHA256HashSize, "SHA256_DIGEST_LENGTH should be 32");
157 1 : SHA256Reset(&c);
158 1 : SHA256Input(&c, (const uint8_t *) string, (unsigned int) len);
159 1 : SHA256Result(&c, md);
160 :
161 1 : ret = malloc(SHA256_DIGEST_LENGTH * 2 + 1);
162 1 : if(ret) {
163 1 : snprintf(ret, SHA256_DIGEST_LENGTH * 2 + 1,
164 : "%02x%02x%02x%02x%02x%02x%02x%02x"
165 : "%02x%02x%02x%02x%02x%02x%02x%02x"
166 : "%02x%02x%02x%02x%02x%02x%02x%02x"
167 : "%02x%02x%02x%02x%02x%02x%02x%02x",
168 1 : md[0], md[1], md[2], md[3], md[4],
169 1 : md[5], md[6], md[7], md[8], md[9],
170 1 : md[10], md[11], md[12], md[13], md[14],
171 1 : md[15], md[16], md[17], md[18], md[19],
172 1 : md[20], md[21], md[22], md[23], md[24],
173 1 : md[25], md[26], md[27], md[28], md[29],
174 1 : md[30], md[31]);
175 : }
176 :
177 1 : return ret;
178 : }
179 :
180 : /**
181 : * Returns a malloced string representing the hex representation of
182 : * the SHA-384 hash of the given string.
183 : */
184 : char *
185 1 : mcrypt_SHA384Sum(const char *string, size_t len)
186 : {
187 : SHA384Context c;
188 : uint8_t md[SHA384_DIGEST_LENGTH];
189 : char *ret;
190 :
191 : static_assert(SHA384_DIGEST_LENGTH == SHA384HashSize, "SHA384_DIGEST_LENGTH should be 48");
192 1 : SHA384Reset(&c);
193 1 : SHA384Input(&c, (const uint8_t *) string, (unsigned int) len);
194 1 : SHA384Result(&c, md);
195 :
196 1 : ret = malloc(SHA384_DIGEST_LENGTH * 2 + 1);
197 1 : if(ret) {
198 1 : snprintf(ret, SHA384_DIGEST_LENGTH * 2 + 1,
199 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
200 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
201 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
202 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
203 : "%02x%02x%02x%02x%02x%02x%02x%02x",
204 1 : md[0], md[1], md[2], md[3], md[4],
205 1 : md[5], md[6], md[7], md[8], md[9],
206 1 : md[10], md[11], md[12], md[13], md[14],
207 1 : md[15], md[16], md[17], md[18], md[19],
208 1 : md[20], md[21], md[22], md[23], md[24],
209 1 : md[25], md[26], md[27], md[28], md[29],
210 1 : md[30], md[31], md[32], md[33], md[34],
211 1 : md[35], md[36], md[37], md[38], md[39],
212 1 : md[40], md[41], md[42], md[43], md[44],
213 1 : md[45], md[46], md[47]);
214 : }
215 :
216 1 : return ret;
217 : }
218 :
219 : /**
220 : * Returns a malloced string representing the hex representation of
221 : * the SHA-512 hash of the given string.
222 : */
223 : char *
224 515 : mcrypt_SHA512Sum(const char *string, size_t len)
225 : {
226 : SHA512Context c;
227 : uint8_t md[SHA512_DIGEST_LENGTH];
228 : char *ret;
229 :
230 : static_assert(SHA512_DIGEST_LENGTH == SHA512HashSize, "SHA512_DIGEST_LENGTH should be 64");
231 515 : SHA512Reset(&c);
232 515 : SHA512Input(&c, (const uint8_t *) string, (unsigned int) len);
233 515 : SHA512Result(&c, md);
234 :
235 515 : ret = malloc(SHA512_DIGEST_LENGTH * 2 + 1);
236 515 : if(ret) {
237 515 : snprintf(ret, SHA512_DIGEST_LENGTH * 2 + 1,
238 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
239 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
240 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
241 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
242 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
243 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
244 : "%02x%02x%02x%02x",
245 515 : md[0], md[1], md[2], md[3], md[4],
246 515 : md[5], md[6], md[7], md[8], md[9],
247 515 : md[10], md[11], md[12], md[13], md[14],
248 515 : md[15], md[16], md[17], md[18], md[19],
249 515 : md[20], md[21], md[22], md[23], md[24],
250 515 : md[25], md[26], md[27], md[28], md[29],
251 515 : md[30], md[31], md[32], md[33], md[34],
252 515 : md[35], md[36], md[37], md[38], md[39],
253 515 : md[40], md[41], md[42], md[43], md[44],
254 515 : md[45], md[46], md[47], md[48], md[49],
255 515 : md[50], md[51], md[52], md[53], md[54],
256 515 : md[55], md[56], md[57], md[58], md[59],
257 515 : md[60], md[61], md[62], md[63]);
258 : }
259 :
260 515 : return ret;
261 : }
262 :
263 : /**
264 : * Returns a malloced string representing the hex representation of
265 : * the RIPEMD-160 hash of the given string.
266 : */
267 : char *
268 1 : mcrypt_RIPEMD160Sum(const char *string, size_t len)
269 : {
270 : RIPEMD160Context c;
271 : uint8_t md[RIPEMD160_DIGEST_LENGTH];
272 : char *ret;
273 :
274 : static_assert(RIPEMD160_DIGEST_LENGTH == 20, "RIPEMD160_DIGEST_LENGTH should be 20");
275 1 : RIPEMD160Reset(&c);
276 1 : RIPEMD160Input(&c, (const uint8_t *) string, (unsigned int) len);
277 1 : RIPEMD160Result(&c, md);
278 :
279 1 : ret = malloc(RIPEMD160_DIGEST_LENGTH * 2 + 1);
280 1 : if(ret) {
281 1 : snprintf(ret, RIPEMD160_DIGEST_LENGTH * 2 + 1,
282 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
283 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
284 1 : md[0], md[1], md[2], md[3], md[4],
285 1 : md[5], md[6], md[7], md[8], md[9],
286 1 : md[10], md[11], md[12], md[13], md[14],
287 1 : md[15], md[16], md[17], md[18], md[19]);
288 : }
289 :
290 1 : return ret;
291 : }
292 :
293 : /**
294 : * Returns a malloced string representing the hex representation of
295 : * the by the backend used hash of the given string.
296 : */
297 : #define concat(x,y,z) x##y##z
298 : #define mcryptsum(h) concat(mcrypt_, h, Sum)
299 : char *
300 290 : mcrypt_BackendSum(const char *string, size_t len)
301 : {
302 290 : return mcryptsum(MONETDB5_PASSWDHASH_TOKEN)(string, len);
303 : }
304 :
305 : /**
306 : * Returns the hash for the given password, challenge and algorithm.
307 : * The hash calculated using the given algorithm over the password
308 : * concatenated with the challenge. The returned string is allocated
309 : * using malloc, and hence should be freed with free by the
310 : * caller. Returns NULL when the given algorithm is not supported.
311 : */
312 : char *
313 6616 : mcrypt_hashPassword(
314 : const char *algo,
315 : const char *password,
316 : const char *challenge)
317 : {
318 : unsigned char md[64]; /* should be SHA512_DIGEST_LENGTH */
319 : char ret[sizeof(md) * 2 + 1];
320 : int len;
321 :
322 : /* make valgrind happy, prevent us from printing garbage afterwards */
323 6616 : memset(md, 0, sizeof(md));
324 :
325 6616 : if (strcmp(algo, "RIPEMD160") == 0) {
326 : RIPEMD160Context c;
327 :
328 6117 : RIPEMD160Reset(&c);
329 6117 : RIPEMD160Input(&c, (const uint8_t *) password, (unsigned int) strlen(password));
330 6117 : RIPEMD160Input(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
331 6117 : RIPEMD160Result(&c, md);
332 :
333 : len = 40;
334 499 : } else if (strcmp(algo, "SHA512") == 0) {
335 : SHA512Context sc;
336 :
337 162 : SHA512Reset(&sc);
338 162 : SHA512Input(&sc, (const uint8_t *) password, (unsigned int) strlen(password));
339 162 : SHA512Input(&sc, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
340 162 : SHA512Result(&sc, md);
341 :
342 : len = 128;
343 337 : } else if (strcmp(algo, "SHA384") == 0) {
344 : SHA384Context c;
345 :
346 0 : SHA384Reset(&c);
347 0 : SHA384Input(&c, (const uint8_t *) password, (unsigned int) strlen(password));
348 0 : SHA384Input(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
349 0 : SHA384Result(&c, md);
350 :
351 : len = 96;
352 337 : } else if (strcmp(algo, "SHA256") == 0) {
353 : SHA256Context c;
354 :
355 0 : SHA256Reset(&c);
356 0 : SHA256Input(&c, (const uint8_t *) password, (unsigned int) strlen(password));
357 0 : SHA256Input(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
358 0 : SHA256Result(&c, md);
359 :
360 : len = 64;
361 337 : } else if (strcmp(algo, "SHA224") == 0) {
362 : SHA224Context c;
363 :
364 0 : SHA224Reset(&c);
365 0 : SHA224Input(&c, (const uint8_t *) password, (unsigned int) strlen(password));
366 0 : SHA224Input(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
367 0 : SHA224Result(&c, md);
368 :
369 : len = 56;
370 337 : } else if (strcmp(algo, "SHA1") == 0) {
371 : SHA1Context c;
372 :
373 337 : SHA1Reset(&c);
374 337 : SHA1Input(&c, (const uint8_t *) password, (unsigned int) strlen(password));
375 337 : SHA1Input(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
376 337 : SHA1Result(&c, md);
377 :
378 : len = 40;
379 0 : } else if (strcmp(algo, "MD5") == 0) {
380 : MD5_CTX c;
381 :
382 0 : MD5Init(&c);
383 0 : MD5Update(&c, (const uint8_t *) password, (unsigned int) strlen(password));
384 0 : MD5Update(&c, (const uint8_t *) challenge, (unsigned int) strlen(challenge));
385 0 : MD5Final(md, &c);
386 :
387 : len = 32;
388 : } else {
389 0 : fprintf(stderr, "Unrecognized hash function (%s) requested.\n", algo);
390 0 : return NULL;
391 : }
392 :
393 6616 : snprintf(ret, sizeof(ret),
394 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
395 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
396 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
397 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
398 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
399 : "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
400 : "%02x%02x%02x%02x",
401 6616 : md[0], md[1], md[2], md[3],
402 6616 : md[4], md[5], md[6], md[7],
403 6616 : md[8], md[9], md[10], md[11],
404 6616 : md[12], md[13], md[14], md[15],
405 6616 : md[16], md[17], md[18], md[19],
406 6616 : md[20], md[21], md[22], md[23],
407 6616 : md[24], md[25], md[26], md[27],
408 6616 : md[28], md[29], md[30], md[31],
409 6616 : md[32], md[33], md[34], md[35],
410 6616 : md[36], md[37], md[38], md[39],
411 6616 : md[40], md[41], md[42], md[43],
412 6616 : md[44], md[45], md[46], md[47],
413 6616 : md[48], md[49], md[50], md[51],
414 6616 : md[52], md[53], md[54], md[55],
415 6616 : md[56], md[57], md[58], md[59],
416 6616 : md[60], md[61], md[62], md[63]);
417 6616 : ret[len] = '\0';
418 :
419 6616 : return strdup(ret);
420 : }
|