Blame crypt-pbkdf1-sha1.c

Packit 13e0ca
/*
Packit 13e0ca
 * Copyright (c) 2004, Juniper Networks, Inc.
Packit 13e0ca
 * All rights reserved.
Packit 13e0ca
 *
Packit 13e0ca
 * Redistribution and use in source and binary forms, with or without
Packit 13e0ca
 * modification, are permitted provided that the following conditions
Packit 13e0ca
 * are met:
Packit 13e0ca
 * 1. Redistributions of source code must retain the above copyright
Packit 13e0ca
 *    notice, this list of conditions and the following disclaimer.
Packit 13e0ca
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 13e0ca
 *    notice, this list of conditions and the following disclaimer in the
Packit 13e0ca
 *    documentation and/or other materials provided with the distribution.
Packit 13e0ca
 * 3. Neither the name of the copyright holders nor the names of its
Packit 13e0ca
 *    contributors may be used to endorse or promote products derived
Packit 13e0ca
 *    from this software without specific prior written permission.
Packit 13e0ca
 *
Packit 13e0ca
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 13e0ca
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 13e0ca
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 13e0ca
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 13e0ca
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 13e0ca
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 13e0ca
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 13e0ca
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 13e0ca
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 13e0ca
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 13e0ca
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 13e0ca
 */
Packit 13e0ca
Packit 13e0ca
#include "crypt-port.h"
Packit 13e0ca
#include "crypt-private.h"
Packit 13e0ca
#include "alg-hmac-sha1.h"
Packit 13e0ca
#include "byteorder.h"
Packit 13e0ca
Packit 13e0ca
#include <errno.h>
Packit 13e0ca
#include <stdio.h>
Packit 13e0ca
#include <stdlib.h>
Packit 13e0ca
Packit 13e0ca
#if INCLUDE_sha1
Packit 13e0ca
Packit 13e0ca
/*
Packit 13e0ca
 * The default iterations - should take >0s on a fast CPU
Packit 13e0ca
 * but not be insane for a slow CPU.
Packit 13e0ca
 */
Packit 13e0ca
#ifndef CRYPT_SHA1_ITERATIONS
Packit 13e0ca
# define CRYPT_SHA1_ITERATIONS 262144
Packit 13e0ca
#endif
Packit 13e0ca
/*
Packit 13e0ca
 * Support a reasonably? long salt.
Packit 13e0ca
 */
Packit 13e0ca
#ifndef CRYPT_SHA1_SALT_LENGTH
Packit 13e0ca
# define CRYPT_SHA1_SALT_LENGTH 64
Packit 13e0ca
#endif
Packit 13e0ca
Packit 13e0ca
#define SHA1_SIZE 20         /* size of raw SHA1 digest, 160 bits */
Packit 13e0ca
#define SHA1_OUTPUT_SIZE 28  /* size of base64-ed output string */
Packit 13e0ca
Packit 13e0ca
static const uint8_t itoa64[] =
Packit 13e0ca
  "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Packit 13e0ca
