yescrypt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,358 @@
1
+ /*
2
+ * yescrypt optimized implementation.
3
+ *
4
+ * Based on the scrypt algorithm by Colin Percival and the yescrypt
5
+ * extensions by Alexander Peslyak.
6
+ *
7
+ * Copyright (c) 2009 Colin Percival
8
+ * Copyright (c) 2013-2021 Alexander Peslyak
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without
12
+ * modification, are permitted.
13
+ */
14
+
15
+ #include <stdlib.h>
16
+ #include <string.h>
17
+ #include <stdint.h>
18
+
19
+ #include "yescrypt.h"
20
+ #include "sha256.h"
21
+ #include "insecure_memzero.h"
22
+
23
+ /* Defined in yescrypt-common.c */
24
+ extern int yescrypt_ensure_local(yescrypt_local_t *local, size_t need);
25
+
26
+ static inline uint32_t le32dec(const void *pp)
27
+ {
28
+ const uint8_t *p = (const uint8_t *)pp;
29
+ return (uint32_t)p[0] | ((uint32_t)p[1] << 8) |
30
+ ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
31
+ }
32
+
33
+ static inline void le32enc(void *pp, uint32_t x)
34
+ {
35
+ uint8_t *p = (uint8_t *)pp;
36
+ p[0] = x & 0xff;
37
+ p[1] = (x >> 8) & 0xff;
38
+ p[2] = (x >> 16) & 0xff;
39
+ p[3] = (x >> 24) & 0xff;
40
+ }
41
+
42
+ #define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
43
+
44
+ /* Salsa20/8 core */
45
+ static void salsa20_8(uint32_t B[16])
46
+ {
47
+ uint32_t x[16];
48
+ int i;
49
+
50
+ memcpy(x, B, sizeof(x));
51
+
52
+ for (i = 0; i < 8; i += 2) {
53
+ /* Odd round */
54
+ x[ 4] ^= ROTL32(x[ 0] + x[12], 7);
55
+ x[ 8] ^= ROTL32(x[ 4] + x[ 0], 9);
56
+ x[12] ^= ROTL32(x[ 8] + x[ 4], 13);
57
+ x[ 0] ^= ROTL32(x[12] + x[ 8], 18);
58
+ x[ 9] ^= ROTL32(x[ 5] + x[ 1], 7);
59
+ x[13] ^= ROTL32(x[ 9] + x[ 5], 9);
60
+ x[ 1] ^= ROTL32(x[13] + x[ 9], 13);
61
+ x[ 5] ^= ROTL32(x[ 1] + x[13], 18);
62
+ x[14] ^= ROTL32(x[10] + x[ 6], 7);
63
+ x[ 2] ^= ROTL32(x[14] + x[10], 9);
64
+ x[ 6] ^= ROTL32(x[ 2] + x[14], 13);
65
+ x[10] ^= ROTL32(x[ 6] + x[ 2], 18);
66
+ x[ 3] ^= ROTL32(x[15] + x[11], 7);
67
+ x[ 7] ^= ROTL32(x[ 3] + x[15], 9);
68
+ x[11] ^= ROTL32(x[ 7] + x[ 3], 13);
69
+ x[15] ^= ROTL32(x[11] + x[ 7], 18);
70
+ /* Even round */
71
+ x[ 1] ^= ROTL32(x[ 0] + x[ 3], 7);
72
+ x[ 2] ^= ROTL32(x[ 1] + x[ 0], 9);
73
+ x[ 3] ^= ROTL32(x[ 2] + x[ 1], 13);
74
+ x[ 0] ^= ROTL32(x[ 3] + x[ 2], 18);
75
+ x[ 6] ^= ROTL32(x[ 5] + x[ 4], 7);
76
+ x[ 7] ^= ROTL32(x[ 6] + x[ 5], 9);
77
+ x[ 4] ^= ROTL32(x[ 7] + x[ 6], 13);
78
+ x[ 5] ^= ROTL32(x[ 4] + x[ 7], 18);
79
+ x[11] ^= ROTL32(x[10] + x[ 9], 7);
80
+ x[ 8] ^= ROTL32(x[11] + x[10], 9);
81
+ x[ 9] ^= ROTL32(x[ 8] + x[11], 13);
82
+ x[10] ^= ROTL32(x[ 9] + x[ 8], 18);
83
+ x[12] ^= ROTL32(x[15] + x[14], 7);
84
+ x[13] ^= ROTL32(x[12] + x[15], 9);
85
+ x[14] ^= ROTL32(x[13] + x[12], 13);
86
+ x[15] ^= ROTL32(x[14] + x[13], 18);
87
+ }
88
+
89
+ for (i = 0; i < 16; i++)
90
+ B[i] += x[i];
91
+ }
92
+
93
+ /* scrypt BlockMix using Salsa20/8 */
94
+ static void blockmix_salsa8(const uint32_t *Bin, uint32_t *Bout, uint32_t *X, size_t r)
95
+ {
96
+ size_t i;
97
+ size_t r2 = 2 * r;
98
+
99
+ /* X = B[2r - 1] */
100
+ memcpy(X, &Bin[(r2 - 1) * 16], 64);
101
+
102
+ for (i = 0; i < r2; i++) {
103
+ /* X = X xor B[i] */
104
+ size_t k;
105
+ for (k = 0; k < 16; k++)
106
+ X[k] ^= Bin[i * 16 + k];
107
+
108
+ salsa20_8(X);
109
+
110
+ /* Y[i] = X */
111
+ /* Place even blocks at start, odd at end */
112
+ if (i % 2 == 0)
113
+ memcpy(&Bout[(i / 2) * 16], X, 64);
114
+ else
115
+ memcpy(&Bout[(r + i / 2) * 16], X, 64);
116
+ }
117
+ }
118
+
119
+ /* Integerify: extract a 64-bit integer from block B */
120
+ static inline uint64_t integerify(const uint32_t *B, size_t r)
121
+ {
122
+ const uint32_t *X = &B[(2 * r - 1) * 16];
123
+ return (uint64_t)X[0] | ((uint64_t)X[13] << 32);
124
+ }
125
+
126
+ /*
127
+ * pwxform: password-dependent computation for yescrypt.
128
+ * This makes time-memory tradeoff attacks more expensive.
129
+ *
130
+ * PWXgather/PWXround/PWXloop simplified for the default parameters.
131
+ */
132
+
133
+ /* PWXform parameters for YESCRYPT_DEFAULTS */
134
+ #define PWXSIMPLE 2
135
+ #define PWXGATHER 4
136
+ #define PWXROUNDS 6
137
+ #define PWXBYTES (PWXGATHER * PWXSIMPLE * 8)
138
+ #define PWXWORDS (PWXBYTES / sizeof(uint32_t))
139
+
140
+ /* S-box size: 2 * PWXGATHER * PWXSIMPLE * 8 * (PWXROUNDS + 2) */
141
+ #define SWORDS (2 * PWXGATHER * PWXSIMPLE * (PWXROUNDS + 2))
142
+
143
+ static void pwxform(uint32_t *B, const uint32_t *S)
144
+ {
145
+ int i, j;
146
+ uint32_t (*X)[PWXSIMPLE * 2] = (void *)B;
147
+ const uint32_t *S0 = S;
148
+ const uint32_t *S1 = S + SWORDS / 2;
149
+
150
+ for (i = 0; i < PWXROUNDS; i++) {
151
+ for (j = 0; j < PWXGATHER; j++) {
152
+ uint32_t xl = X[j][0];
153
+ uint32_t xh = X[j][1];
154
+
155
+ /* Lookup in S-boxes */
156
+ const uint32_t *p0 = S0 + (xl & ((SWORDS / 4 - 1) & ~1));
157
+ const uint32_t *p1 = S1 + (xh & ((SWORDS / 4 - 1) & ~1));
158
+
159
+ /* Multiply and add */
160
+ uint64_t x = (uint64_t)xh * xl;
161
+ X[j][0] = (uint32_t)x + p0[0];
162
+ X[j][1] = (uint32_t)(x >> 32) + p1[1];
163
+
164
+ if (PWXSIMPLE > 1) {
165
+ xl = X[j][2];
166
+ xh = X[j][3];
167
+ p0 = S0 + (xl & ((SWORDS / 4 - 1) & ~1));
168
+ p1 = S1 + (xh & ((SWORDS / 4 - 1) & ~1));
169
+ x = (uint64_t)xh * xl;
170
+ X[j][2] = (uint32_t)x + p0[0];
171
+ X[j][3] = (uint32_t)(x >> 32) + p1[1];
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ /* BlockMix using pwxform (yescrypt-specific) */
178
+ static void blockmix_pwxform(const uint32_t *Bin, uint32_t *Bout,
179
+ uint32_t *S, size_t r)
180
+ {
181
+ size_t r1 = 128 * r / PWXBYTES;
182
+ size_t i, k;
183
+ uint32_t X[PWXWORDS];
184
+
185
+ /* X = B[r1 - 1] */
186
+ memcpy(X, &Bin[(r1 - 1) * PWXWORDS], PWXBYTES);
187
+
188
+ for (i = 0; i < r1; i++) {
189
+ /* X = X xor B[i] */
190
+ for (k = 0; k < PWXWORDS; k++)
191
+ X[k] ^= Bin[i * PWXWORDS + k];
192
+
193
+ pwxform(X, S);
194
+
195
+ memcpy(&Bout[i * PWXWORDS], X, PWXBYTES);
196
+ }
197
+
198
+ /* Final Salsa20/8 on last block */
199
+ i = (r1 - 1) * PWXWORDS;
200
+ salsa20_8(&Bout[i > 15 ? i : 0]);
201
+ }
202
+
203
+ /*
204
+ * SMix - the core sequential memory-hard function.
205
+ *
206
+ * For YESCRYPT_WORM (classic scrypt):
207
+ * 1. Expand: V[i] = BlockMix(V[i-1]) for i = 0..N-1
208
+ * 2. Mix: for i = 0..N-1: j = Integerify(X) % N; X = BlockMix(X xor V[j])
209
+ *
210
+ * For YESCRYPT_RW (yescrypt):
211
+ * Uses pwxform-based BlockMix and updates V entries during mixing.
212
+ */
213
+ static void smix(uint8_t *B, size_t r, uint64_t N, uint32_t t,
214
+ yescrypt_flags_t flags,
215
+ uint32_t *V, uint32_t *XY, uint32_t *S,
216
+ const yescrypt_shared_t *shared)
217
+ {
218
+ (void)shared;
219
+ size_t s = 32 * r;
220
+ uint32_t *X = XY;
221
+ uint32_t *Y = &XY[s];
222
+ uint32_t *Z = &XY[2 * s];
223
+ uint64_t i, j;
224
+ size_t k;
225
+ int use_pwxform = (flags & YESCRYPT_RW) || (flags >= YESCRYPT_DEFAULTS);
226
+
227
+ /* Convert B from bytes to uint32 (little-endian) */
228
+ for (k = 0; k < s; k++)
229
+ X[k] = le32dec(&B[k * 4]);
230
+
231
+ /* Step 1: Expand - fill V */
232
+ if (use_pwxform && S) {
233
+ /* Initialize S-boxes from X */
234
+ uint32_t *src = X;
235
+ uint32_t *Sp = S;
236
+ for (k = 0; k < SWORDS; k += PWXWORDS) {
237
+ size_t m;
238
+ for (m = 0; m < PWXWORDS && m < s; m++)
239
+ Sp[k + m] = src[m % s];
240
+ /* Simple mixing */
241
+ if (k + PWXWORDS <= SWORDS)
242
+ salsa20_8(&Sp[k > 0 ? k : 0]);
243
+ }
244
+ }
245
+
246
+ for (i = 0; i < N; i++) {
247
+ /* V[i] = X */
248
+ memcpy(&V[i * s], X, s * sizeof(uint32_t));
249
+
250
+ if (use_pwxform && S)
251
+ blockmix_pwxform(X, Y, S, r);
252
+ else
253
+ blockmix_salsa8(X, Y, Z, r);
254
+
255
+ /* Swap X and Y */
256
+ uint32_t *tmp = X; X = Y; Y = tmp;
257
+ }
258
+
259
+ /* Step 2: Mix */
260
+ uint64_t Nloop = N; /* default iterations */
261
+ if (t > 0) {
262
+ /* Extra time cost: more iterations */
263
+ Nloop = N * (t + 1);
264
+ }
265
+
266
+ for (i = 0; i < Nloop; i++) {
267
+ j = integerify(X, r) & (N - 1);
268
+
269
+ /* X = X xor V[j] */
270
+ for (k = 0; k < s; k++)
271
+ X[k] ^= V[j * s + k];
272
+
273
+ /* If RW mode, update V[j] */
274
+ if (use_pwxform) {
275
+ memcpy(&V[j * s], X, s * sizeof(uint32_t));
276
+ }
277
+
278
+ if (use_pwxform && S)
279
+ blockmix_pwxform(X, Y, S, r);
280
+ else
281
+ blockmix_salsa8(X, Y, Z, r);
282
+
283
+ uint32_t *tmp = X; X = Y; Y = tmp;
284
+ }
285
+
286
+ /* Convert X back to bytes */
287
+ for (k = 0; k < s; k++)
288
+ le32enc(&B[k * 4], X[k]);
289
+ }
290
+
291
+ /*
292
+ * yescrypt KDF - the main entry point.
293
+ */
294
+ int yescrypt_kdf(
295
+ const yescrypt_shared_t *shared,
296
+ yescrypt_local_t *local,
297
+ const uint8_t *passwd, size_t passwdlen,
298
+ const uint8_t *salt, size_t saltlen,
299
+ const yescrypt_params_t *params,
300
+ uint8_t *buf, size_t buflen)
301
+ {
302
+ yescrypt_flags_t flags = params->flags;
303
+ uint64_t N = params->N;
304
+ uint32_t r = params->r;
305
+ uint32_t p = params->p;
306
+ uint32_t t = params->t;
307
+ size_t B_size, V_size, XY_size, S_size, need;
308
+ uint8_t *B;
309
+ uint32_t *V, *XY, *S;
310
+ uint32_t i;
311
+
312
+ /* Validate parameters */
313
+ if (N < 2 || (N & (N - 1)) != 0) /* N must be power of 2, >= 2 */
314
+ return -1;
315
+ if (r < 1 || p < 1)
316
+ return -1;
317
+ if (buflen < 1)
318
+ return -1;
319
+
320
+ /* Calculate memory requirements with overflow checks */
321
+ B_size = (size_t)128 * r * p;
322
+ V_size = (size_t)128 * r * N;
323
+ XY_size = (size_t)256 * r + 64;
324
+ S_size = SWORDS * sizeof(uint32_t);
325
+
326
+ /* Guard against size_t overflow (critical on 32-bit platforms) */
327
+ if (r != 0 && V_size / r / 128 != N)
328
+ return -1;
329
+ if (V_size > SIZE_MAX - B_size - XY_size - S_size)
330
+ return -1;
331
+
332
+ need = B_size + V_size + XY_size + S_size;
333
+
334
+ /* Allocate working memory */
335
+ if (yescrypt_ensure_local(local, need))
336
+ return -1;
337
+
338
+ B = (uint8_t *)local->aligned;
339
+ V = (uint32_t *)(B + B_size);
340
+ XY = (uint32_t *)((uint8_t *)V + V_size);
341
+ S = (uint32_t *)((uint8_t *)XY + XY_size);
342
+
343
+ /* Step 1: PBKDF2-HMAC-SHA256 to generate initial B */
344
+ PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
345
+
346
+ /* Step 2: Apply SMix to each block */
347
+ for (i = 0; i < p; i++) {
348
+ smix(&B[(size_t)128 * i * r], r, N, t, flags, V, XY, S, shared);
349
+ }
350
+
351
+ /* Step 3: PBKDF2-HMAC-SHA256 to generate output */
352
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
353
+
354
+ /* Clean up */
355
+ insecure_memzero(B, B_size);
356
+
357
+ return 0;
358
+ }
@@ -0,0 +1,124 @@
1
+ /*
2
+ * yescrypt API header.
3
+ *
4
+ * Copyright (c) 2013-2021 Alexander Peslyak
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions
9
+ * are met:
10
+ * 1. Redistributions of source code must retain the above copyright
11
+ * notice, this list of conditions and the following disclaimer.
12
+ * 2. Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED.
20
+ */
21
+
22
+ #ifndef YESCRYPT_H
23
+ #define YESCRYPT_H
24
+
25
+ #include <stddef.h>
26
+ #include <stdint.h>
27
+
28
+ /* yescrypt flavor flags */
29
+ typedef enum {
30
+ /* Classic scrypt */
31
+ YESCRYPT_WORM = 0,
32
+ /* yescrypt with read-write access (stronger) */
33
+ YESCRYPT_RW = 1,
34
+ /* Recommended defaults (includes YESCRYPT_RW) */
35
+ YESCRYPT_DEFAULTS = 2,
36
+ /* Flags for backwards compatibility modes */
37
+ YESCRYPT_ROUNDS_3 = 0x000,
38
+ YESCRYPT_ROUNDS_6 = 0x004,
39
+ YESCRYPT_GATHER_1 = 0x000,
40
+ YESCRYPT_GATHER_2 = 0x008,
41
+ YESCRYPT_GATHER_4 = 0x010,
42
+ YESCRYPT_GATHER_8 = 0x018,
43
+ YESCRYPT_SIMPLE_1 = 0x000,
44
+ YESCRYPT_SIMPLE_2 = 0x020,
45
+ YESCRYPT_SIMPLE_4 = 0x040,
46
+ YESCRYPT_SIMPLE_8 = 0x060
47
+ } yescrypt_flags_t;
48
+
49
+ /* Parameter structure */
50
+ typedef struct {
51
+ yescrypt_flags_t flags;
52
+ uint64_t N; /* block count (must be a power of 2) */
53
+ uint32_t r; /* block size parameter */
54
+ uint32_t p; /* parallelism parameter */
55
+ uint32_t t; /* time parameter (extra rounds) */
56
+ uint32_t g; /* ROM generation count */
57
+ } yescrypt_params_t;
58
+
59
+ /* Thread-local working memory */
60
+ typedef struct {
61
+ void *base;
62
+ size_t aligned_size;
63
+ void *aligned;
64
+ } yescrypt_region_t;
65
+
66
+ typedef yescrypt_region_t yescrypt_local_t;
67
+
68
+ /* Shared ROM (optional) */
69
+ typedef struct {
70
+ yescrypt_region_t region;
71
+ uint64_t mask1;
72
+ uint64_t N;
73
+ int dummy;
74
+ } yescrypt_shared_t;
75
+
76
+ /* Hash output buffer size */
77
+ #define YESCRYPT_HASH_SIZE 32
78
+
79
+ /* Maximum encoded hash length */
80
+ #define YESCRYPT_MAX_ENCODED 512
81
+
82
+ /* Initialize thread-local storage */
83
+ int yescrypt_init_local(yescrypt_local_t *local);
84
+
85
+ /* Free thread-local storage */
86
+ int yescrypt_free_local(yescrypt_local_t *local);
87
+
88
+ /* Initialize shared memory (no ROM) */
89
+ int yescrypt_init_shared(yescrypt_shared_t *shared);
90
+
91
+ /* Free shared memory */
92
+ int yescrypt_free_shared(yescrypt_shared_t *shared);
93
+
94
+ /* The main KDF function */
95
+ int yescrypt_kdf(
96
+ const yescrypt_shared_t *shared,
97
+ yescrypt_local_t *local,
98
+ const uint8_t *passwd, size_t passwdlen,
99
+ const uint8_t *salt, size_t saltlen,
100
+ const yescrypt_params_t *params,
101
+ uint8_t *buf, size_t buflen);
102
+
103
+ /* Crypt-style interface: generate a setting string */
104
+ uint8_t *yescrypt_gensalt(
105
+ uint32_t N_log2, uint32_t r, uint32_t p, uint32_t t,
106
+ yescrypt_flags_t flags,
107
+ const uint8_t *src, size_t srclen,
108
+ uint8_t *buf, size_t buflen);
109
+
110
+ /* Decode params from a setting string (no salt output) */
111
+ const uint8_t *yescrypt_decode_params_ext(
112
+ const uint8_t *setting,
113
+ uint32_t *N_log2, uint32_t *r, uint32_t *p, uint32_t *t,
114
+ yescrypt_flags_t *flags);
115
+
116
+ /* Crypt-style interface: hash a password */
117
+ uint8_t *yescrypt_r(
118
+ const yescrypt_shared_t *shared,
119
+ yescrypt_local_t *local,
120
+ const uint8_t *passwd, size_t passwdlen,
121
+ const uint8_t *setting,
122
+ uint8_t *buf, size_t buflen);
123
+
124
+ #endif /* YESCRYPT_H */