LCOV - code coverage report
Current view: top level - src/common - md5_common.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 58.9 % 56 33
Test Date: 2026-01-26 10:56:24 Functions: 75.0 % 4 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 35.0 % 20 7

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * md5_common.c
       4                 :             :  *        Routines shared between all MD5 implementations used for encrypted
       5                 :             :  *        passwords.
       6                 :             :  *
       7                 :             :  * Sverre H. Huseby <sverrehu@online.no>
       8                 :             :  *
       9                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      10                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      11                 :             :  *
      12                 :             :  * IDENTIFICATION
      13                 :             :  *        src/common/md5_common.c
      14                 :             :  *
      15                 :             :  *-------------------------------------------------------------------------
      16                 :             :  */
      17                 :             : 
      18                 :             : #ifndef FRONTEND
      19                 :             : #include "postgres.h"
      20                 :             : #else
      21                 :             : #include "postgres_fe.h"
      22                 :             : #endif
      23                 :             : 
      24                 :             : #include "common/cryptohash.h"
      25                 :             : #include "common/md5.h"
      26                 :             : 
      27                 :             : static void
      28                 :          20 : bytesToHex(uint8 b[16], char *s)
      29                 :             : {
      30                 :             :         static const char *hex = "0123456789abcdef";
      31                 :          20 :         int                     q,
      32                 :             :                                 w;
      33                 :             : 
      34         [ +  + ]:         340 :         for (q = 0, w = 0; q < 16; q++)
      35                 :             :         {
      36                 :         320 :                 s[w++] = hex[(b[q] >> 4) & 0x0F];
      37                 :         320 :                 s[w++] = hex[b[q] & 0x0F];
      38                 :         320 :         }
      39                 :          20 :         s[w] = '\0';
      40                 :          20 : }
      41                 :             : 
      42                 :             : /*
      43                 :             :  *      pg_md5_hash
      44                 :             :  *
      45                 :             :  *      Calculates the MD5 sum of the bytes in a buffer.
      46                 :             :  *
      47                 :             :  *      SYNOPSIS          #include "md5.h"
      48                 :             :  *                                bool pg_md5_hash(const void *buff, size_t len, char *hexsum,
      49                 :             :  *                                                 const char **errstr)
      50                 :             :  *
      51                 :             :  *      INPUT             buff    the buffer containing the bytes that you want
      52                 :             :  *                                                the MD5 sum of.
      53                 :             :  *                                len     number of bytes in the buffer.
      54                 :             :  *
      55                 :             :  *      OUTPUT            hexsum  the MD5 sum as a '\0'-terminated string of
      56                 :             :  *                                                hexadecimal digits.  an MD5 sum is 16 bytes long.
      57                 :             :  *                                                each byte is represented by two hexadecimal
      58                 :             :  *                                                characters.  you thus need to provide an array
      59                 :             :  *                                                of 33 characters, including the trailing '\0'.
      60                 :             :  *
      61                 :             :  *                                errstr  filled with a constant-string error message
      62                 :             :  *                                                on failure return; NULL on success.
      63                 :             :  *
      64                 :             :  *      RETURNS           false on failure (out of memory for internal buffers
      65                 :             :  *                                or MD5 computation failure) or true on success.
      66                 :             :  *
      67                 :             :  *      STANDARDS         MD5 is described in RFC 1321.
      68                 :             :  *
      69                 :             :  *      AUTHOR            Sverre H. Huseby <sverrehu@online.no>
      70                 :             :  *
      71                 :             :  */
      72                 :             : 
      73                 :             : bool
      74                 :          20 : pg_md5_hash(const void *buff, size_t len, char *hexsum, const char **errstr)
      75                 :             : {
      76                 :          20 :         uint8           sum[MD5_DIGEST_LENGTH];
      77                 :          20 :         pg_cryptohash_ctx *ctx;
      78                 :             : 
      79                 :          20 :         *errstr = NULL;
      80                 :          20 :         ctx = pg_cryptohash_create(PG_MD5);
      81         [ +  - ]:          20 :         if (ctx == NULL)
      82                 :             :         {
      83                 :           0 :                 *errstr = pg_cryptohash_error(NULL);    /* returns OOM */
      84                 :           0 :                 return false;
      85                 :             :         }
      86                 :             : 
      87         [ +  - ]:          20 :         if (pg_cryptohash_init(ctx) < 0 ||
      88   [ +  -  -  + ]:          20 :                 pg_cryptohash_update(ctx, buff, len) < 0 ||
      89                 :          20 :                 pg_cryptohash_final(ctx, sum, sizeof(sum)) < 0)
      90                 :             :         {
      91                 :           0 :                 *errstr = pg_cryptohash_error(ctx);
      92                 :           0 :                 pg_cryptohash_free(ctx);
      93                 :           0 :                 return false;
      94                 :             :         }
      95                 :             : 
      96                 :          20 :         bytesToHex(sum, hexsum);
      97                 :          20 :         pg_cryptohash_free(ctx);
      98                 :          20 :         return true;
      99                 :          20 : }
     100                 :             : 
     101                 :             : /*
     102                 :             :  * pg_md5_binary
     103                 :             :  *
     104                 :             :  * As above, except that the MD5 digest is returned as a binary string
     105                 :             :  * (of size MD5_DIGEST_LENGTH) rather than being converted to ASCII hex.
     106                 :             :  */
     107                 :             : bool
     108                 :           0 : pg_md5_binary(const void *buff, size_t len, uint8 *outbuf, const char **errstr)
     109                 :             : {
     110                 :           0 :         pg_cryptohash_ctx *ctx;
     111                 :             : 
     112                 :           0 :         *errstr = NULL;
     113                 :           0 :         ctx = pg_cryptohash_create(PG_MD5);
     114         [ #  # ]:           0 :         if (ctx == NULL)
     115                 :             :         {
     116                 :           0 :                 *errstr = pg_cryptohash_error(NULL);    /* returns OOM */
     117                 :           0 :                 return false;
     118                 :             :         }
     119                 :             : 
     120         [ #  # ]:           0 :         if (pg_cryptohash_init(ctx) < 0 ||
     121   [ #  #  #  # ]:           0 :                 pg_cryptohash_update(ctx, buff, len) < 0 ||
     122                 :           0 :                 pg_cryptohash_final(ctx, outbuf, MD5_DIGEST_LENGTH) < 0)
     123                 :             :         {
     124                 :           0 :                 *errstr = pg_cryptohash_error(ctx);
     125                 :           0 :                 pg_cryptohash_free(ctx);
     126                 :           0 :                 return false;
     127                 :             :         }
     128                 :             : 
     129                 :           0 :         pg_cryptohash_free(ctx);
     130                 :           0 :         return true;
     131                 :           0 : }
     132                 :             : 
     133                 :             : 
     134                 :             : /*
     135                 :             :  * Computes MD5 checksum of "passwd" (a null-terminated string) followed
     136                 :             :  * by "salt" (which need not be null-terminated).
     137                 :             :  *
     138                 :             :  * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
     139                 :             :  * Hence, the output buffer "buf" must be at least 36 bytes long.
     140                 :             :  *
     141                 :             :  * Returns true if okay, false on error with *errstr providing some
     142                 :             :  * error context.
     143                 :             :  */
     144                 :             : bool
     145                 :           6 : pg_md5_encrypt(const char *passwd, const uint8 *salt, size_t salt_len,
     146                 :             :                            char *buf, const char **errstr)
     147                 :             : {
     148                 :           6 :         size_t          passwd_len = strlen(passwd);
     149                 :             : 
     150                 :             :         /* +1 here is just to avoid risk of unportable malloc(0) */
     151                 :           6 :         char       *crypt_buf = malloc(passwd_len + salt_len + 1);
     152                 :           6 :         bool            ret;
     153                 :             : 
     154         [ +  - ]:           6 :         if (!crypt_buf)
     155                 :             :         {
     156                 :           0 :                 *errstr = _("out of memory");
     157                 :           0 :                 return false;
     158                 :             :         }
     159                 :             : 
     160                 :             :         /*
     161                 :             :          * Place salt at the end because it may be known by users trying to crack
     162                 :             :          * the MD5 output.
     163                 :             :          */
     164                 :           6 :         memcpy(crypt_buf, passwd, passwd_len);
     165                 :           6 :         memcpy(crypt_buf + passwd_len, salt, salt_len);
     166                 :             : 
     167                 :           6 :         strcpy(buf, "md5");
     168                 :           6 :         ret = pg_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3, errstr);
     169                 :             : 
     170                 :           6 :         free(crypt_buf);
     171                 :             : 
     172                 :           6 :         return ret;
     173                 :           6 : }
        

Generated by: LCOV version 2.3.2-1