Packit 13e0ca
static inline void
Packit 13e0ca
to64 (uint8_t *s, unsigned long v, int n)
Packit 13e0ca
{
Packit 13e0ca
  while (--n >= 0)
Packit 13e0ca
    {
Packit 13e0ca
      *s++ = itoa64[v & 0x3f];
Packit 13e0ca
      v >>= 6;
Packit 13e0ca
    }
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
/*
Packit 13e0ca
 * UNIX password using hmac_sha1
Packit 13e0ca
 * This is PBKDF1 from RFC 2898, but using hmac_sha1.
Packit 13e0ca
 *
Packit 13e0ca
 * The format of the encrypted password is:
Packit 13e0ca
 * $<tag>$<iterations>$<salt>$<digest>
Packit 13e0ca
 *
Packit 13e0ca
 * where:
Packit 13e0ca
 * 	<tag>		is "sha1"
Packit 13e0ca
 *	<iterations>	is an unsigned int identifying how many rounds
Packit 13e0ca
 * 			have been applied to <digest>.  The number
Packit 13e0ca
 * 			should vary slightly for each password to make
Packit 13e0ca
 * 			it harder to generate a dictionary of
Packit 13e0ca
 * 			pre-computed hashes.  See gensalt_sha1_rn.
Packit 13e0ca
 * 	<salt>		up to 64 bytes of random data, 8 bytes is
Packit 13e0ca
 * 			currently considered more than enough.
Packit 13e0ca
 *	<digest>	the hashed password.
Packit 13e0ca
 *
Packit 13e0ca
 * NOTE:
Packit 13e0ca
 * To be FIPS 140 compliant, the password which is used as a hmac key,
Packit 13e0ca
 * should be between 10 and 20 characters to provide at least 80bits
Packit 13e0ca
 * strength, and avoid the need to hash it before using as the
Packit 13e0ca
 * hmac key.
Packit 13e0ca
 */
Packit 13e0ca
void
Packit 13e0ca
crypt_sha1_rn (const char *phrase, size_t phr_size,
Packit 13e0ca
               const char *setting, size_t ARG_UNUSED (set_size),
Packit 13e0ca
               uint8_t *output, size_t out_size,
Packit 13e0ca
               void *scratch, size_t scr_size)
Packit 13e0ca
{
Packit 13e0ca
  static const char *magic = "$sha1$";
Packit 13e0ca
Packit 13e0ca
  if ((out_size < (strlen (magic) + 2 + 10 + CRYPT_SHA1_SALT_LENGTH +
Packit 13e0ca
                   SHA1_OUTPUT_SIZE)) ||
Packit 13e0ca
      scr_size < SHA1_SIZE)
Packit 13e0ca
    {
Packit 13e0ca
      errno = ERANGE;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  const char *sp;
Packit 13e0ca
  uint8_t *ep;
Packit 13e0ca
  unsigned long ul;
Packit 13e0ca
  size_t sl;
Packit 13e0ca
  size_t pl = phr_size;
Packit 13e0ca
  int dl;
Packit 13e0ca
  unsigned long iterations;
Packit 13e0ca
  unsigned long i;
Packit 13e0ca
  /* XXX silence -Wpointer-sign (would be nice to fix this some other way) */
Packit 13e0ca
  const uint8_t *pwu = (const uint8_t *)phrase;
Packit 13e0ca
  uint8_t *hmac_buf = scratch;
Packit 13e0ca
Packit 13e0ca
  /*
Packit 13e0ca
   * Salt format is
Packit 13e0ca
   * $<tag>$<iterations>$salt[$]
Packit 13e0ca
   */
Packit 13e0ca
Packit 13e0ca
  /* If the string doesn't starts with the magic prefix, we shouldn't have been called */
Packit 13e0ca
  if (strncmp (setting, magic, strlen (magic)))
Packit 13e0ca
    {
Packit 13e0ca
      errno = EINVAL;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  setting += strlen (magic);
Packit 13e0ca
  /* get the iteration count */
Packit 13e0ca
  iterations = (unsigned long)strtoul (setting, (char **)&ep, 10);
Packit 13e0ca
  if (*ep != '$')
Packit 13e0ca
    {
Packit 13e0ca
      errno = EINVAL;
Packit 13e0ca
      return;  /* invalid input */
Packit 13e0ca
    }
Packit 13e0ca
  setting = (char *)ep + 1;  /* skip over the '$' */
Packit 13e0ca
Packit 13e0ca
  /* The next 1..CRYPT_SHA1_SALT_LENGTH bytes should be itoa64 characters,
Packit 13e0ca
     followed by another '$' (or end of string).  */
Packit 13e0ca
  sp = setting + strspn (setting, (const char *)itoa64);
Packit 13e0ca
  if (sp == setting || (*sp && *sp != '$'))
Packit 13e0ca
    {
Packit 13e0ca
      errno = EINVAL;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  sl = (size_t)(sp - setting);
Packit 13e0ca
Packit 13e0ca
  /*
Packit 13e0ca
   * Now get to work...
Packit 13e0ca
   * Prime the pump with <salt><magic><iterations>
Packit 13e0ca
   */
Packit 13e0ca
  dl = snprintf ((char *)output, out_size, "%.*s%s%lu",
Packit 13e0ca
                 (int)sl, setting, magic, iterations);
Packit 13e0ca
  /*
Packit 13e0ca
   * Then hmac using <phrase> as key, and repeat...
Packit 13e0ca
   */
Packit 13e0ca
  hmac_sha1_process_data ((const unsigned char *)output, (size_t)dl,
Packit 13e0ca
                          pwu, pl, hmac_buf);
Packit 13e0ca
  for (i = 1; i < iterations; ++i)
Packit 13e0ca
    {
Packit 13e0ca
      hmac_sha1_process_data (hmac_buf, SHA1_SIZE, pwu, pl, hmac_buf);
Packit 13e0ca
    }
Packit 13e0ca
  /* Now output... */
Packit 13e0ca
  pl = (size_t)snprintf ((char *)output, out_size, "%s%lu$%.*s$",
Packit 13e0ca
                         magic, iterations, (int)sl, setting);
Packit 13e0ca
  ep = output + pl;
Packit 13e0ca
Packit 13e0ca
  /* Every 3 bytes of hash gives 24 bits which is 4 base64 chars */
Packit 13e0ca
  for (i = 0; i < SHA1_SIZE - 3; i += 3)
Packit 13e0ca
    {
Packit 13e0ca
      ul = (unsigned long)((hmac_buf[i+0] << 16) |
Packit 13e0ca
                           (hmac_buf[i+1] << 8) |
Packit 13e0ca
                           hmac_buf[i+2]);
Packit 13e0ca
      to64 (ep, ul, 4);
Packit 13e0ca
      ep += 4;
Packit 13e0ca
    }
Packit 13e0ca
  /* Only 2 bytes left, so we pad with byte0 */
Packit 13e0ca
  ul = (unsigned long)((hmac_buf[SHA1_SIZE - 2] << 16) |
Packit 13e0ca
                       (hmac_buf[SHA1_SIZE - 1] << 8) |
Packit 13e0ca
                       hmac_buf[0]);
Packit 13e0ca
  to64 (ep, ul, 4);
Packit 13e0ca
  ep += 4;
Packit 13e0ca
  *ep = '\0';
Packit 13e0ca
Packit 13e0ca
  /* Don't leave anything around in vm they could use. */
Packit 13e0ca
  XCRYPT_SECURE_MEMSET (scratch, scr_size);
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
/* Modified excerpt from:
Packit 13e0ca
   http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/lib/libcrypt/pw_gensalt.c */
Packit 13e0ca
void
Packit 13e0ca
gensalt_sha1_rn (unsigned long count,
Packit 13e0ca
                 const uint8_t *rbytes, size_t nrbytes,
Packit 13e0ca
                 uint8_t *output, size_t o_size)
Packit 13e0ca
{
Packit 13e0ca
  static_assert (sizeof (uint32_t) == 4,
Packit 13e0ca
                 "space calculations below assume 8-bit bytes");
Packit 13e0ca
Packit 13e0ca
  /* Make sure we have enough random bytes to use for the salt.
Packit 13e0ca
     The format supports using up to 48 random bytes, but 12 is
Packit 13e0ca
     enough.  We require another 4 bytes of randomness to perturb
Packit 13e0ca
     'count' with.  */
Packit 13e0ca
  if (nrbytes < 12 + 4)
Packit 13e0ca
    {
Packit 13e0ca
      errno = EINVAL;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  /* Make sure we have enough output space, given the amount of
Packit 13e0ca
     randomness available.  $sha1$<10digits>$<(nrbytes-4)*4/3>$ */
Packit 13e0ca
  if (o_size < (nrbytes - 4) * 4 / 3 + sizeof "$sha1$$$" + 10)
Packit 13e0ca
    {
Packit 13e0ca
      errno = ERANGE;
Packit 13e0ca
      return;
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  /*
Packit 13e0ca
   * We treat 'count' as a hint.
Packit 13e0ca
   * Make it harder for someone to pre-compute hashes for a
Packit 13e0ca
   * dictionary attack by not using the same iteration count for
Packit 13e0ca
   * every entry.
Packit 13e0ca
   */
Packit 13e0ca
  uint32_t rounds, random = le32_to_cpu (rbytes);
Packit 13e0ca
Packit 13e0ca
  if (count == 0)
Packit 13e0ca
    count = CRYPT_SHA1_ITERATIONS;
Packit 13e0ca
  if (count > UINT32_MAX)
Packit 13e0ca
    count = UINT32_MAX;
Packit 13e0ca
  rounds = (uint32_t) (count - (random % (count / 4)));
Packit 13e0ca
Packit 13e0ca
  uint32_t encbuf;
Packit 13e0ca
  int n = snprintf((char *)output, o_size, "$sha1$%u$", (unsigned int)rounds);
Packit 13e0ca
  assert (n >= 1 && (size_t)n + 2 < o_size);
Packit 13e0ca
Packit 13e0ca
  const uint8_t *r = rbytes + 4;
Packit 13e0ca
  const uint8_t *rlim = rbytes + nrbytes;
Packit 13e0ca
  uint8_t *o = output + n;
Packit 13e0ca
  uint8_t *olim = output + n + CRYPT_SHA1_SALT_LENGTH;
Packit 13e0ca
  if (olim + 2 > output + o_size)
Packit 13e0ca
    olim = output + o_size - 2;
Packit 13e0ca
Packit 13e0ca
  for (; r + 3 < rlim && o + 4 < olim; r += 3, o += 4)
Packit 13e0ca
    {
Packit 13e0ca
      encbuf = ((((uint32_t)r[0]) << 16) |
Packit 13e0ca
                (((uint32_t)r[1]) <<  8) |
Packit 13e0ca
                (((uint32_t)r[2]) <<  0));
Packit 13e0ca
      to64 (o, encbuf, 4);
Packit 13e0ca
    }
Packit 13e0ca
Packit 13e0ca
  o[0] = '$';
Packit 13e0ca
  o[1] = '\0';
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
#endif