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