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 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | #include "monetdb_config.h" |
10 | #include "mcrypt.h" |
11 | #include <string.h> |
12 | |
13 | #ifndef HAVE_EMBEDDED |
14 | /* only provide digest functions if not embedded */ |
15 | #ifdef HAVE_OPENSSL |
16 | #include <openssl/md5.h> |
17 | #include <openssl/sha.h> |
18 | #include <openssl/ripemd.h> |
19 | #else |
20 | #ifdef HAVE_COMMONCRYPTO |
21 | #define COMMON_DIGEST_FOR_OPENSSL |
22 | #include <CommonCrypto/CommonDigest.h> |
23 | #endif |
24 | #endif |
25 | #endif |
26 | |
27 | /** |
28 | * Returns a comma separated list of supported hash algorithms suitable |
29 | * for final hashing by the client. This list contains the smaller |
30 | * (in char size) hashes. |
31 | * The returned string is malloced and should be freed. |
32 | */ |
33 | const char * |
34 | mcrypt_getHashAlgorithms(void) |
35 | { |
36 | /* Currently, four "hashes" are available, RIPEMD160, SHA-2, SHA-1 |
37 | * and MD5. Previous versions supported UNIX crypt and plain text |
38 | * login, but those were removed when SHA-1 became mandatory for |
39 | * hashing the plain password in wire protocol version 9. |
40 | * Better/stronger/faster algorithms can be added in the future upon |
41 | * desire. |
42 | */ |
43 | static const char *algorithms = |
44 | "PROT10" |
45 | #ifdef HAVE_RIPEMD160_UPDATE |
46 | ",RIPEMD160" |
47 | #endif |
48 | #ifdef HAVE_SHA256_UPDATE |
49 | ",SHA256" |
50 | #endif |
51 | #ifdef HAVE_SHA1_UPDATE |
52 | ",SHA1" |
53 | #endif |
54 | #ifdef HAVE_MD5_UPDATE |
55 | ",MD5" |
56 | #endif |
57 | #ifdef HAVE_LIBSNAPPY |
58 | ",COMPRESSION_SNAPPY" |
59 | #endif |
60 | #ifdef HAVE_LIBLZ4 |
61 | ",COMPRESSION_LZ4" |
62 | #endif |
63 | ; |
64 | return algorithms; |
65 | } |
66 | |
67 | /** |
68 | * Returns a malloced string representing the hex representation of |
69 | * the MD5 hash of the given string. |
70 | */ |
71 | char * |
72 | mcrypt_MD5Sum(const char *string, size_t len) |
73 | { |
74 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_MD5_UPDATE) |
75 | MD5_CTX c; |
76 | unsigned char md[MD5_DIGEST_LENGTH]; |
77 | char *ret; |
78 | |
79 | static_assert(MD5_DIGEST_LENGTH == 16, "MD5_DIGEST_LENGTH should be 16" ); |
80 | MD5_Init(&c); |
81 | MD5_Update(&c, string, len); |
82 | MD5_Final(md, &c); |
83 | |
84 | ret = malloc(MD5_DIGEST_LENGTH * 2 + 1); |
85 | if(ret) { |
86 | snprintf(ret, MD5_DIGEST_LENGTH * 2 + 1, |
87 | "%02x%02x%02x%02x%02x%02x%02x%02x" |
88 | "%02x%02x%02x%02x%02x%02x%02x%02x" , |
89 | md[0], md[1], md[2], md[3], |
90 | md[4], md[5], md[6], md[7], |
91 | md[8], md[9], md[10], md[11], |
92 | md[12], md[13], md[14], md[15]); |
93 | } |
94 | |
95 | return ret; |
96 | #else |
97 | (void) string; |
98 | (void) len; |
99 | fprintf(stderr, "No MD5 digest function available.\n" ); |
100 | return NULL; |
101 | #endif |
102 | } |
103 | |
104 | /** |
105 | * Returns a malloced string representing the hex representation of |
106 | * the SHA-1 hash of the given string. |
107 | */ |
108 | char * |
109 | mcrypt_SHA1Sum(const char *string, size_t len) |
110 | { |
111 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_SHA1_UPDATE) |
112 | SHA_CTX c; |
113 | unsigned char md[SHA_DIGEST_LENGTH]; |
114 | char *ret; |
115 | |
116 | static_assert(SHA_DIGEST_LENGTH == 20, "SHA_DIGEST_LENGTH should be 20" ); |
117 | SHA1_Init(&c); |
118 | SHA1_Update(&c, string, len); |
119 | SHA1_Final(md, &c); |
120 | |
121 | ret = malloc(SHA_DIGEST_LENGTH * 2 + 1); |
122 | if(ret) { |
123 | snprintf(ret, SHA_DIGEST_LENGTH * 2 + 1, |
124 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
125 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" , |
126 | md[0], md[1], md[2], md[3], md[4], |
127 | md[5], md[6], md[7], md[8], md[9], |
128 | md[10], md[11], md[12], md[13], md[14], |
129 | md[15], md[16], md[17], md[18], md[19]); |
130 | } |
131 | |
132 | return ret; |
133 | #else |
134 | (void) string; |
135 | (void) len; |
136 | fprintf(stderr, "No SHA1 digest function available.\n" ); |
137 | return NULL; |
138 | #endif |
139 | } |
140 | |
141 | /** |
142 | * Returns a malloced string representing the hex representation of |
143 | * the SHA-224 hash of the given string. |
144 | */ |
145 | char * |
146 | mcrypt_SHA224Sum(const char *string, size_t len) |
147 | { |
148 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_SHA224_UPDATE) |
149 | SHA256_CTX c; |
150 | unsigned char md[SHA224_DIGEST_LENGTH]; |
151 | char *ret; |
152 | |
153 | static_assert(SHA224_DIGEST_LENGTH == 28, "SHA224_DIGEST_LENGTH should be 28" ); |
154 | SHA224_Init(&c); |
155 | SHA224_Update(&c, string, len); |
156 | SHA224_Final(md, &c); |
157 | |
158 | ret = malloc(SHA224_DIGEST_LENGTH * 2 + 1); |
159 | if(ret) { |
160 | snprintf(ret, SHA224_DIGEST_LENGTH * 2 + 1, |
161 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
162 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
163 | "%02x%02x%02x%02x%02x%02x%02x%02x" , |
164 | md[0], md[1], md[2], md[3], md[4], |
165 | md[5], md[6], md[7], md[8], md[9], |
166 | md[10], md[11], md[12], md[13], md[14], |
167 | md[15], md[16], md[17], md[18], md[19], |
168 | md[20], md[21], md[22], md[23], md[24], |
169 | md[25], md[26], md[27]); |
170 | } |
171 | |
172 | return ret; |
173 | #else |
174 | (void) string; |
175 | (void) len; |
176 | fprintf(stderr, "No SHA224 digest function available.\n" ); |
177 | return NULL; |
178 | #endif |
179 | } |
180 | |
181 | /** |
182 | * Returns a malloced string representing the hex representation of |
183 | * the SHA-256 hash of the given string. |
184 | */ |
185 | char * |
186 | mcrypt_SHA256Sum(const char *string, size_t len) |
187 | { |
188 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_SHA256_UPDATE) |
189 | SHA256_CTX c; |
190 | unsigned char md[SHA256_DIGEST_LENGTH]; |
191 | char *ret; |
192 | |
193 | static_assert(SHA256_DIGEST_LENGTH == 32, "SHA256_DIGEST_LENGTH should be 32" ); |
194 | SHA256_Init(&c); |
195 | SHA256_Update(&c, string, len); |
196 | SHA256_Final(md, &c); |
197 | |
198 | ret = malloc(SHA256_DIGEST_LENGTH * 2 + 1); |
199 | if(ret) { |
200 | snprintf(ret, SHA256_DIGEST_LENGTH * 2 + 1, |
201 | "%02x%02x%02x%02x%02x%02x%02x%02x" |
202 | "%02x%02x%02x%02x%02x%02x%02x%02x" |
203 | "%02x%02x%02x%02x%02x%02x%02x%02x" |
204 | "%02x%02x%02x%02x%02x%02x%02x%02x" , |
205 | md[0], md[1], md[2], md[3], md[4], |
206 | md[5], md[6], md[7], md[8], md[9], |
207 | md[10], md[11], md[12], md[13], md[14], |
208 | md[15], md[16], md[17], md[18], md[19], |
209 | md[20], md[21], md[22], md[23], md[24], |
210 | md[25], md[26], md[27], md[28], md[29], |
211 | md[30], md[31]); |
212 | } |
213 | |
214 | return ret; |
215 | #else |
216 | (void) string; |
217 | (void) len; |
218 | fprintf(stderr, "No SHA256 digest function available.\n" ); |
219 | return NULL; |
220 | #endif |
221 | } |
222 | |
223 | /** |
224 | * Returns a malloced string representing the hex representation of |
225 | * the SHA-384 hash of the given string. |
226 | */ |
227 | char * |
228 | mcrypt_SHA384Sum(const char *string, size_t len) |
229 | { |
230 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_SHA384_UPDATE) |
231 | SHA512_CTX c; |
232 | unsigned char md[SHA384_DIGEST_LENGTH]; |
233 | char *ret; |
234 | |
235 | static_assert(SHA384_DIGEST_LENGTH == 48, "SHA384_DIGEST_LENGTH should be 48" ); |
236 | SHA384_Init(&c); |
237 | SHA384_Update(&c, string, len); |
238 | SHA384_Final(md, &c); |
239 | |
240 | ret = malloc(SHA384_DIGEST_LENGTH * 2 + 1); |
241 | if(ret) { |
242 | snprintf(ret, SHA384_DIGEST_LENGTH * 2 + 1, |
243 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
244 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
245 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
246 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
247 | "%02x%02x%02x%02x%02x%02x%02x%02x" , |
248 | md[0], md[1], md[2], md[3], md[4], |
249 | md[5], md[6], md[7], md[8], md[9], |
250 | md[10], md[11], md[12], md[13], md[14], |
251 | md[15], md[16], md[17], md[18], md[19], |
252 | md[20], md[21], md[22], md[23], md[24], |
253 | md[25], md[26], md[27], md[28], md[29], |
254 | md[30], md[31], md[32], md[33], md[34], |
255 | md[35], md[36], md[37], md[38], md[39], |
256 | md[40], md[41], md[42], md[43], md[44], |
257 | md[45], md[46], md[47]); |
258 | } |
259 | |
260 | return ret; |
261 | #else |
262 | (void) string; |
263 | (void) len; |
264 | fprintf(stderr, "No SHA384 digest function available.\n" ); |
265 | return NULL; |
266 | #endif |
267 | } |
268 | |
269 | /** |
270 | * Returns a malloced string representing the hex representation of |
271 | * the SHA-512 hash of the given string. |
272 | */ |
273 | char * |
274 | mcrypt_SHA512Sum(const char *string, size_t len) |
275 | { |
276 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_SHA512_UPDATE) |
277 | SHA512_CTX c; |
278 | unsigned char md[SHA512_DIGEST_LENGTH]; |
279 | char *ret; |
280 | |
281 | static_assert(SHA512_DIGEST_LENGTH == 64, "SHA512_DIGEST_LENGTH should be 64" ); |
282 | SHA512_Init(&c); |
283 | SHA512_Update(&c, string, len); |
284 | SHA512_Final(md, &c); |
285 | |
286 | ret = malloc(SHA512_DIGEST_LENGTH * 2 + 1); |
287 | if(ret) { |
288 | snprintf(ret, SHA512_DIGEST_LENGTH * 2 + 1, |
289 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
290 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
291 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
292 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
293 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
294 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
295 | "%02x%02x%02x%02x" , |
296 | md[0], md[1], md[2], md[3], md[4], |
297 | md[5], md[6], md[7], md[8], md[9], |
298 | md[10], md[11], md[12], md[13], md[14], |
299 | md[15], md[16], md[17], md[18], md[19], |
300 | md[20], md[21], md[22], md[23], md[24], |
301 | md[25], md[26], md[27], md[28], md[29], |
302 | md[30], md[31], md[32], md[33], md[34], |
303 | md[35], md[36], md[37], md[38], md[39], |
304 | md[40], md[41], md[42], md[43], md[44], |
305 | md[45], md[46], md[47], md[48], md[49], |
306 | md[50], md[51], md[52], md[53], md[54], |
307 | md[55], md[56], md[57], md[58], md[59], |
308 | md[60], md[61], md[62], md[63]); |
309 | } |
310 | |
311 | return ret; |
312 | #else |
313 | (void) string; |
314 | (void) len; |
315 | fprintf(stderr, "No SHA512 digest function available.\n" ); |
316 | return NULL; |
317 | #endif |
318 | } |
319 | |
320 | /** |
321 | * Returns a malloced string representing the hex representation of |
322 | * the RIPEMD-160 hash of the given string. |
323 | */ |
324 | char * |
325 | mcrypt_RIPEMD160Sum(const char *string, size_t len) |
326 | { |
327 | #if !defined(HAVE_EMBEDDED) && defined(HAVE_RIPEMD160_UPDATE) |
328 | RIPEMD160_CTX c; |
329 | unsigned char md[RIPEMD160_DIGEST_LENGTH]; |
330 | char *ret; |
331 | |
332 | static_assert(RIPEMD160_DIGEST_LENGTH == 20, "RIPEMD160_DIGEST_LENGTH should be 20" ); |
333 | RIPEMD160_Init(&c); |
334 | RIPEMD160_Update(&c, string, len); |
335 | RIPEMD160_Final(md, &c); |
336 | |
337 | ret = malloc(RIPEMD160_DIGEST_LENGTH * 2 + 1); |
338 | if(ret) { |
339 | snprintf(ret, RIPEMD160_DIGEST_LENGTH * 2 + 1, |
340 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
341 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" , |
342 | md[0], md[1], md[2], md[3], md[4], |
343 | md[5], md[6], md[7], md[8], md[9], |
344 | md[10], md[11], md[12], md[13], md[14], |
345 | md[15], md[16], md[17], md[18], md[19]); |
346 | } |
347 | |
348 | return ret; |
349 | #else |
350 | (void) string; |
351 | (void) len; |
352 | fprintf(stderr, "No RIPEMD160 digest function available.\n" ); |
353 | return NULL; |
354 | #endif |
355 | } |
356 | |
357 | /** |
358 | * Returns a malloced string representing the hex representation of |
359 | * the by the backend used hash of the given string. |
360 | */ |
361 | #define concat(x,y,z) x##y##z |
362 | #define mcryptsum(h) concat(mcrypt_, h, Sum) |
363 | char * |
364 | mcrypt_BackendSum(const char *string, size_t len) |
365 | { |
366 | #if !defined(HAVE_EMBEDDED) && (defined(HAVE_OPENSSL) || defined(HAVE_COMMONCRYPTO)) |
367 | return mcryptsum(MONETDB5_PASSWDHASH_TOKEN)(string, len); |
368 | #else |
369 | (void) string; |
370 | (void) len; |
371 | fprintf(stderr, "No digest function available.\n" ); |
372 | return NULL; |
373 | #endif |
374 | } |
375 | |
376 | /** |
377 | * Returns the hash for the given password, challenge and algorithm. |
378 | * The hash calculated using the given algorithm over the password |
379 | * concatenated with the challenge. The returned string is allocated |
380 | * using malloc, and hence should be freed with free by the |
381 | * caller. Returns NULL when the given algorithm is not supported. |
382 | */ |
383 | char * |
384 | mcrypt_hashPassword( |
385 | const char *algo, |
386 | const char *password, |
387 | const char *challenge) |
388 | { |
389 | #if !defined(HAVE_EMBEDDED) && (defined(HAVE_OPENSSL) || defined(HAVE_COMMONCRYPTO)) |
390 | unsigned char md[64]; /* should be SHA512_DIGEST_LENGTH */ |
391 | char ret[sizeof(md) * 2 + 1]; |
392 | int len; |
393 | |
394 | /* make valgrind happy, prevent us from printing garbage afterwards */ |
395 | memset(md, 0, sizeof(md)); |
396 | |
397 | #ifdef HAVE_RIPEMD160_UPDATE |
398 | if (strcmp(algo, "RIPEMD160" ) == 0) { |
399 | RIPEMD160_CTX c; |
400 | |
401 | RIPEMD160_Init(&c); |
402 | RIPEMD160_Update(&c, password, strlen(password)); |
403 | RIPEMD160_Update(&c, challenge, strlen(challenge)); |
404 | RIPEMD160_Final(md, &c); |
405 | |
406 | len = 40; |
407 | } else |
408 | #endif |
409 | #ifdef HAVE_SHA512_UPDATE |
410 | if (strcmp(algo, "SHA512" ) == 0) { |
411 | SHA512_CTX c; |
412 | |
413 | SHA512_Init(&c); |
414 | SHA512_Update(&c, password, strlen(password)); |
415 | SHA512_Update(&c, challenge, strlen(challenge)); |
416 | SHA512_Final(md, &c); |
417 | |
418 | len = 128; |
419 | } else |
420 | #endif |
421 | #ifdef HAVE_SHA384_UPDATE |
422 | if (strcmp(algo, "SHA384" ) == 0) { |
423 | SHA512_CTX c; |
424 | |
425 | SHA384_Init(&c); |
426 | SHA384_Update(&c, password, strlen(password)); |
427 | SHA384_Update(&c, challenge, strlen(challenge)); |
428 | SHA384_Final(md, &c); |
429 | |
430 | len = 96; |
431 | } else |
432 | #endif |
433 | #ifdef HAVE_SHA256_UPDATE |
434 | if (strcmp(algo, "SHA256" ) == 0) { |
435 | SHA256_CTX c; |
436 | |
437 | SHA256_Init(&c); |
438 | SHA256_Update(&c, password, strlen(password)); |
439 | SHA256_Update(&c, challenge, strlen(challenge)); |
440 | SHA256_Final(md, &c); |
441 | |
442 | len = 64; |
443 | } else |
444 | #endif |
445 | #ifdef HAVE_SHA224_UPDATE |
446 | if (strcmp(algo, "SHA224" ) == 0) { |
447 | SHA256_CTX c; |
448 | |
449 | SHA224_Init(&c); |
450 | SHA224_Update(&c, password, strlen(password)); |
451 | SHA224_Update(&c, challenge, strlen(challenge)); |
452 | SHA224_Final(md, &c); |
453 | |
454 | len = 56; |
455 | } else |
456 | #endif |
457 | #ifdef HAVE_SHA1_UPDATE |
458 | if (strcmp(algo, "SHA1" ) == 0) { |
459 | SHA_CTX c; |
460 | |
461 | SHA1_Init(&c); |
462 | SHA1_Update(&c, password, strlen(password)); |
463 | SHA1_Update(&c, challenge, strlen(challenge)); |
464 | SHA1_Final(md, &c); |
465 | |
466 | len = 40; |
467 | } else |
468 | #endif |
469 | #ifdef HAVE_MD5_UPDATE |
470 | if (strcmp(algo, "MD5" ) == 0) { |
471 | MD5_CTX c; |
472 | |
473 | MD5_Init(&c); |
474 | MD5_Update(&c, password, strlen(password)); |
475 | MD5_Update(&c, challenge, strlen(challenge)); |
476 | MD5_Final(md, &c); |
477 | |
478 | len = 32; |
479 | } else |
480 | #endif |
481 | #endif |
482 | { |
483 | (void) algo; |
484 | (void) password; |
485 | (void) challenge; |
486 | fprintf(stderr, "MonetDB was built without OpenSSL, but what you are trying to do requires it.\n" ); |
487 | return NULL; |
488 | } |
489 | |
490 | #if !defined(HAVE_EMBEDDED) && (defined(HAVE_OPENSSL) || defined(HAVE_COMMONCRYPTO)) |
491 | snprintf(ret, sizeof(ret), |
492 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
493 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
494 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
495 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
496 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
497 | "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" |
498 | "%02x%02x%02x%02x" , |
499 | md[0], md[1], md[2], md[3], |
500 | md[4], md[5], md[6], md[7], |
501 | md[8], md[9], md[10], md[11], |
502 | md[12], md[13], md[14], md[15], |
503 | md[16], md[17], md[18], md[19], |
504 | md[20], md[21], md[22], md[23], |
505 | md[24], md[25], md[26], md[27], |
506 | md[28], md[29], md[30], md[31], |
507 | md[32], md[33], md[34], md[35], |
508 | md[36], md[37], md[38], md[39], |
509 | md[40], md[41], md[42], md[43], |
510 | md[44], md[45], md[46], md[47], |
511 | md[48], md[49], md[50], md[51], |
512 | md[52], md[53], md[54], md[55], |
513 | md[56], md[57], md[58], md[59], |
514 | md[60], md[61], md[62], md[63]); |
515 | ret[len] = '\0'; |
516 | |
517 | return strdup(ret); |
518 | #endif |
519 | } |
520 | |