(root)/
libxcrypt-4.4.36/
lib/
crypt-sha512.c
       1  /* One way encryption based on the SHA512-based Unix crypt implementation.
       2   *
       3   * Written by Ulrich Drepper <drepper at redhat.com> in 2007 [1].
       4   * Modified by Zack Weinberg <zackw at panix.com> in 2017, 2018.
       5   * Composed by Björn Esser <besser82 at fedoraproject.org> in 2018.
       6   * Modified by Björn Esser <besser82 at fedoraproject.org> in 2020.
       7   * To the extent possible under law, the named authors have waived all
       8   * copyright and related or neighboring rights to this work.
       9   *
      10   * See https://creativecommons.org/publicdomain/zero/1.0/ for further
      11   * details.
      12   *
      13   * This file is a modified except from [2], lines 1403 up to 1676.
      14   *
      15   * [1]  https://www.akkadia.org/drepper/sha-crypt.html
      16   * [2]  https://www.akkadia.org/drepper/SHA-crypt.txt
      17   */
      18  
      19  #include "crypt-port.h"
      20  #include "alg-sha512.h"
      21  
      22  #include <errno.h>
      23  #include <stdio.h>
      24  #include <stdlib.h>
      25  
      26  #if INCLUDE_sha512crypt
      27  
      28  /* Define our magic string to mark salt for SHA512 "encryption"
      29     replacement.  */
      30  static const char sha512_salt_prefix[] = "$6$";
      31  
      32  /* Prefix for optional rounds specification.  */
      33  static const char sha512_rounds_prefix[] = "rounds=";
      34  
      35  /* Maximum salt string length.  */
      36  #define SALT_LEN_MAX 16
      37  /* Default number of rounds if not explicitly specified.  */
      38  #define ROUNDS_DEFAULT 5000
      39  /* Minimum number of rounds.  */
      40  #define ROUNDS_MIN 1000
      41  /* Maximum number of rounds.  */
      42  #define ROUNDS_MAX 999999999
      43  
      44  /* The maximum possible length of a SHA512-hashed password string,
      45     including the terminating NUL character.  Prefix (including its NUL)
      46     + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX)
      47     + salt (up to SALT_LEN_MAX chars) + '$' + hash (86 chars).  */
      48  
      49  #define LENGTH_OF_NUMBER(n) (sizeof #n - 1)
      50  
      51  #define SHA512_HASH_LENGTH \
      52    (sizeof (sha512_salt_prefix) + sizeof (sha512_rounds_prefix) + \
      53     LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 86)
      54  
      55  static_assert (SHA512_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
      56                 "CRYPT_OUTPUT_SIZE is too small for SHA512");
      57  
      58  /* A sha512_buffer holds all of the sensitive intermediate data.  */
      59  struct sha512_buffer
      60  {
      61    SHA512_CTX ctx;
      62    uint8_t result[64];
      63    uint8_t p_bytes[64];
      64    uint8_t s_bytes[64];
      65  };
      66  
      67  static_assert (sizeof (struct sha512_buffer) <= ALG_SPECIFIC_SIZE,
      68                 "ALG_SPECIFIC_SIZE is too small for SHA512");
      69  
      70  
      71  /* Subroutine of _xcrypt_crypt_sha512crypt_rn: Feed CTX with LEN bytes of a
      72     virtual byte sequence consisting of BLOCK repeated over and over
      73     indefinitely.  */
      74  static void
      75  sha512_process_recycled_bytes (unsigned char block[64], size_t len,
      76                                 SHA512_CTX *ctx)
      77  {
      78    size_t cnt;
      79    for (cnt = len; cnt >= 64; cnt -= 64)
      80      SHA512_Update (ctx, block, 64);
      81    SHA512_Update (ctx, block, cnt);
      82  }
      83  
      84  void
      85  crypt_sha512crypt_rn (const char *phrase, size_t phr_size,
      86                        const char *setting, size_t ARG_UNUSED (set_size),
      87                        uint8_t *output, size_t out_size,
      88                        void *scratch, size_t scr_size)
      89  {
      90    /* This shouldn't ever happen, but...  */
      91    if (out_size < SHA512_HASH_LENGTH
      92        || scr_size < sizeof (struct sha512_buffer))
      93      {
      94        errno = ERANGE;
      95        return;
      96      }
      97  
      98    struct sha512_buffer *buf = scratch;
      99    SHA512_CTX *ctx = &buf->ctx;
     100    uint8_t *result = buf->result;
     101    uint8_t *p_bytes = buf->p_bytes;
     102    uint8_t *s_bytes = buf->s_bytes;
     103    char *cp = (char *)output;
     104    const char *salt = setting;
     105  
     106    size_t salt_size;
     107    size_t cnt;
     108    /* Default number of rounds.  */
     109    size_t rounds = ROUNDS_DEFAULT;
     110    bool rounds_custom = false;
     111  
     112    /* Find beginning of salt string.  The prefix should normally always
     113       be present.  Just in case it is not.  */
     114    if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
     115      /* Skip salt prefix.  */
     116      salt += sizeof (sha512_salt_prefix) - 1;
     117  
     118    if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
     119        == 0)
     120      {
     121        const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
     122        /* Do not allow an explicit setting of zero rounds, nor of the
     123           default number of rounds, nor leading zeroes on the rounds.  */
     124        if (!(*num >= '1' && *num <= '9'))
     125          {
     126            errno = EINVAL;
     127            return;
     128          }
     129  
     130        errno = 0;
     131        char *endp;
     132        rounds = strtoul (num, &endp, 10);
     133        if (endp == num || *endp != '$'
     134            || rounds < ROUNDS_MIN
     135            || rounds > ROUNDS_MAX
     136            || errno)
     137          {
     138            errno = EINVAL;
     139            return;
     140          }
     141        salt = endp + 1;
     142        rounds_custom = true;
     143      }
     144  
     145    /* The salt ends at the next '$' or the end of the string.
     146       Ensure ':' does not appear in the salt (it is used as a separator in /etc/passwd).
     147       Also check for '\n', as in /etc/passwd the whole parameters of the user data must
     148       be on a single line. */
     149    salt_size = strcspn (salt, "$:\n");
     150    if (!(salt[salt_size] == '$' || !salt[salt_size]))
     151      {
     152        errno = EINVAL;
     153        return;
     154      }
     155  
     156    /* Ensure we do not use more salt than SALT_LEN_MAX. */
     157    if (salt_size > SALT_LEN_MAX)
     158      salt_size = SALT_LEN_MAX;
     159  
     160    /* Compute alternate SHA512 sum with input PHRASE, SALT, and PHRASE.  The
     161       final result will be added to the first context.  */
     162    SHA512_Init (ctx);
     163  
     164    /* Add phrase.  */
     165    SHA512_Update (ctx, phrase, phr_size);
     166  
     167    /* Add salt.  */
     168    SHA512_Update (ctx, salt, salt_size);
     169  
     170    /* Add phrase again.  */
     171    SHA512_Update (ctx, phrase, phr_size);
     172  
     173    /* Now get result of this (64 bytes) and add it to the other
     174       context.  */
     175    SHA512_Final (result, ctx);
     176  
     177    /* Prepare for the real work.  */
     178    SHA512_Init (ctx);
     179  
     180    /* Add the phrase string.  */
     181    SHA512_Update (ctx, phrase, phr_size);
     182  
     183    /* The last part is the salt string.  This must be at most 8
     184       characters and it ends at the first `$' character (for
     185       compatibility with existing implementations).  */
     186    SHA512_Update (ctx, salt, salt_size);
     187  
     188    /* Add for any character in the phrase one byte of the alternate sum.  */
     189    for (cnt = phr_size; cnt > 64; cnt -= 64)
     190      SHA512_Update (ctx, result, 64);
     191    SHA512_Update (ctx, result, cnt);
     192  
     193    /* Take the binary representation of the length of the phrase and for every
     194       1 add the alternate sum, for every 0 the phrase.  */
     195    for (cnt = phr_size; cnt > 0; cnt >>= 1)
     196      if ((cnt & 1) != 0)
     197        SHA512_Update (ctx, result, 64);
     198      else
     199        SHA512_Update (ctx, phrase, phr_size);
     200  
     201    /* Create intermediate result.  */
     202    SHA512_Final (result, ctx);
     203  
     204    /* Start computation of P byte sequence.  */
     205    SHA512_Init (ctx);
     206  
     207    /* For every character in the password add the entire password.  */
     208    for (cnt = 0; cnt < phr_size; ++cnt)
     209      SHA512_Update (ctx, phrase, phr_size);
     210  
     211    /* Finish the digest.  */
     212    SHA512_Final (p_bytes, ctx);
     213  
     214    /* Start computation of S byte sequence.  */
     215    SHA512_Init (ctx);
     216  
     217    /* For every character in the password add the entire password.  */
     218    for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
     219      SHA512_Update (ctx, salt, salt_size);
     220  
     221    /* Finish the digest.  */
     222    SHA512_Final (s_bytes, ctx);
     223  
     224    /* Repeatedly run the collected hash value through SHA512 to burn
     225       CPU cycles.  */
     226    for (cnt = 0; cnt < rounds; ++cnt)
     227      {
     228        /* New context.  */
     229        SHA512_Init (ctx);
     230  
     231        /* Add phrase or last result.  */
     232        if ((cnt & 1) != 0)
     233          sha512_process_recycled_bytes (p_bytes, phr_size, ctx);
     234        else
     235          SHA512_Update (ctx, result, 64);
     236  
     237        /* Add salt for numbers not divisible by 3.  */
     238        if (cnt % 3 != 0)
     239          sha512_process_recycled_bytes (s_bytes, salt_size, ctx);
     240  
     241        /* Add phrase for numbers not divisible by 7.  */
     242        if (cnt % 7 != 0)
     243          sha512_process_recycled_bytes (p_bytes, phr_size, ctx);
     244  
     245        /* Add phrase or last result.  */
     246        if ((cnt & 1) != 0)
     247          SHA512_Update (ctx, result, 64);
     248        else
     249          sha512_process_recycled_bytes (p_bytes, phr_size, ctx);
     250  
     251        /* Create intermediate result.  */
     252        SHA512_Final (result, ctx);
     253      }
     254  
     255    /* Now we can construct the result string.  It consists of four
     256       parts, one of which is optional.  We already know that buflen is
     257       at least sha512_hash_length, therefore none of the string bashing
     258       below can overflow the buffer. */
     259  
     260    memcpy (cp, sha512_salt_prefix, sizeof (sha512_salt_prefix) - 1);
     261    cp += sizeof (sha512_salt_prefix) - 1;
     262  
     263    if (rounds_custom)
     264      {
     265        int n = snprintf (cp,
     266                          SHA512_HASH_LENGTH - (sizeof (sha512_salt_prefix) - 1),
     267                          "%s%zu$", sha512_rounds_prefix, rounds);
     268        cp += n;
     269      }
     270  
     271    memcpy (cp, salt, salt_size);
     272    cp += salt_size;
     273    *cp++ = '$';
     274  
     275  #define b64_from_24bit(B2, B1, B0, N)                   \
     276    do {                                                  \
     277      unsigned int w = ((((unsigned int)(B2)) << 16) |    \
     278                        (((unsigned int)(B1)) << 8) |     \
     279                        ((unsigned int)(B0)));            \
     280      int n = (N);                                        \
     281      while (n-- > 0)                                     \
     282        {                                                 \
     283          *cp++ = b64t[w & 0x3f];                         \
     284          w >>= 6;                                        \
     285        }                                                 \
     286    } while (0)
     287  
     288    b64_from_24bit (result[0], result[21], result[42], 4);
     289    b64_from_24bit (result[22], result[43], result[1], 4);
     290    b64_from_24bit (result[44], result[2], result[23], 4);
     291    b64_from_24bit (result[3], result[24], result[45], 4);
     292    b64_from_24bit (result[25], result[46], result[4], 4);
     293    b64_from_24bit (result[47], result[5], result[26], 4);
     294    b64_from_24bit (result[6], result[27], result[48], 4);
     295    b64_from_24bit (result[28], result[49], result[7], 4);
     296    b64_from_24bit (result[50], result[8], result[29], 4);
     297    b64_from_24bit (result[9], result[30], result[51], 4);
     298    b64_from_24bit (result[31], result[52], result[10], 4);
     299    b64_from_24bit (result[53], result[11], result[32], 4);
     300    b64_from_24bit (result[12], result[33], result[54], 4);
     301    b64_from_24bit (result[34], result[55], result[13], 4);
     302    b64_from_24bit (result[56], result[14], result[35], 4);
     303    b64_from_24bit (result[15], result[36], result[57], 4);
     304    b64_from_24bit (result[37], result[58], result[16], 4);
     305    b64_from_24bit (result[59], result[17], result[38], 4);
     306    b64_from_24bit (result[18], result[39], result[60], 4);
     307    b64_from_24bit (result[40], result[61], result[19], 4);
     308    b64_from_24bit (result[62], result[20], result[41], 4);
     309    b64_from_24bit (0, 0, result[63], 2);
     310  
     311    *cp = '\0';
     312  }
     313  
     314  void
     315  gensalt_sha512crypt_rn (unsigned long count,
     316                          const uint8_t *rbytes, size_t nrbytes,
     317                          uint8_t *output, size_t output_size)
     318  {
     319    gensalt_sha_rn ('6', SALT_LEN_MAX, ROUNDS_DEFAULT, ROUNDS_MIN, ROUNDS_MAX,
     320                    count, rbytes, nrbytes, output, output_size);
     321  }
     322  
     323  #endif