LCOV - differential code coverage report
Current view: top level - contrib/pgcrypto - crypt-sha.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 83.0 % 206 171 35 171
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 1 1 1
Baseline: lcov-20250906-005545-baseline Branches: 63.2 % 272 172 100 172
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 83.0 % 206 171 35 171
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
Branch coverage date bins:
(30,360] days: 63.2 % 272 172 100 172

 Age         Owner                    Branch data    TLA  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 *
  154 alvherre@alvh.no-ip.       69                 :CBC          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)
  154 alvherre@alvh.no-ip.      102                 :UBC           0 :         return NULL;
                                103                 :                : 
  154 alvherre@alvh.no-ip.      104         [ -  + ]:CBC          26 :     if (pw == NULL)
  154 alvherre@alvh.no-ip.      105         [ #  # ]:UBC           0 :         elog(ERROR, "null value for password rejected");
                                106                 :                : 
  154 alvherre@alvh.no-ip.      107         [ -  + ]:CBC          26 :     if (salt == NULL)
  154 alvherre@alvh.no-ip.      108         [ #  # ]:UBC           0 :         elog(ERROR, "null value for salt rejected");
                                109                 :                : 
                                110                 :                :     /*
                                111                 :                :      * Make sure result buffers are large enough.
                                112                 :                :      */
  154 alvherre@alvh.no-ip.      113         [ -  + ]:CBC          26 :     if (dstlen < PX_SHACRYPT_BUF_LEN)
  154 alvherre@alvh.no-ip.      114         [ #  # ]:UBC           0 :         elog(ERROR, "insufficient result buffer size to encrypt password");
                                115                 :                : 
                                116                 :                :     /* Init result buffer */
  153 tgl@sss.pgh.pa.us         117                 :CBC          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 */
  154 alvherre@alvh.no-ip.      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)
  154 alvherre@alvh.no-ip.      138         [ #  # ]:UBC           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                 :                :      */
  154 alvherre@alvh.no-ip.      146   [ +  -  -  + ]:CBC          26 :     if ((dec_salt_binary[0] != '$') || (dec_salt_binary[2] != '$'))
  154 alvherre@alvh.no-ip.      147         [ #  # ]:UBC           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                 :                :      */
  154 alvherre@alvh.no-ip.      158         [ +  + ]:CBC          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 != '$')
  154 alvherre@alvh.no-ip.      192         [ #  # ]:UBC           0 :             ereport(ERROR,
                                193                 :                :                     errcode(ERRCODE_SYNTAX_ERROR),
                                194                 :                :                     errmsg("could not parse salt options"));
                                195                 :                : 
  154 alvherre@alvh.no-ip.      196                 :CBC          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                 :                :         {
  154 alvherre@alvh.no-ip.      211         [ #  # ]:UBC           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                 :                :         }
  154 alvherre@alvh.no-ip.      218         [ +  + ]:CBC          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)
  154 alvherre@alvh.no-ip.      243                 :UBC           0 :                     goto error;
                                244                 :                : 
  154 alvherre@alvh.no-ip.      245                 :CBC          13 :                 err = px_find_digest("sha256", &digestB);
                                246         [ -  + ]:             13 :                 if (err)
  154 alvherre@alvh.no-ip.      247                 :UBC           0 :                     goto error;
                                248                 :                : 
                                249                 :                :                 /* digest buffer length is 32 for sha256 */
  154 alvherre@alvh.no-ip.      250                 :CBC          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)
  154 alvherre@alvh.no-ip.      261                 :UBC           0 :                     goto error;
                                262                 :                : 
  154 alvherre@alvh.no-ip.      263                 :CBC          13 :                 err = px_find_digest("sha512", &digestB);
                                264         [ -  + ]:             13 :                 if (err)
  154 alvherre@alvh.no-ip.      265                 :UBC           0 :                     goto error;
                                266                 :                : 
  154 alvherre@alvh.no-ip.      267                 :CBC          13 :                 buf_size = PX_SHACRYPT_DIGEST_MAX_LEN;
                                268                 :                : 
                                269                 :             13 :                 appendStringInfoString(out_buf, magic_bytes[1]);
                                270                 :             13 :                 break;
                                271                 :                :             }
                                272                 :                : 
  154 alvherre@alvh.no-ip.      273                 :UBC           0 :         case PGCRYPTO_SHA_UNKOWN:
                                274         [ #  # ]:              0 :             elog(ERROR, "unknown crypt identifier \"%c\"", salt[1]);
                                275                 :                :     }
                                276                 :                : 
  154 alvherre@alvh.no-ip.      277         [ +  + ]:CBC          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)
  154 alvherre@alvh.no-ip.      309         [ #  # ]:UBC           0 :             elog(ERROR, "bogus magic byte found in salt string");
                                310                 :                : 
  154 alvherre@alvh.no-ip.      311                 :CBC         342 :         fp = strstr(dec_salt_binary, magic_bytes[1]);
                                312         [ -  + ]:            342 :         if (fp != NULL)
  154 alvherre@alvh.no-ip.      313         [ #  # ]:UBC           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                 :                :          */
  154 alvherre@alvh.no-ip.      319                 :CBC         342 :         fp = strstr(dec_salt_binary, rounds_prefix);
                                320         [ -  + ]:            342 :         if (fp != NULL)
  154 alvherre@alvh.no-ip.      321         [ #  # ]:UBC           0 :             elog(ERROR, "invalid rounds option specified in salt string");
                                322                 :                : 
  154 alvherre@alvh.no-ip.      323         [ +  - ]:CBC         342 :         if (*ep != '$')
                                324                 :                :         {
  152 tgl@sss.pgh.pa.us         325         [ +  - ]:            342 :             if (strchr(_crypt_itoa64, *ep) != NULL)
  154 alvherre@alvh.no-ip.      326         [ +  + ]:            342 :                 appendStringInfoCharMacro(decoded_salt, *ep);
                                327                 :                :             else
  152 tgl@sss.pgh.pa.us         328         [ #  # ]:UBC           0 :                 ereport(ERROR,
                                329                 :                :                         errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                330                 :                :                         errmsg("invalid character in salt string: \"%.*s\"",
                                331                 :                :                                pg_mblen(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                 :                :              */
  154 alvherre@alvh.no-ip.      344         [ #  # ]:              0 :             if (decoded_salt->len > 0)
                                345                 :              0 :                 break;
                                346                 :                :         }
                                347                 :                :     }
                                348                 :                : 
  154 alvherre@alvh.no-ip.      349                 :CBC          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))
  154 alvherre@alvh.no-ip.      359         [ #  # ]:UBC           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                 :                :      */
  154 alvherre@alvh.no-ip.      366                 :CBC          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                 :                :     {
  154 alvherre@alvh.no-ip.      437                 :UBC           0 :         goto error;
                                438                 :                :     }
                                439                 :                : 
                                440                 :                :     /* N step of 16, copy over the bytes from password */
  154 alvherre@alvh.no-ip.      441         [ +  + ]:CBC          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         [ +  + ]:           3605 :     for (block = 16 + sha_buf[0]; block > 0; block--)
                                456                 :           3579 :         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)
  154 alvherre@alvh.no-ip.      473                 :UBC           0 :         goto error;
                                474                 :                : 
  154 alvherre@alvh.no-ip.      475         [ -  + ]:CBC          26 :     for (cp = s_bytes, block = salt_len; block > buf_size; block -= buf_size, cp += buf_size)
  154 alvherre@alvh.no-ip.      476                 :UBC           0 :         memcpy(cp, sha_buf_tmp, buf_size);
  154 alvherre@alvh.no-ip.      477                 :CBC          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                 :                : 
  154 alvherre@alvh.no-ip.      604                 :UBC           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                 :                :      */
  154 alvherre@alvh.no-ip.      618                 :CBC          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                 :                : 
  154 alvherre@alvh.no-ip.      628                 :UBC           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                 :                : 
  153 tgl@sss.pgh.pa.us         635                 :              0 :     destroyStringInfo(out_buf);
                                636                 :              0 :     destroyStringInfo(decoded_salt);
                                637                 :                : 
  154 alvherre@alvh.no-ip.      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.4-beta