LCOV - code coverage report
Current view: top level - common/utils - mcrypt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 185 212 87.3 %
Date: 2024-10-03 20:03:20 Functions: 10 10 100.0 %

          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             : }

Generated by: LCOV version 1.14