Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/cipher/scrypt.c
Line
Count
Source (jump to first uncovered line)
1
/* scrypt.c - Scrypt password-based key derivation function.
2
 * Copyright (C) 2012 Simon Josefsson
3
 * Copyright (C) 2013 Christian Grothoff
4
 * Copyright (C) 2013 g10 Code GmbH
5
 *
6
 * This file is part of Libgcrypt.
7
 *
8
 * Libgcrypt is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser general Public License as
10
 * published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * Libgcrypt is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
/* Adapted from the nettle, low-level cryptographics library for
23
 * libgcrypt by Christian Grothoff; original license:
24
 *
25
 * Copyright (C) 2012 Simon Josefsson
26
 *
27
 * The nettle library is free software; you can redistribute it and/or modify
28
 * it under the terms of the GNU Lesser General Public License as published by
29
 * the Free Software Foundation; either version 2.1 of the License, or (at your
30
 * option) any later version.
31
 *
32
 * The nettle library is distributed in the hope that it will be useful, but
33
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
34
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
35
 * License for more details.
36
 *
37
 * You should have received a copy of the GNU Lesser General Public License
38
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
39
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
40
 * MA 02111-1301, USA.
41
 */
42
43
#include <config.h>
44
#include <assert.h>
45
#include <stdlib.h>
46
#include <string.h>
47
48
#include "g10lib.h"
49
#include "kdf-internal.h"
50
#include "bufhelp.h"
51
52
/* We really need a 64 bit type for this code.  */
53
0
#define SALSA20_INPUT_LENGTH 16
54
55
0
#define ROTL32(n,x) (((x)<<(n)) | ((x)>>(32-(n))))
56
57
58
/* Reads a 64-bit integer, in network, big-endian, byte order */
59
#define READ_UINT64(p) buf_get_be64(p)
60
61
62
/* And the other, little-endian, byteorder */
63
0
#define LE_READ_UINT64(p) buf_get_le64(p)
64
65
0
#define LE_SWAP32(v) le_bswap32(v)
66
67
68
0
#define QROUND(x0, x1, x2, x3) do { \
69
0
  x1 ^= ROTL32(7, x0 + x3);     \
70
0
  x2 ^= ROTL32(9, x1 + x0);     \
71
0
  x3 ^= ROTL32(13, x2 + x1);      \
72
0
  x0 ^= ROTL32(18, x3 + x2);      \
73
0
  } while(0)
74
75
76
static void
77
salsa20_core (u32 *dst, const u32 *src, unsigned int rounds)
78
0
{
79
0
  u32 x[SALSA20_INPUT_LENGTH];
80
0
  unsigned i;
81
82
0
  assert ( (rounds & 1) == 0);
83
84
0
  for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
85
0
    x[i] = LE_SWAP32(src[i]);
86
87
0
  for (i = 0; i < rounds;i += 2)
88
0
    {
89
0
      QROUND(x[0], x[4], x[8], x[12]);
90
0
      QROUND(x[5], x[9], x[13], x[1]);
91
0
      QROUND(x[10], x[14], x[2], x[6]);
92
0
      QROUND(x[15], x[3], x[7], x[11]);
93
94
0
      QROUND(x[0], x[1], x[2], x[3]);
95
0
      QROUND(x[5], x[6], x[7], x[4]);
96
0
      QROUND(x[10], x[11], x[8], x[9]);
97
0
      QROUND(x[15], x[12], x[13], x[14]);
98
0
    }
99
100
0
  for (i = 0; i < SALSA20_INPUT_LENGTH; i++)
101
0
    {
102
0
      u32 t = x[i] + LE_SWAP32(src[i]);
103
0
      dst[i] = LE_SWAP32(t);
104
0
    }
105
0
}
106
107
108
static void
109
scrypt_block_mix (u32 r, unsigned char *B, unsigned char *tmp2)
110
0
{
111
0
  u64 i;
112
0
  unsigned char *X = tmp2;
113
0
  unsigned char *Y = tmp2 + 64;
114
115
#if 0
116
  if (r == 1)
117
    {
118
      for (i = 0; i < 2 * r; i++)
119
        {
120
          size_t j;
121
          printf ("B[%d] = ", (int)i);
122
          for (j = 0; j < 64; j++)
123
            {
124
              if (j && !(j % 16))
125
                printf ("\n       ");
126
              printf (" %02x", B[i * 64 + j]);
127
            }
128
          putchar ('\n');
129
        }
130
    }
131
#endif
132
133
  /* X = B[2 * r - 1] */
134
0
  memcpy (X, &B[(2 * r - 1) * 64], 64);
135
136
  /* for i = 0 to 2 * r - 1 do */
137
0
  for (i = 0; i <= 2 * r - 1; i++)
138
0
    {
139
      /* T = X xor B[i] */
140
0
      buf_xor(X, X, &B[i * 64], 64);
141
142
      /* X = Salsa (T) */
143
0
      salsa20_core ((u32*)(void*)X, (u32*)(void*)X, 8);
144
145
      /* Y[i] = X */
146
0
      memcpy (&Y[i * 64], X, 64);
147
0
    }
148
149
0
  for (i = 0; i < r; i++)
150
0
    {
151
0
      memcpy (&B[i * 64], &Y[2 * i * 64], 64);
152
0
      memcpy (&B[(r + i) * 64], &Y[(2 * i + 1) * 64], 64);
153
0
    }
154
155
#if 0
156
  if (r==1)
157
    {
158
      for (i = 0; i < 2 * r; i++)
159
        {
160
          size_t j;
161
          printf ("B'[%d] =", (int)i);
162
          for (j = 0; j < 64; j++)
163
            {
164
              if (j && !(j % 16))
165
                printf ("\n       ");
166
              printf (" %02x", B[i * 64 + j]);
167
            }
168
          putchar ('\n');
169
        }
170
    }
171
#endif
172
0
}
173
174
175
static void
176
scrypt_ro_mix (u32 r, unsigned char *B, u64 N,
177
        unsigned char *tmp1, unsigned char *tmp2)
