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