LCOV - code coverage report
Current view: top level - contrib/pgcrypto - crypt-sha.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 83.0 % 206 171
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 1 1
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 63.2 % 272 172

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/pgcrypto/crypt-sha.c
       3                 :             :  *
       4                 :             :  * This implements shacrypt password hash functions and follows the
       5                 :             :  * public available reference implementation from
       6                 :             :  *
       7                 :             :  * https://www.akkadia.org/drepper/SHA-crypt.txt
       8                 :             :  *
       9                 :             :  * This code is public domain.
      10                 :             :  *
      11                 :             :  * Please see the inline comments for details about the algorithm.
      12                 :             :  *
      13                 :             :  * Basically the following code implements password hashing with sha256 and
      14                 :             :  * sha512 digest via OpenSSL. Additionally, an extended salt generation (see
      15                 :             :  * crypt-gensalt.c for details) is provided, which generates a salt suitable
      16                 :             :  * for either sha256crypt and sha512crypt password hash generation.
      17                 :             :  *
      18                 :             :  * Official identifiers for suitable password hashes used in salts are
      19                 :             :  * 5 : sha256crypt and
      20                 :             :  * 6 : sha512crypt
      21                 :             :  *
      22                 :             :  * The hashing code below supports and uses salt length up to 16 bytes. Longer
      23                 :             :  * input is possible, but any additional byte of the input is disregarded.
      24                 :             :  * gen_salt(), when called with a sha256crypt or sha512crypt identifier will
      25                 :             :  * always generate a 16 byte long salt string.
      26                 :             :  *
      27                 :             :  * Output is compatible with any sha256crypt and sha512crypt output
      28                 :             :  * generated by e.g. OpenSSL or libc crypt().
      29                 :             :  *
      30                 :             :  * The described algorithm uses default computing rounds of 5000. Currently,
      31                 :             :  * even when no specific rounds specification is used, we always explicitly
      32                 :             :  * print out the rounds option flag with the final hash password string.
      33                 :             :  *
      34                 :             :  * The length of the specific password hash (without magic bytes and salt
      35                 :             :  * string) is:
      36                 :             :  *
      37                 :             :  * sha256crypt: 43 bytes and
      38                 :             :  * sha512crypt: 86 bytes.
      39                 :             :  *
      40                 :             :  * Overall hashed password length is:
      41                 :             :  *
      42                 :             :  * sha256crypt: 80 bytes and
      43                 :             :  * sha512crypt: 123 bytes
      44                 :             :  *
      45                 :             :  */
      46                 :             : #include "postgres.h"
      47                 :             : 
      48                 :             : #include "common/string.h"
      49                 :             : #include "mb/pg_wchar.h"
      50                 :             : #include "miscadmin.h"
      51                 :             : 
      52                 :             : #include "px-crypt.h"
      53                 :             : #include "px.h"
      54                 :             : 
      55                 :             : typedef enum
      56                 :             : {
      57                 :             :     PGCRYPTO_SHA256CRYPT = 0,
      58                 :             :     PGCRYPTO_SHA512CRYPT = 1,
      59                 :             :     PGCRYPTO_SHA_UNKOWN
      60                 :             : } PGCRYPTO_SHA_t;
      61                 :             : 
      62                 :             : static const char _crypt_itoa64[64 + 1] =
      63                 :             : "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      64                 :             : 
      65                 :             : /*
      66                 :             :  * Modern UNIX password, based on SHA crypt hashes
      67                 :             :  */
      68                 :             : char *
      69                 :          26 : px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstlen)
      70                 :             : {
      71                 :             :     static const char rounds_prefix[] = "rounds=";
      72                 :             :     static const char *magic_bytes[2] = {"$5$", "$6$"};
      73                 :             : 
      74                 :             :     /* Used to create the password hash string */
      75                 :          26 :     StringInfo  out_buf = NULL;
      76                 :             : 
      77                 :          26 :     PGCRYPTO_SHA_t type = PGCRYPTO_SHA_UNKOWN;
      78                 :          26 :     PX_MD      *digestA = NULL;
      79                 :          26 :     PX_MD      *digestB = NULL;
      80                 :             :     int         err;
      81                 :             : 
      82                 :             :     const char *dec_salt_binary;    /* pointer into the real salt string */
      83                 :          26 :     StringInfo  decoded_salt = NULL;    /* decoded salt string */
      84                 :             :     unsigned char sha_buf[PX_SHACRYPT_DIGEST_MAX_LEN];
      85                 :             : 
      86                 :             :     /* temporary buffer for digests */
      87                 :             :     unsigned char sha_buf_tmp[PX_SHACRYPT_DIGEST_MAX_LEN];
      88                 :          26 :     char        rounds_custom = 0;
      89                 :          26 :     char       *p_bytes = NULL;
      90                 :          26 :     char       *s_bytes = NULL;
      91                 :          26 :     char       *cp = NULL;
      92                 :          26 :     const char *fp = NULL;      /* intermediate pointer within salt string */
      93                 :          26 :     const char *ep = NULL;      /* holds pointer to the end of the salt string */
      94                 :          26 :     size_t      buf_size = 0;   /* buffer size for sha256crypt/sha512crypt */
      95                 :             :     unsigned int block;         /* number of bytes processed */
      96                 :          26 :     uint32      rounds = PX_SHACRYPT_ROUNDS_DEFAULT;
      97                 :             :     unsigned int len,
      98                 :          26 :                 salt_len = 0;
      99                 :             : 
     100                 :             :     /* Sanity checks */
     101         [ -  + ]:          26 :     if (!passwd)
     102                 :           0 :         return NULL;
     103                 :             : 
     104         [ -  + ]:          26 :     if (pw == NULL)
     105         [ #  # ]:           0 :         elog(ERROR, "null value for password rejected");
     106                 :             : 
     107         [ -  + ]:          26 :     if (salt == NULL)
     108         [ #  # ]:           0 :         elog(ERROR, "null value for salt rejected");
     109                 :             : 
     110                 :             :     /*
     111                 :             :      * Make sure result buffers are large enough.
     112                 :             :      */
     113         [ -  + ]:          26 :     if (dstlen < PX_SHACRYPT_BUF_LEN)
     114         [ #  # ]:           0 :         elog(ERROR, "insufficient result buffer size to encrypt password");
     115                 :             : 
     116                 :             :     /* Init result buffer */
     117                 :          26 :     out_buf = makeStringInfoExt(PX_SHACRYPT_BUF_LEN);
     118                 :          26 :     decoded_salt = makeStringInfoExt(PX_SHACRYPT_SALT_MAX_LEN);
     119                 :             : 
     120                 :             :     /* Init contents of buffers properly */
     121                 :          26 :     memset(&sha_buf, '\0', sizeof(sha_buf));
     122                 :          26 :     memset(&sha_buf_tmp, '\0', sizeof(sha_buf_tmp));
     123                 :             : 
     124                 :             :     /*
     125                 :             :      * Decode the salt string. We need to know how many rounds and which
     126                 :             :      * digest we have to use to hash the password.
     127                 :             :      */
     128                 :          26 :     len = strlen(pw);
     129                 :          26 :     dec_salt_binary = salt;
     130                 :             : 
     131                 :             :     /*
     132                 :             :      * Analyze and prepare the salt string
     133                 :             :      *
     134                 :             :      * The magic string should be specified in the first three bytes of the
     135                 :             :      * salt string.  Do some sanity checks first.
     136                 :             :      */
     137         [ -  + ]:          26 :     if (strlen(dec_salt_binary) < 3)
     138         [ #  # ]:           0 :         ereport(ERROR,
     139                 :             :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     140                 :             :                 errmsg("invalid salt"));
     141                 :             : 
     142                 :             :     /*
     143                 :             :      * Check format of magic bytes. These should define either 5=sha256crypt
     144                 :             :      * or 6=sha512crypt in the second byte, enclosed by ascii dollar signs.
     145                 :             :      */
     146   [ +  -  -  + ]:          26 :     if ((dec_salt_binary[0] != '$') || (dec_salt_binary[2] != '$'))
     147         [ #  # ]:           0 :         ereport(ERROR,
     148                 :             :                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     149                 :             :                 errmsg("invalid format of salt"),
     150                 :             :                 errhint("Magic byte format for shacrypt is either \"$5$\" or \"$6$\"."));
     151                 :             : 
     152                 :             :     /*
     153                 :             :      * Check magic byte for supported shacrypt digest.
     154                 :             :      *
     155                 :             :      * We're just interested in the very first 3 bytes of the salt string,
     156                 :             :      * since this defines the digest length to use.
     157                 :             :      */
     158         [ +  + ]:          26 :     if (strncmp(dec_salt_binary, magic_bytes[0], strlen(magic_bytes[0])) == 0)
     159                 :             :     {
     160                 :          13 :         type = PGCRYPTO_SHA256CRYPT;
     161                 :          13 :         dec_salt_binary += strlen(magic_bytes[0]);
     162                 :             :     }
     163         [ +  - ]:          13 :     else if (strncmp(dec_salt_binary, magic_bytes[1], strlen(magic_bytes[1])) == 0)
     164                 :             :     {
     165                 :          13 :         type = PGCRYPTO_SHA512CRYPT;
     166                 :          13 :         dec_salt_binary += strlen(magic_bytes[1]);
     167                 :             :     }
     168                 :             : 
     169                 :             :     /*
     170                 :             :      * dec_salt_binary pointer is positioned after the magic bytes now
     171                 :             :      *
     172                 :             :      * We extract any options in the following code branch. The only optional
     173                 :             :      * setting we need to take care of is the "rounds" option. Note that the
     174                 :             :      * salt generator already checked for invalid settings before, but we need
     175                 :             :      * to do it here again to protect against injection of wrong values when
     176                 :             :      * called without the generator.
     177                 :             :      *
     178                 :             :      * If there is any garbage added after the magic byte and the options/salt
     179                 :             :      * string, we don't treat this special: This is just absorbed as part of
     180                 :             :      * the salt with up to PX_SHACRYPT_SALT_LEN_MAX.
     181                 :             :      *
     182                 :             :      * Unknown magic byte is handled further below.
     183                 :             :      */
     184         [ +  + ]:          26 :     if (strncmp(dec_salt_binary,
     185                 :             :                 rounds_prefix, sizeof(rounds_prefix) - 1) == 0)
     186                 :             :     {
     187                 :          20 :         const char *num = dec_salt_binary + sizeof(rounds_prefix) - 1;
     188                 :             :         char       *endp;
     189                 :          20 :         int         srounds = strtoint(num, &endp, 10);
     190                 :             : 
     191         [ -  + ]:          20 :         if (*endp != '$')
     192         [ #  # ]:           0 :             ereport(ERROR,
     193                 :             :                     errcode(ERRCODE_SYNTAX_ERROR),
     194                 :             :                     errmsg("could not parse salt options"));
     195                 :             : 
     196                 :          20 :         dec_salt_binary = endp + 1;
     197                 :             : 
     198                 :             :         /*
     199                 :             :          * We violate supported lower or upper bound of rounds, but in this
     200                 :             :          * case we change this value to the supported lower or upper value. We
     201                 :             :          * don't do this silently and print a NOTICE in such a case.
     202                 :             :          *
     203                 :             :          * Note that a salt string generated with gen_salt() would never
     204                 :             :          * generated such a salt string, since it would error out.
     205                 :             :          *
     206                 :             :          * But Drepper's upstream reference implementation supports this when
     207                 :             :          * passing the salt string directly, so we maintain compatibility.
     208                 :             :          */
     209         [ -  + ]:          20 :         if (srounds > PX_SHACRYPT_ROUNDS_MAX)
     210                 :             :         {
     211         [ #  # ]:           0 :             ereport(NOTICE,
     212                 :             :                     errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     213                 :             :                     errmsg("rounds=%d exceeds maximum supported value (%d), using %d instead",
     214                 :             :                            srounds, PX_SHACRYPT_ROUNDS_MAX,
     215                 :             :                            PX_SHACRYPT_ROUNDS_MAX));
     216                 :           0 :             srounds = PX_SHACRYPT_ROUNDS_MAX;
     217                 :             :         }
     218         [ +  + ]:          20 :         else if (srounds < PX_SHACRYPT_ROUNDS_MIN)
     219                 :             :         {
     220         [ +  - ]:           2 :             ereport(NOTICE,
     221                 :             :                     errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     222                 :             :                     errmsg("rounds=%d is below supported value (%d), using %d instead",
     223                 :             :                            srounds, PX_SHACRYPT_ROUNDS_MIN,
     224                 :             :                            PX_SHACRYPT_ROUNDS_MIN));
     225                 :           2 :             srounds = PX_SHACRYPT_ROUNDS_MIN;
     226                 :             :         }
     227                 :             : 
     228                 :          20 :         rounds = (uint32) srounds;
     229                 :          20 :         rounds_custom = 1;
     230                 :             :     }
     231                 :             : 
     232                 :             :     /*
     233                 :             :      * Choose the correct digest length and add the magic bytes to the result
     234                 :             :      * buffer. Also handle possible invalid magic byte we've extracted above.
     235                 :             :      */
     236   [ +  +  -  - ]:          26 :     switch (type)
     237                 :             :     {
     238                 :          13 :         case PGCRYPTO_SHA256CRYPT:
     239                 :             :             {
     240                 :             :                 /* Two PX_MD objects required */
     241                 :          13 :                 err = px_find_digest("sha256", &digestA);
     242         [ -  + ]:          13 :                 if (err)
     243                 :           0 :                     goto error;
     244                 :             : 
     245                 :          13 :                 err = px_find_digest("sha256", &digestB);
     246         [ -  + ]:          13 :                 if (err)
     247                 :           0 :                     goto error;
     248                 :             : 
     249                 :             :                 /* digest buffer length is 32 for sha256 */
     250                 :          13 :                 buf_size = 32;
     251                 :             : 
     252                 :          13 :                 appendStringInfoString(out_buf, magic_bytes[0]);
     253                 :          13 :                 break;
     254                 :             :             }
     255                 :             : 
     256                 :          13 :         case PGCRYPTO_SHA512CRYPT:
     257                 :             :             {
     258                 :             :                 /* Two PX_MD objects required */
     259                 :          13 :                 err = px_find_digest("sha512", &digestA);
     260         [ -  + ]:          13 :                 if (err)
     261                 :           0 :                     goto error;
     262                 :             : 
     263                 :          13 :                 err = px_find_digest("sha512", &digestB);
     264         [ -  + ]:          13 :                 if (err)
     265                 :           0 :                     goto error;
     266                 :             : 
     267                 :          13 :                 buf_size = PX_SHACRYPT_DIGEST_MAX_LEN;
     268                 :             : 
     269                 :          13 :                 appendStringInfoString(out_buf, magic_bytes[1]);
     270                 :          13 :                 break;
     271                 :             :             }
     272                 :             : 
     273                 :           0 :         case PGCRYPTO_SHA_UNKOWN:
     274         [ #  # ]:           0 :             elog(ERROR, "unknown crypt identifier \"%c\"", salt[1]);
     275                 :             :     }
     276                 :             : 
     277         [ +  + ]:          26 :     if (rounds_custom > 0)
     278                 :          20 :         appendStringInfo(out_buf, "rounds=%u$", rounds);
     279                 :             : 
     280                 :             :     /*
     281                 :             :      * We need the real decoded salt string from salt input, this is every
     282                 :             :      * character before the last '$' in the preamble. Append every compatible
     283                 :             :      * character up to PX_SHACRYPT_SALT_MAX_LEN to the result buffer. Note
     284                 :             :      * that depending on the input, there might be no '$' marker after the
     285                 :             :      * salt, when there is no password hash attached at the end.
     286                 :             :      *
     287                 :             :      * We try hard to recognize mistakes, but since we might get an input
     288                 :             :      * string which might also have the password hash after the salt string
     289                 :             :      * section we give up as soon we reach the end of the input or if there
     290                 :             :      * are any bytes consumed for the salt string until we reach the first '$'
     291                 :             :      * marker thereafter.
     292                 :             :      */
     293                 :          26 :     for (ep = dec_salt_binary;
     294   [ +  +  +  + ]:         368 :          *ep && ep < (dec_salt_binary + PX_SHACRYPT_SALT_MAX_LEN);
     295                 :         342 :          ep++)
     296                 :             :     {
     297                 :             :         /*
     298                 :             :          * Filter out any string which shouldn't be here.
     299                 :             :          *
     300                 :             :          * First check for accidentally embedded magic strings here. We don't
     301                 :             :          * support '$' in salt strings anyways and seeing a magic byte trying
     302                 :             :          * to identify shacrypt hashes might indicate that something went
     303                 :             :          * wrong when generating this salt string. Note that we later check
     304                 :             :          * for non-supported literals anyways, but any '$' here confuses us at
     305                 :             :          * this point.
     306                 :             :          */
     307                 :         342 :         fp = strstr(dec_salt_binary, magic_bytes[0]);
     308         [ -  + ]:         342 :         if (fp != NULL)
     309         [ #  # ]:           0 :             elog(ERROR, "bogus magic byte found in salt string");
     310                 :             : 
     311                 :         342 :         fp = strstr(dec_salt_binary, magic_bytes[1]);
     312         [ -  + ]:         342 :         if (fp != NULL)
     313         [ #  # ]:           0 :             elog(ERROR, "bogus magic byte found in salt string");
     314                 :             : 
     315                 :             :         /*
     316                 :             :          * This looks very strict, but we assume the caller did something
     317                 :             :          * wrong when we see a "rounds=" option here.
     318                 :             :          */
     319                 :         342 :         fp = strstr(dec_salt_binary, rounds_prefix);
     320         [ -  + ]:         342 :         if (fp != NULL)
     321         [ #  # ]:           0 :             elog(ERROR, "invalid rounds option specified in salt string");
     322                 :             : 
     323         [ +  - ]:         342 :         if (*ep != '$')
     324                 :             :         {
     325         [ +  - ]:         342 :             if (strchr(_crypt_itoa64, *ep) != NULL)
     326         [ +  + ]:         342 :                 appendStringInfoCharMacro(decoded_salt, *ep);
     327                 :             :             else
     328         [ #  # ]:           0 :                 ereport(ERROR,
     329                 :             :                         errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     330                 :             :                         errmsg("invalid character in salt string: \"%.*s\"",
     331                 :             :                                pg_mblen_cstr(ep), ep));
     332                 :             :         }
     333                 :             :         else
     334                 :             :         {
     335                 :             :             /*
     336                 :             :              * We encountered a '$' marker. Check if we already absorbed some
     337                 :             :              * bytes from input. If true, we are optimistic and terminate at
     338                 :             :              * this stage. If not, we try further.
     339                 :             :              *
     340                 :             :              * If we already consumed enough bytes for the salt string,
     341                 :             :              * everything that is after this marker is considered to be part
     342                 :             :              * of an optionally specified password hash and ignored.
     343                 :             :              */
     344         [ #  # ]:           0 :             if (decoded_salt->len > 0)
     345                 :           0 :                 break;
     346                 :             :         }
     347                 :             :     }
     348                 :             : 
     349                 :          26 :     salt_len = decoded_salt->len;
     350                 :          26 :     appendStringInfoString(out_buf, decoded_salt->data);
     351         [ -  + ]:          26 :     elog(DEBUG1, "using salt \"%s\", salt len = %d, rounds = %u",
     352                 :             :          decoded_salt->data, decoded_salt->len, rounds);
     353                 :             : 
     354                 :             :     /*
     355                 :             :      * Sanity check: at this point the salt string buffer must not exceed
     356                 :             :      * expected size.
     357                 :             :      */
     358         [ -  + ]:          26 :     if (out_buf->len > (3 + 17 * rounds_custom + salt_len))
     359         [ #  # ]:           0 :         elog(ERROR, "unexpected length of salt string");
     360                 :             : 
     361                 :             :     /*-
     362                 :             :      * 1. Start digest A
     363                 :             :      * 2. Add the password string to digest A
     364                 :             :      * 3. Add the salt to digest A
     365                 :             :      */
     366                 :          26 :     px_md_update(digestA, (const unsigned char *) pw, len);
     367                 :          26 :     px_md_update(digestA, (const unsigned char *) decoded_salt->data, salt_len);
     368                 :             : 
     369                 :             :     /*-
     370                 :             :      * 4. Create digest B
     371                 :             :      * 5. Add password to digest B
     372                 :             :      * 6. Add the salt string to digest B
     373                 :             :      * 7. Add the password again to digest B
     374                 :             :      * 8. Finalize digest B
     375                 :             :      */
     376                 :          26 :     px_md_update(digestB, (const unsigned char *) pw, len);
     377                 :          26 :     px_md_update(digestB, (const unsigned char *) dec_salt_binary, salt_len);
     378                 :          26 :     px_md_update(digestB, (const unsigned char *) pw, len);
     379                 :          26 :     px_md_finish(digestB, sha_buf);
     380                 :             : 
     381                 :             :     /*
     382                 :             :      * 9. For each block (excluding the NULL byte), add digest B to digest A.
     383                 :             :      */
     384         [ +  + ]:          31 :     for (block = len; block > buf_size; block -= buf_size)
     385                 :           5 :         px_md_update(digestA, sha_buf, buf_size);
     386                 :             : 
     387                 :             :     /*-
     388                 :             :      * 10. For the remaining N bytes of the password string, add the first N
     389                 :             :      * bytes of digest B to A.
     390                 :             :      */
     391                 :          26 :     px_md_update(digestA, sha_buf, block);
     392                 :             : 
     393                 :             :     /*-
     394                 :             :      * 11. For each bit of the binary representation of the length of the
     395                 :             :      * password string up to and including the highest 1-digit, starting from
     396                 :             :      * to lowest bit position (numeric value 1)
     397                 :             :      *
     398                 :             :      * a) for a 1-digit add digest B (sha_buf) to digest A
     399                 :             :      * b) for a 0-digit add the password string
     400                 :             :      */
     401                 :          26 :     block = len;
     402         [ +  + ]:         136 :     while (block)
     403                 :             :     {
     404   [ +  +  +  + ]:         110 :         px_md_update(digestA,
     405                 :             :                      (block & 1) ? sha_buf : (const unsigned char *) pw,
     406                 :             :                      (block & 1) ? buf_size : len);
     407                 :             : 
     408                 :             :         /* right shift to next byte */
     409                 :         110 :         block >>= 1;
     410                 :             :     }
     411                 :             : 
     412                 :             :     /* 12. Finalize digest A */
     413                 :          26 :     px_md_finish(digestA, sha_buf);
     414                 :             : 
     415                 :             :     /* 13. Start digest DP */
     416                 :          26 :     px_md_reset(digestB);
     417                 :             : 
     418                 :             :     /*-
     419                 :             :      * 14 Add every byte of the password string (excluding trailing NULL)
     420                 :             :      * to the digest DP
     421                 :             :      */
     422         [ +  + ]:         556 :     for (block = len; block > 0; block--)
     423                 :         530 :         px_md_update(digestB, (const unsigned char *) pw, len);
     424                 :             : 
     425                 :             :     /* 15. Finalize digest DP */
     426                 :          26 :     px_md_finish(digestB, sha_buf_tmp);
     427                 :             : 
     428                 :             :     /*-
     429                 :             :      * 16. produce byte sequence P with same length as password.
     430                 :             :      *     a) for each block of 32 or 64 bytes of length of the password
     431                 :             :      *        string the entire digest DP is used
     432                 :             :      *     b) for the remaining N (up to  31 or 63) bytes use the
     433                 :             :      *        first N bytes of digest DP
     434                 :             :      */
     435         [ -  + ]:          26 :     if ((p_bytes = palloc0(len)) == NULL)
     436                 :             :     {
     437                 :           0 :         goto error;
     438                 :             :     }
     439                 :             : 
     440                 :             :     /* N step of 16, copy over the bytes from password */
     441         [ +  + ]:          31 :     for (cp = p_bytes, block = len; block > buf_size; block -= buf_size, cp += buf_size)
     442                 :           5 :         memcpy(cp, sha_buf_tmp, buf_size);
     443                 :          26 :     memcpy(cp, sha_buf_tmp, block);
     444                 :             : 
     445                 :             :     /*
     446                 :             :      * 17. Start digest DS
     447                 :             :      */
     448                 :          26 :     px_md_reset(digestB);
     449                 :             : 
     450                 :             :     /*-
     451                 :             :      * 18. Repeat the following 16+A[0] times, where A[0] represents the first
     452                 :             :      *    byte in digest A interpreted as an 8-bit unsigned value
     453                 :             :      *    add the salt to digest DS
     454                 :             :      */
     455         [ +  + ]:        4123 :     for (block = 16 + sha_buf[0]; block > 0; block--)
     456                 :        4097 :         px_md_update(digestB, (const unsigned char *) dec_salt_binary, salt_len);
     457                 :             : 
     458                 :             :     /*
     459                 :             :      * 19. Finalize digest DS
     460                 :             :      */
     461                 :          26 :     px_md_finish(digestB, sha_buf_tmp);
     462                 :             : 
     463                 :             :     /*-
     464                 :             :      * 20. Produce byte sequence S of the same length as the salt string where
     465                 :             :      *
     466                 :             :      * a) for each block of 32 or 64 bytes of length of the salt string the
     467                 :             :      *    entire digest DS is used
     468                 :             :      *
     469                 :             :      * b) for the remaining N (up to  31 or 63) bytes use the first N
     470                 :             :      *    bytes of digest DS
     471                 :             :      */
     472         [ -  + ]:          26 :     if ((s_bytes = palloc0(salt_len)) == NULL)
     473                 :           0 :         goto error;
     474                 :             : 
     475         [ -  + ]:          26 :     for (cp = s_bytes, block = salt_len; block > buf_size; block -= buf_size, cp += buf_size)
     476                 :           0 :         memcpy(cp, sha_buf_tmp, buf_size);
     477                 :          26 :     memcpy(cp, sha_buf_tmp, block);
     478                 :             : 
     479                 :             :     /* Make sure we don't leave something important behind */
     480                 :          26 :     px_memset(&sha_buf_tmp, 0, sizeof sha_buf);
     481                 :             : 
     482                 :             :     /*-
     483                 :             :      * 21. Repeat a loop according to the number specified in the rounds=<N>
     484                 :             :      *     specification in the salt (or the default value if none is
     485                 :             :      *     present).  Each round is numbered, starting with 0 and up to N-1.
     486                 :             :      *
     487                 :             :      *     The loop uses a digest as input.  In the first round it is the
     488                 :             :      *     digest produced in step 12.  In the latter steps it is the digest
     489                 :             :      *     produced in step 21.h of the previous round.  The following text
     490                 :             :      *     uses the notation "digest A/B" to describe this behavior.
     491                 :             :      */
     492         [ +  + ]:      527288 :     for (block = 0; block < rounds; block++)
     493                 :             :     {
     494                 :             :         /*
     495                 :             :          * Make it possible to abort in case large values for "rounds" are
     496                 :             :          * specified.
     497                 :             :          */
     498         [ -  + ]:      527262 :         CHECK_FOR_INTERRUPTS();
     499                 :             : 
     500                 :             :         /* a) start digest B */
     501                 :      527262 :         px_md_reset(digestB);
     502                 :             : 
     503                 :             :         /*-
     504                 :             :          * b) for odd round numbers add the byte sequence P to digest B
     505                 :             :          * c) for even round numbers add digest A/B
     506                 :             :          */
     507   [ +  +  +  + ]:      527262 :         px_md_update(digestB,
     508                 :             :                      (block & 1) ? (const unsigned char *) p_bytes : sha_buf,
     509                 :             :                      (block & 1) ? len : buf_size);
     510                 :             : 
     511                 :             :         /* d) for all round numbers not divisible by 3 add the byte sequence S */
     512         [ +  + ]:      527262 :         if ((block % 3) != 0)
     513                 :      351500 :             px_md_update(digestB, (const unsigned char *) s_bytes, salt_len);
     514                 :             : 
     515                 :             :         /* e) for all round numbers not divisible by 7 add the byte sequence P */
     516         [ +  + ]:      527262 :         if ((block % 7) != 0)
     517                 :      451926 :             px_md_update(digestB, (const unsigned char *) p_bytes, len);
     518                 :             : 
     519                 :             :         /*-
     520                 :             :          * f) for odd round numbers add digest A/C
     521                 :             :          * g) for even round numbers add the byte sequence P
     522                 :             :          */
     523   [ +  +  +  + ]:      527262 :         px_md_update(digestB,
     524                 :             :                      (block & 1) ? sha_buf : (const unsigned char *) p_bytes,
     525                 :             :                      (block & 1) ? buf_size : len);
     526                 :             : 
     527                 :             :         /* h) finish digest C. */
     528                 :      527262 :         px_md_finish(digestB, sha_buf);
     529                 :             :     }
     530                 :             : 
     531                 :          26 :     px_md_free(digestA);
     532                 :          26 :     px_md_free(digestB);
     533                 :             : 
     534                 :          26 :     digestA = NULL;
     535                 :          26 :     digestB = NULL;
     536                 :             : 
     537                 :          26 :     pfree(s_bytes);
     538                 :          26 :     pfree(p_bytes);
     539                 :             : 
     540                 :          26 :     s_bytes = NULL;
     541                 :          26 :     p_bytes = NULL;
     542                 :             : 
     543                 :             :     /* prepare final result buffer */
     544         [ -  + ]:          26 :     appendStringInfoCharMacro(out_buf, '$');
     545                 :             : 
     546                 :             : #define b64_from_24bit(B2, B1, B0, N)                                    \
     547                 :             :     do {                                                                 \
     548                 :             :         unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);              \
     549                 :             :         int     i = (N);                                                 \
     550                 :             :         while (i-- > 0)                                                  \
     551                 :             :         {                                                                \
     552                 :             :             appendStringInfoCharMacro(out_buf, _crypt_itoa64[w & 0x3f]); \
     553                 :             :             w >>= 6;                                                     \
     554                 :             :         }                                                                \
     555                 :             :     } while (0)
     556                 :             : 
     557   [ +  +  -  - ]:          26 :     switch (type)
     558                 :             :     {
     559                 :          13 :         case PGCRYPTO_SHA256CRYPT:
     560                 :             :             {
     561   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[0], sha_buf[10], sha_buf[20], 4);
     562   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[21], sha_buf[1], sha_buf[11], 4);
     563   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[12], sha_buf[22], sha_buf[2], 4);
     564   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[3], sha_buf[13], sha_buf[23], 4);
     565   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[24], sha_buf[4], sha_buf[14], 4);
     566   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[15], sha_buf[25], sha_buf[5], 4);
     567   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[6], sha_buf[16], sha_buf[26], 4);
     568   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[27], sha_buf[7], sha_buf[17], 4);
     569   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[18], sha_buf[28], sha_buf[8], 4);
     570   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[9], sha_buf[19], sha_buf[29], 4);
     571   [ -  +  +  + ]:          52 :                 b64_from_24bit(0, sha_buf[31], sha_buf[30], 3);
     572                 :             : 
     573                 :          13 :                 break;
     574                 :             :             }
     575                 :             : 
     576                 :          13 :         case PGCRYPTO_SHA512CRYPT:
     577                 :             :             {
     578   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[0], sha_buf[21], sha_buf[42], 4);
     579   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[22], sha_buf[43], sha_buf[1], 4);
     580   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[44], sha_buf[2], sha_buf[23], 4);
     581   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[3], sha_buf[24], sha_buf[45], 4);
     582   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[25], sha_buf[46], sha_buf[4], 4);
     583   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[47], sha_buf[5], sha_buf[26], 4);
     584   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[6], sha_buf[27], sha_buf[48], 4);
     585   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[28], sha_buf[49], sha_buf[7], 4);
     586   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[50], sha_buf[8], sha_buf[29], 4);
     587   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[9], sha_buf[30], sha_buf[51], 4);
     588   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[31], sha_buf[52], sha_buf[10], 4);
     589   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[53], sha_buf[11], sha_buf[32], 4);
     590   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[12], sha_buf[33], sha_buf[54], 4);
     591   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[34], sha_buf[55], sha_buf[13], 4);
     592   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[56], sha_buf[14], sha_buf[35], 4);
     593   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[15], sha_buf[36], sha_buf[57], 4);
     594   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[37], sha_buf[58], sha_buf[16], 4);
     595   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[59], sha_buf[17], sha_buf[38], 4);
     596   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[18], sha_buf[39], sha_buf[60], 4);
     597   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[40], sha_buf[61], sha_buf[19], 4);
     598   [ -  +  +  + ]:          65 :                 b64_from_24bit(sha_buf[62], sha_buf[20], sha_buf[41], 4);
     599   [ -  +  +  + ]:          39 :                 b64_from_24bit(0, 0, sha_buf[63], 2);
     600                 :             : 
     601                 :          13 :                 break;
     602                 :             :             }
     603                 :             : 
     604                 :           0 :         case PGCRYPTO_SHA_UNKOWN:
     605                 :             :             /* we shouldn't land here ... */
     606         [ #  # ]:           0 :             elog(ERROR, "unsupported digest length");
     607                 :             :     }
     608                 :             : 
     609                 :             :     /*
     610                 :             :      * Copy over result to specified buffer.
     611                 :             :      *
     612                 :             :      * The passwd character buffer should have at least PX_SHACRYPT_BUF_LEN
     613                 :             :      * allocated, since we checked above if dstlen is smaller than
     614                 :             :      * PX_SHACRYPT_BUF_LEN (which also includes the NULL byte).
     615                 :             :      *
     616                 :             :      * In that case we would have failed above already.
     617                 :             :      */
     618                 :          26 :     memcpy(passwd, out_buf->data, out_buf->len);
     619                 :             : 
     620                 :             :     /* make sure nothing important is left behind */
     621                 :          26 :     px_memset(&sha_buf, 0, sizeof sha_buf);
     622                 :          26 :     destroyStringInfo(out_buf);
     623                 :          26 :     destroyStringInfo(decoded_salt);
     624                 :             : 
     625                 :             :     /* ...and we're done */
     626                 :          26 :     return passwd;
     627                 :             : 
     628                 :           0 : error:
     629         [ #  # ]:           0 :     if (digestA != NULL)
     630                 :           0 :         px_md_free(digestA);
     631                 :             : 
     632         [ #  # ]:           0 :     if (digestB != NULL)
     633                 :           0 :         px_md_free(digestB);
     634                 :             : 
     635                 :           0 :     destroyStringInfo(out_buf);
     636                 :           0 :     destroyStringInfo(decoded_salt);
     637                 :             : 
     638         [ #  # ]:           0 :     ereport(ERROR,
     639                 :             :             errcode(ERRCODE_INTERNAL_ERROR),
     640                 :             :             errmsg("cannot create encrypted password"));
     641                 :             :     return NULL;                /* keep compiler quiet */
     642                 :             : }
        

Generated by: LCOV version 2.0-1