/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 | } |