178
0
{
179
0
  unsigned char *X = B, *T = B;
180
0
  u64 i;
181
182
#if 0
183
  if (r == 1)
184
    {
185
      printf ("B = ");
186
      for (i = 0; i < 128 * r; i++)
187
        {
188
          if (i && !(i % 16))
189
            printf ("\n    ");
190
          printf (" %02x", B[i]);
191
        }
192
      putchar ('\n');
193
    }
194
#endif
195
196
  /* for i = 0 to N - 1 do */
197
0
  for (i = 0; i <= N - 1; i++)
198
0
    {
199
      /* V[i] = X */
200
0
      memcpy (&tmp1[i * 128 * r], X, 128 * r);
201
202
      /* X =  ScryptBlockMix (X) */
203
0
      scrypt_block_mix (r, X, tmp2);
204
0
    }
205
206
  /* for i = 0 to N - 1 do */
207
0
  for (i = 0; i <= N - 1; i++)
208
0
    {
209
0
      u64 j;
210
211
      /* j = Integerify (X) mod N */
212
0
      j = LE_READ_UINT64 (&X[128 * r - 64]) % N;
213
214
      /* T = X xor V[j] */
215
0
      buf_xor (T, T, &tmp1[j * 128 * r], 128 * r);
216
217
      /* X = scryptBlockMix (T) */
218
0
      scrypt_block_mix (r, T, tmp2);
219
0
    }
220
221
#if 0
222
  if (r == 1)
223
    {
224
      printf ("B' =");
225
      for (i = 0; i < 128 * r; i++)
226
        {
227
          if (i && !(i % 16))
228
            printf ("\n    ");
229
          printf (" %02x", B[i]);
230
        }
231
      putchar ('\n');
232
    }
233
#endif
234
0
}
235
236
237
/*
238
 *
239
 */
240
gcry_err_code_t
241
_gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
242
                  int algo, int subalgo,
243
                  const unsigned char *salt, size_t saltlen,
244
                  unsigned long iterations,
245
                  size_t dkLen, unsigned char *DK)
246
0
{
247
0
  u64 N = subalgo;    /* CPU/memory cost parameter.  */
248
0
  u32 r;              /* Block size.  */
249
0
  u32 p = iterations; /* Parallelization parameter.  */
250
251
0
  gpg_err_code_t ec;
252
0
  u32 i;
253
0
  unsigned char *B = NULL;
254
0
  unsigned char *tmp1 = NULL;
255
0
  unsigned char *tmp2 = NULL;
256
0
  size_t r128;
257
0
  size_t nbytes;
258
259
0
  if (subalgo < 1 || !iterations)
260
0
    return GPG_ERR_INV_VALUE;
261
262
0
  if (algo == GCRY_KDF_SCRYPT)
263
0
    r = 8;
264
0
  else if (algo == 41) /* Hack to allow the use of all test vectors.  */
265
0
    r = 1;
266
0
  else
267
0
    return GPG_ERR_UNKNOWN_ALGORITHM;
268
269
0
  r128 = r * 128;
270
0
  if (r128 / 128 != r)
271
0
    return GPG_ERR_ENOMEM;
272
273
0
  nbytes = p * r128;
274
0
  if (r128 && nbytes / r128 != p)
275
0
    return GPG_ERR_ENOMEM;
276
277
0
  nbytes = N * r128;
278
0
  if (r128 && nbytes / r128 != N)
279
0
    return GPG_ERR_ENOMEM;
280
281
0
  nbytes = 64 + r128;
282
0
  if (nbytes < r128)
283
0
    return GPG_ERR_ENOMEM;
284
285
0
  B = xtrymalloc (p * r128);
286
0
  if (!B)
287
0
    {
288
0
      ec = gpg_err_code_from_syserror ();
289
0
      goto leave;
290
0
    }
291
292
0
  tmp1 = xtrymalloc (N * r128);
293
0
  if (!tmp1)
294
0
    {
295
0
      ec = gpg_err_code_from_syserror ();
296
0
      goto leave;
297
0
    }
298
299
0
  tmp2 = xtrymalloc (64 + r128);
300
0
  if (!tmp2)
301
0
    {
302
0
      ec = gpg_err_code_from_syserror ();
303
0
      goto leave;
304
0
    }
305
306
0
  ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, salt, saltlen,
307
0
                        1 /* iterations */, p * r128, B);
308
309
0
  for (i = 0; !ec && i < p; i++)
310
0
    scrypt_ro_mix (r, &B[i * r128], N, tmp1, tmp2);
311
312
0
  if (!ec)
313
0
    ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128,
314
0
                          1 /* iterations */, dkLen, DK);
315
316
0
 leave:
317
0
  xfree (tmp2);
318
0
  xfree (tmp1);
319
0
  xfree (B);
320
321
0
  return ec;
322
0
}