1  /*
       2   * Copyright (c) 2004, Juniper Networks, Inc.
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   * 1. Redistributions of source code must retain the above copyright
       9   *    notice, this list of conditions and the following disclaimer.
      10   * 2. Redistributions in binary form must reproduce the above copyright
      11   *    notice, this list of conditions and the following disclaimer in the
      12   *    documentation and/or other materials provided with the distribution.
      13   * 3. Neither the name of the copyright holders nor the names of its
      14   *    contributors may be used to endorse or promote products derived
      15   *    from this software without specific prior written permission.
      16   *
      17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      19   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      20   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      21   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      22   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      23   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      24   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      25   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      27   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28   */
      29  
      30  #include "crypt-port.h"
      31  #include "alg-hmac-sha1.h"
      32  #include "byteorder.h"
      33  
      34  #include <errno.h>
      35  #include <stdio.h>
      36  #include <stdlib.h>
      37  
      38  #if INCLUDE_sha1crypt
      39  
      40  /*
      41   * The default iterations - should take >0s on a fast CPU
      42   * but not be insane for a slow CPU.
      43   */
      44  #ifndef CRYPT_SHA1_ITERATIONS
      45  # define CRYPT_SHA1_ITERATIONS 262144
      46  #endif
      47  /*
      48   * Support a reasonably? long salt.
      49   */
      50  #ifndef CRYPT_SHA1_SALT_LENGTH
      51  # define CRYPT_SHA1_SALT_LENGTH 64
      52  #endif
      53  
      54  #define SHA1_SIZE 20         /* size of raw SHA1 digest, 160 bits */
      55  #define SHA1_OUTPUT_SIZE 28  /* size of base64-ed output string */
      56  
      57  static inline void
      58  to64 (uint8_t *s, unsigned long v, int n)
      59  {
      60    while (--n >= 0)
      61      {
      62        *s++ = itoa64[v & 0x3f];
      63        v >>= 6;
      64      }
      65  }
      66  
      67  /*
      68   * UNIX password using hmac_sha1
      69   * This is PBKDF1 from RFC 2898, but using hmac_sha1.
      70   *
      71   * The format of the encrypted password is:
      72   * $<tag>$<iterations>$<salt>$<digest>
      73   *
      74   * where:
      75   * 	<tag>		is "sha1"
      76   *	<iterations>	is an unsigned int identifying how many rounds
      77   * 			have been applied to <digest>.  The number
      78   * 			should vary slightly for each password to make
      79   * 			it harder to generate a dictionary of
      80   * 			pre-computed hashes.  See gensalt_sha1crypt_rn.
      81   * 	<salt>		up to 64 bytes of random data, 8 bytes is
      82   * 			currently considered more than enough.
      83   *	<digest>	the hashed password.
      84   *
      85   * NOTE:
      86   * To be FIPS 140 compliant, the password which is used as a hmac key,
      87   * should be between 10 and 20 characters to provide at least 80bits
      88   * strength, and avoid the need to hash it before using as the
      89   * hmac key.
      90   */
      91  void
      92  crypt_sha1crypt_rn (const char *phrase, size_t phr_size,
      93                      const char *setting, size_t ARG_UNUSED (set_size),
      94                      uint8_t *output, size_t out_size,
      95                      void *scratch, size_t scr_size)
      96  {
      97    static const char *magic = "$sha1$";
      98  
      99    if ((out_size < (strlen (magic) + 2 + 10 + CRYPT_SHA1_SALT_LENGTH +
     100                     SHA1_OUTPUT_SIZE)) ||
     101        scr_size < SHA1_SIZE)
     102      {
     103        errno = ERANGE;
     104        return;
     105      }
     106  
     107    const char *sp;
     108    uint8_t *ep;
     109    unsigned long ul;
     110    size_t sl;
     111    size_t pl = phr_size;
     112    int dl;
     113    unsigned long iterations;
     114    unsigned long i;
     115    /* XXX silence -Wpointer-sign (would be nice to fix this some other way) */
     116    const uint8_t *pwu = (const uint8_t *)phrase;
     117    uint8_t *hmac_buf = scratch;
     118  
     119    /*
     120     * Salt format is
     121     * $<tag>$<iterations>$salt[$]
     122     */
     123  
     124    /* If the string doesn't starts with the magic prefix, we shouldn't have been called */
     125    if (strncmp (setting, magic, strlen (magic)))
     126      {
     127        errno = EINVAL;
     128        return;
     129      }
     130  
     131    setting += strlen (magic);
     132    /* get the iteration count */
     133    iterations = (unsigned long)strtoul (setting, (char **)&ep, 10);
     134    if (*ep != '$')
     135      {
     136        errno = EINVAL;
     137        return;  /* invalid input */
     138      }
     139    setting = (char *)ep + 1;  /* skip over the '$' */
     140  
     141    /* The next 1..CRYPT_SHA1_SALT_LENGTH bytes should be itoa64 characters,
     142       followed by another '$' (or end of string).  */
     143    sp = setting + strspn (setting, (const char *)itoa64);
     144    if (sp == setting || (*sp && *sp != '$'))
     145      {
     146        errno = EINVAL;
     147        return;
     148      }
     149  
     150    sl = (size_t)(sp - setting);
     151  
     152    /*
     153     * Now get to work...
     154     * Prime the pump with <salt><magic><iterations>
     155     */
     156    dl = snprintf ((char *)output, out_size, "%.*s%s%lu",
     157                   (int)sl, setting, magic, iterations);
     158    /*
     159     * Then hmac using <phrase> as key, and repeat...
     160     */
     161    hmac_sha1_process_data ((const unsigned char *)output, (size_t)dl,
     162                            pwu, pl, hmac_buf);
     163    for (i = 1; i < iterations; ++i)
     164      {
     165        hmac_sha1_process_data (hmac_buf, SHA1_SIZE, pwu, pl, hmac_buf);
     166      }
     167    /* Now output... */
     168    pl = (size_t)snprintf ((char *)output, out_size, "%s%lu$%.*s$",
     169                           magic, iterations, (int)sl, setting);
     170    ep = output + pl;
     171  
     172    /* Every 3 bytes of hash gives 24 bits which is 4 base64 chars */
     173    for (i = 0; i < SHA1_SIZE - 3; i += 3)
     174      {
     175        ul = (unsigned long)((hmac_buf[i+0] << 16) |
     176                             (hmac_buf[i+1] << 8) |
     177                             hmac_buf[i+2]);
     178        to64 (ep, ul, 4);
     179        ep += 4;
     180      }
     181    /* Only 2 bytes left, so we pad with byte0 */
     182    ul = (unsigned long)((hmac_buf[SHA1_SIZE - 2] << 16) |
     183                         (hmac_buf[SHA1_SIZE - 1] << 8) |
     184                         hmac_buf[0]);
     185    to64 (ep, ul, 4);
     186    ep += 4;
     187    *ep = '\0';
     188  
     189    /* Don't leave anything around in vm they could use. */
     190    explicit_bzero (scratch, scr_size);
     191  }
     192  
     193  /* Modified excerpt from:
     194     http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/lib/libcrypt/pw_gensalt.c */
     195  void
     196  gensalt_sha1crypt_rn (unsigned long count,
     197                        const uint8_t *rbytes, size_t nrbytes,
     198                        uint8_t *output, size_t o_size)
     199  {
     200    static_assert (sizeof (uint32_t) == 4,
     201                   "space calculations below assume 8-bit bytes");
     202  
     203    /* Make sure we have enough random bytes to use for the salt.
     204       The format supports using up to 48 random bytes, but 12 is
     205       enough.  We require another 4 bytes of randomness to perturb
     206       'count' with.  */
     207    if (nrbytes < 12 + 4)
     208      {
     209        errno = EINVAL;
     210        return;
     211      }
     212  
     213    /* Make sure we have enough output space, given the amount of
     214       randomness available.  $sha1$<10digits>$<(nrbytes-4)*4/3>$ */
     215    if (o_size < (nrbytes - 4) * 4 / 3 + sizeof "$sha1$$$" + 10)
     216      {
     217        errno = ERANGE;
     218        return;
     219      }
     220  
     221    /*
     222     * We treat 'count' as a hint.
     223     * Make it harder for someone to pre-compute hashes for a
     224     * dictionary attack by not using the same iteration count for
     225     * every entry.
     226     */
     227    uint32_t rounds, random = le32_to_cpu (rbytes);
     228  
     229    if (count == 0)
     230      count = CRYPT_SHA1_ITERATIONS;
     231    if (count < 4)
     232      count = 4;
     233    if (count > UINT32_MAX)
     234      count = UINT32_MAX;
     235    rounds = (uint32_t) (count - (random % (count / 4)));
     236  
     237    uint32_t encbuf;
     238    int n = snprintf((char *)output, o_size, "$sha1$%u$", (unsigned int)rounds);
     239    assert (n >= 1 && (size_t)n + 2 < o_size);
     240  
     241    const uint8_t *r = rbytes + 4;
     242    const uint8_t *rlim = rbytes + nrbytes;
     243    uint8_t *o = output + n;
     244    uint8_t *olim = output + n + CRYPT_SHA1_SALT_LENGTH;
     245    if (olim + 2 > output + o_size)
     246      olim = output + o_size - 2;
     247  
     248    for (; r + 3 < rlim && o + 4 < olim; r += 3, o += 4)
     249      {
     250        encbuf = ((((uint32_t)r[0]) << 16) |
     251                  (((uint32_t)r[1]) <<  8) |
     252                  (((uint32_t)r[2]) <<  0));
     253        to64 (o, encbuf, 4);
     254      }
     255  
     256    o[0] = '$';
     257    o[1] = '\0';
     258  }
     259  
     260  #endif