Coverage Report

Created: 2024-06-18 06:23

/src/hpn-ssh/openbsd-compat/bcrypt_pbkdf.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: bcrypt_pbkdf.c,v 1.16 2020/08/02 18:35:48 tb Exp $ */
2
/*
3
 * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
/* OPENBSD ORIGINAL: lib/libutil/bcrypt_pbkdf.c */
19
20
/* This version has been modified to use SHA512 from SUPERCOP */
21
22
#include "includes.h"
23
24
#ifndef HAVE_BCRYPT_PBKDF
25
26
#include <sys/types.h>
27
28
#ifdef HAVE_STDLIB_H
29
# include <stdlib.h>
30
#endif
31
#include <string.h>
32
33
#ifdef HAVE_BLF_H
34
# include <blf.h>
35
#endif
36
37
#include "crypto_api.h"
38
#ifdef SHA512_DIGEST_LENGTH
39
# undef SHA512_DIGEST_LENGTH
40
#endif
41
0
#define SHA512_DIGEST_LENGTH crypto_hash_sha512_BYTES
42
43
0
#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
44
45
/*
46
 * pkcs #5 pbkdf2 implementation using the "bcrypt" hash
47
 *
48
 * The bcrypt hash function is derived from the bcrypt password hashing
49
 * function with the following modifications:
50
 * 1. The input password and salt are preprocessed with SHA512.
51
 * 2. The output length is expanded to 256 bits.
52
 * 3. Subsequently the magic string to be encrypted is lengthened and modifed
53
 *    to "OxychromaticBlowfishSwatDynamite"
54
 * 4. The hash function is defined to perform 64 rounds of initial state
55
 *    expansion. (More rounds are performed by iterating the hash.)
56
 *
57
 * Note that this implementation pulls the SHA512 operations into the caller
58
 * as a performance optimization.
59
 *
60
 * One modification from official pbkdf2. Instead of outputting key material
61
 * linearly, we mix it. pbkdf2 has a known weakness where if one uses it to
62
 * generate (e.g.) 512 bits of key material for use as two 256 bit keys, an
63
 * attacker can merely run once through the outer loop, but the user
64
 * always runs it twice. Shuffling output bytes requires computing the
65
 * entirety of the key material to assemble any subkey. This is something a
66
 * wise caller could do; we just do it for you.
67
 */
68
69
0
#define BCRYPT_WORDS 8
70
#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
71
72
static void
73
bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
74
0
{
75
0
  blf_ctx state;
76
0
  uint8_t ciphertext[BCRYPT_HASHSIZE] =
77
0
      "OxychromaticBlowfishSwatDynamite";
78
0
  uint32_t cdata[BCRYPT_WORDS];
79
0
  int i;
80
0
  uint16_t j;
81
0
  size_t shalen = SHA512_DIGEST_LENGTH;
82
83
  /* key expansion */
84
0
  Blowfish_initstate(&state);
85
0
  Blowfish_expandstate(&state, sha2salt, shalen, sha2pass, shalen);
86
0
  for (i = 0; i < 64; i++) {
87
0
    Blowfish_expand0state(&state, sha2salt, shalen);
88
0
    Blowfish_expand0state(&state, sha2pass, shalen);
89
0
  }
90
91
  /* encryption */
92
0
  j = 0;
93
0
  for (i = 0; i < BCRYPT_WORDS; i++)
94
0
    cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
95
0
        &j);
96
0
  for (i = 0; i < 64; i++)
97
0
    blf_enc(&state, cdata, BCRYPT_WORDS / 2);
98
99
  /* copy out */
100
0
  for (i = 0; i < BCRYPT_WORDS; i++) {
101
0
    out[4 * i + 3] = (cdata[i] >> 24) & 0xff;
102
0
    out[4 * i + 2] = (cdata[i] >> 16) & 0xff;
103
0
    out[4 * i + 1] = (cdata[i] >> 8) & 0xff;
104
0
    out[4 * i + 0] = cdata[i] & 0xff;
105
0
  }
106
107
  /* zap */
108
0
  explicit_bzero(ciphertext, sizeof(ciphertext));
109
0
  explicit_bzero(cdata, sizeof(cdata));
110
0
  explicit_bzero(&state, sizeof(state));
111
0
}
112
113
int
114
bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen,
115
    uint8_t *key, size_t keylen, unsigned int rounds)
116
0
{
117
0
  uint8_t sha2pass[SHA512_DIGEST_LENGTH];
118
0
  uint8_t sha2salt[SHA512_DIGEST_LENGTH];
119
0
  uint8_t out[BCRYPT_HASHSIZE];
120
0
  uint8_t tmpout[BCRYPT_HASHSIZE];
121
0
  uint8_t *countsalt;
122
0
  size_t i, j, amt, stride;
123
0
  uint32_t count;
124
0
  size_t origkeylen = keylen;
125
126
  /* nothing crazy */
127
0
  if (rounds < 1)
128
0
    goto bad;
129
0
  if (passlen == 0 || saltlen == 0 || keylen == 0 ||
130
0
      keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20)
131
0
    goto bad;
132
0
  if ((countsalt = calloc(1, saltlen + 4)) == NULL)
133
0
    goto bad;
134
0
  stride = (keylen + sizeof(out) - 1) / sizeof(out);
135
0
  amt = (keylen + stride - 1) / stride;
136
137
0
  memcpy(countsalt, salt, saltlen);
138
139
  /* collapse password */
140
0
  crypto_hash_sha512(sha2pass, pass, passlen);
141
142
  /* generate key, sizeof(out) at a time */
143
0
  for (count = 1; keylen > 0; count++) {
144
0
    countsalt[saltlen + 0] = (count >> 24) & 0xff;
145
0
    countsalt[saltlen + 1] = (count >> 16) & 0xff;
146
0
    countsalt[saltlen + 2] = (count >> 8) & 0xff;
147
0
    countsalt[saltlen + 3] = count & 0xff;
148
149
    /* first round, salt is salt */
150
0
    crypto_hash_sha512(sha2salt, countsalt, saltlen + 4);
151
152
0
    bcrypt_hash(sha2pass, sha2salt, tmpout);
153
0
    memcpy(out, tmpout, sizeof(out));
154
155
0
    for (i = 1; i < rounds; i++) {
156
      /* subsequent rounds, salt is previous output */
157
0
      crypto_hash_sha512(sha2salt, tmpout, sizeof(tmpout));
158
0
      bcrypt_hash(sha2pass, sha2salt, tmpout);
159
0
      for (j = 0; j < sizeof(out); j++)
160
0
        out[j] ^= tmpout[j];
161
0
    }
162
163
    /*
164
     * pbkdf2 deviation: output the key material non-linearly.
165
     */
166
0
    amt = MINIMUM(amt, keylen);
167
0
    for (i = 0; i < amt; i++) {
168
0
      size_t dest = i * stride + (count - 1);
169
0
      if (dest >= origkeylen)
170
0
        break;
171
0
      key[dest] = out[i];
172
0
    }
173
0
    keylen -= i;
174
0
  }
175
176
  /* zap */
177
0
  freezero(countsalt, saltlen + 4);
178
0
  explicit_bzero(out, sizeof(out));
179
0
  explicit_bzero(tmpout, sizeof(tmpout));
180
181
0
  return 0;
182
183
0
bad:
184
  /* overwrite with random in case caller doesn't check return code */
185
0
  arc4random_buf(key, keylen);
186
0
  return -1;
187
0
}
188
#endif /* HAVE_BCRYPT_PBKDF */