source: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/wolfcrypt/src/pwdbased.c@ 372

Last change on this file since 372 was 372, checked in by coas-nagasima, 5 years ago

wolfsslを3.15.7にバージョンアップ

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 19.6 KB
Line 
1/* pwdbased.c
2 *
3 * Copyright (C) 2006-2017 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23#ifdef HAVE_CONFIG_H
24 #include <config.h>
25#endif
26
27#include <wolfssl/wolfcrypt/settings.h>
28
29#ifndef NO_PWDBASED
30
31#include <wolfssl/wolfcrypt/pwdbased.h>
32#include <wolfssl/wolfcrypt/hmac.h>
33#include <wolfssl/wolfcrypt/hash.h>
34#include <wolfssl/wolfcrypt/integer.h>
35#include <wolfssl/wolfcrypt/error-crypt.h>
36
37#ifdef NO_INLINE
38 #include <wolfssl/wolfcrypt/misc.h>
39#else
40 #define WOLFSSL_MISC_INCLUDED
41 #include <wolfcrypt/src/misc.c>
42#endif
43
44
45/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
46int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
47 const byte* passwd, int passwdLen, const byte* salt, int saltLen,
48 int iterations, int hashType, void* heap)
49{
50 int err;
51 int keyLeft, ivLeft, i;
52 int digestLeft, store;
53 int keyOutput = 0;
54 int diestLen;
55 byte digest[WC_MAX_DIGEST_SIZE];
56#ifdef WOLFSSL_SMALL_STACK
57 wc_HashAlg* hash = NULL;
58#else
59 wc_HashAlg hash[1];
60#endif
61 enum wc_HashType hashT;
62
63 (void)heap;
64
65 if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){
66 return BAD_FUNC_ARG;
67 }
68
69 if (iterations <= 0)
70 iterations = 1;
71
72 hashT = wc_HashTypeConvert(hashType);
73 err = wc_HashGetDigestSize(hashT);
74 if (err < 0)
75 return err;
76 diestLen = err;
77
78 /* initialize hash */
79#ifdef WOLFSSL_SMALL_STACK
80 hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap,
81 DYNAMIC_TYPE_HASHCTX);
82 if (hash == NULL)
83 return MEMORY_E;
84#endif
85
86 err = wc_HashInit(hash, hashT);
87 if (err != 0) {
88 #ifdef WOLFSSL_SMALL_STACK
89 XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
90 #endif
91 return err;
92 }
93
94 keyLeft = keyLen;
95 ivLeft = ivLen;
96 while (keyOutput < (keyLen + ivLen)) {
97 digestLeft = diestLen;
98 /* D_(i - 1) */
99 if (keyOutput) { /* first time D_0 is empty */
100 err = wc_HashUpdate(hash, hashT, digest, diestLen);
101 if (err != 0) break;
102 }
103
104 /* data */
105 err = wc_HashUpdate(hash, hashT, passwd, passwdLen);
106 if (err != 0) break;
107
108 /* salt */
109 if (salt) {
110 err = wc_HashUpdate(hash, hashT, salt, saltLen);
111 if (err != 0) break;
112 }
113
114 err = wc_HashFinal(hash, hashT, digest);
115 if (err != 0) break;
116
117 /* count */
118 for (i = 1; i < iterations; i++) {
119 err = wc_HashUpdate(hash, hashT, digest, diestLen);
120 if (err != 0) break;
121
122 err = wc_HashFinal(hash, hashT, digest);
123 if (err != 0) break;
124 }
125
126 if (keyLeft) {
127 store = min(keyLeft, diestLen);
128 XMEMCPY(&key[keyLen - keyLeft], digest, store);
129
130 keyOutput += store;
131 keyLeft -= store;
132 digestLeft -= store;
133 }
134
135 if (ivLeft && digestLeft) {
136 store = min(ivLeft, digestLeft);
137 if (iv != NULL)
138 XMEMCPY(&iv[ivLen - ivLeft],
139 &digest[diestLen - digestLeft], store);
140 keyOutput += store;
141 ivLeft -= store;
142 }
143 }
144
145 wc_HashFree(hash, hashT);
146
147#ifdef WOLFSSL_SMALL_STACK
148 XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX);
149#endif
150
151 if (err != 0)
152 return err;
153
154 if (keyOutput != (keyLen + ivLen))
155 return BUFFER_E;
156
157 return err;
158 }
159
160/* PKCS#5 v1.5 */
161int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
162 int sLen, int iterations, int kLen, int hashType)
163{
164 return wc_PBKDF1_ex(output, kLen, NULL, 0,
165 passwd, pLen, salt, sLen, iterations, hashType, NULL);
166}
167
168
169int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
170 int sLen, int iterations, int kLen, int hashType)
171{
172 word32 i = 1;
173 int hLen;
174 int j, ret;
175#ifdef WOLFSSL_SMALL_STACK
176 byte* buffer;
177 Hmac* hmac;
178#else
179 byte buffer[WC_MAX_DIGEST_SIZE];
180 Hmac hmac[1];
181#endif
182 enum wc_HashType hashT;
183
184 if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) {
185 return BAD_FUNC_ARG;
186 }
187
188 if (iterations <= 0)
189 iterations = 1;
190
191 hashT = wc_HashTypeConvert(hashType);
192 hLen = wc_HashGetDigestSize(hashT);
193 if (hLen < 0)
194 return BAD_FUNC_ARG;
195
196#ifdef WOLFSSL_SMALL_STACK
197 buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
198 if (buffer == NULL)
199 return MEMORY_E;
200 hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC);
201 if (buffer == NULL)
202 return MEMORY_E;
203#endif
204
205 ret = wc_HmacInit(hmac, NULL, INVALID_DEVID);
206 if (ret == 0) {
207 /* use int hashType here, since HMAC FIPS uses the old unique value */
208 ret = wc_HmacSetKey(hmac, hashType, passwd, pLen);
209
210 while (ret == 0 && kLen) {
211 int currentLen;
212
213 ret = wc_HmacUpdate(hmac, salt, sLen);
214 if (ret != 0)
215 break;
216
217 /* encode i */
218 for (j = 0; j < 4; j++) {
219 byte b = (byte)(i >> ((3-j) * 8));
220
221 ret = wc_HmacUpdate(hmac, &b, 1);
222 if (ret != 0)
223 break;
224 }
225
226 /* check ret from inside for loop */
227 if (ret != 0)
228 break;
229
230 ret = wc_HmacFinal(hmac, buffer);
231 if (ret != 0)
232 break;
233
234 currentLen = min(kLen, hLen);
235 XMEMCPY(output, buffer, currentLen);
236
237 for (j = 1; j < iterations; j++) {
238 ret = wc_HmacUpdate(hmac, buffer, hLen);
239 if (ret != 0)
240 break;
241 ret = wc_HmacFinal(hmac, buffer);
242 if (ret != 0)
243 break;
244 xorbuf(output, buffer, currentLen);
245 }
246
247 /* check ret from inside for loop */
248 if (ret != 0)
249 break;
250
251 output += currentLen;
252 kLen -= currentLen;
253 i++;
254 }
255 wc_HmacFree(hmac);
256 }
257
258#ifdef WOLFSSL_SMALL_STACK
259 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
260 XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC);
261#endif
262
263 return ret;
264}
265
266/* helper for PKCS12_PBKDF(), does hash operation */
267static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
268 byte* Ai, word32 u, int iterations)
269{
270 int i;
271 int ret = 0;
272#ifdef WOLFSSL_SMALL_STACK
273 wc_HashAlg* hash = NULL;
274#else
275 wc_HashAlg hash[1];
276#endif
277 enum wc_HashType hashT;
278
279 if (buffer == NULL || Ai == NULL) {
280 return BAD_FUNC_ARG;
281 }
282
283 hashT = wc_HashTypeConvert(hashType);
284
285 /* initialize hash */
286#ifdef WOLFSSL_SMALL_STACK
287 hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL,
288 DYNAMIC_TYPE_HASHCTX);
289 if (hash == NULL)
290 return MEMORY_E;
291#endif
292
293 ret = wc_HashInit(hash, hashT);
294 if (ret != 0) {
295 #ifdef WOLFSSL_SMALL_STACK
296 XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
297 #endif
298 return ret;
299 }
300
301 ret = wc_HashUpdate(hash, hashT, buffer, totalLen);
302
303 if (ret == 0)
304 ret = wc_HashFinal(hash, hashT, Ai);
305
306 for (i = 1; i < iterations; i++) {
307 if (ret == 0)
308 ret = wc_HashUpdate(hash, hashT, Ai, u);
309 if (ret == 0)
310 ret = wc_HashFinal(hash, hashT, Ai);
311 }
312
313 wc_HashFree(hash, hashT);
314
315#ifdef WOLFSSL_SMALL_STACK
316 XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX);
317#endif
318
319 return ret;
320}
321
322
323int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
324 const byte* salt, int saltLen, int iterations, int kLen, int hashType,
325 int id)
326{
327 return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
328 iterations, kLen, hashType, id, NULL);
329}
330
331
332/* extended API that allows a heap hint to be used */
333int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
334 const byte* salt, int saltLen, int iterations, int kLen,
335 int hashType, int id, void* heap)
336{
337 /* all in bytes instead of bits */
338 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
339 int dynamic = 0;
340 int ret = 0;
341 int i;
342 byte *D, *S, *P, *I;
343#ifdef WOLFSSL_SMALL_STACK
344 byte staticBuffer[1]; /* force dynamic usage */
345#else
346 byte staticBuffer[1024];
347#endif
348 byte* buffer = staticBuffer;
349
350#ifdef WOLFSSL_SMALL_STACK
351 byte* Ai;
352 byte* B;
353#else
354 byte Ai[WC_MAX_DIGEST_SIZE];
355 byte B[WC_MAX_BLOCK_SIZE];
356#endif
357 enum wc_HashType hashT;
358
359 (void)heap;
360
361 if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) {
362 return BAD_FUNC_ARG;
363 }
364
365 if (iterations <= 0)
366 iterations = 1;
367
368 hashT = wc_HashTypeConvert(hashType);
369 ret = wc_HashGetDigestSize(hashT);
370 if (ret < 0)
371 return ret;
372 u = ret;
373
374 ret = wc_HashGetBlockSize(hashT);
375 if (ret < 0)
376 return ret;
377 v = ret;
378
379#ifdef WOLFSSL_SMALL_STACK
380 Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
381 if (Ai == NULL)
382 return MEMORY_E;
383
384 B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
385 if (B == NULL) {
386 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
387 return MEMORY_E;
388 }
389#endif
390
391 XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE);
392 XMEMSET(B, 0, WC_MAX_BLOCK_SIZE);
393
394 dLen = v;
395 sLen = v * ((saltLen + v - 1) / v);
396 if (passLen)
397 pLen = v * ((passLen + v - 1) / v);
398 else
399 pLen = 0;
400 iLen = sLen + pLen;
401
402 totalLen = dLen + sLen + pLen;
403
404 if (totalLen > sizeof(staticBuffer)) {
405 buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
406 if (buffer == NULL) {
407#ifdef WOLFSSL_SMALL_STACK
408 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
409 XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
410#endif
411 return MEMORY_E;
412 }
413 dynamic = 1;
414 }
415
416 D = buffer;
417 S = D + dLen;
418 P = S + sLen;
419 I = S;
420
421 XMEMSET(D, id, dLen);
422
423 for (i = 0; i < (int)sLen; i++)
424 S[i] = salt[i % saltLen];
425 for (i = 0; i < (int)pLen; i++)
426 P[i] = passwd[i % passLen];
427
428 while (kLen > 0) {
429 word32 currentLen;
430 mp_int B1;
431
432 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
433 if (ret < 0)
434 break;
435
436 for (i = 0; i < (int)v; i++)
437 B[i] = Ai[i % u];
438
439 if (mp_init(&B1) != MP_OKAY)
440 ret = MP_INIT_E;
441 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
442 ret = MP_READ_E;
443 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
444 ret = MP_ADD_E;
445
446 if (ret != 0) {
447 mp_clear(&B1);
448 break;
449 }
450
451 for (i = 0; i < (int)iLen; i += v) {
452 int outSz;
453 mp_int i1;
454 mp_int res;
455
456 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
457 ret = MP_INIT_E;
458 break;
459 }
460 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
461 ret = MP_READ_E;
462 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
463 ret = MP_ADD_E;
464 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
465 ret = MP_TO_E;
466 else {
467 if (outSz > (int)v) {
468 /* take off MSB */
469 byte tmp[129];
470 ret = mp_to_unsigned_bin(&res, tmp);
471 XMEMCPY(I + i, tmp + 1, v);
472 }
473 else if (outSz < (int)v) {
474 XMEMSET(I + i, 0, v - outSz);
475 ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
476 }
477 else
478 ret = mp_to_unsigned_bin(&res, I + i);
479 }
480
481 mp_clear(&i1);
482 mp_clear(&res);
483 if (ret < 0) break;
484 }
485
486 currentLen = min(kLen, (int)u);
487 XMEMCPY(output, Ai, currentLen);
488 output += currentLen;
489 kLen -= currentLen;
490 mp_clear(&B1);
491 }
492
493 if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
494
495#ifdef WOLFSSL_SMALL_STACK
496 XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
497 XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
498#endif
499
500 return ret;
501}
502
503#ifdef HAVE_SCRYPT
504/* Rotate the 32-bit value a by b bits to the left.
505 *
506 * a 32-bit value.
507 * b Number of bits to rotate.
508 * returns rotated value.
509 */
510#define R(a, b) rotlFixed(a, b)
511
512/* One round of Salsa20/8.
513 * Code taken from RFC 7914: scrypt PBKDF.
514 *
515 * out Output buffer.
516 * in Input data to hash.
517 */
518static void scryptSalsa(word32* out, word32* in)
519{
520 int i;
521 word32 x[16];
522
523#ifdef LITTLE_ENDIAN_ORDER
524 for (i = 0; i < 16; ++i)
525 x[i] = in[i];
526#else
527 for (i = 0; i < 16; i++)
528 x[i] = ByteReverseWord32(in[i]);
529#endif
530 for (i = 8; i > 0; i -= 2) {
531 x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9);
532 x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18);
533 x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9);
534 x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18);
535 x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9);
536 x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18);
537 x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9);
538 x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18);
539 x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9);
540 x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18);
541 x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9);
542 x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18);
543 x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9);
544 x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18);
545 x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9);
546 x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18);
547 }
548#ifdef LITTLE_ENDIAN_ORDER
549 for (i = 0; i < 16; ++i)
550 out[i] = in[i] + x[i];
551#else
552 for (i = 0; i < 16; i++)
553 out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
554#endif
555}
556
557/* Mix a block using Salsa20/8.
558 * Based on RFC 7914: scrypt PBKDF.
559 *
560 * b Blocks to mix.
561 * y Temporary storage.
562 * r Size of the block.
563 */
564static void scryptBlockMix(byte* b, byte* y, int r)
565{
566 byte x[64];
567#ifdef WORD64_AVAILABLE
568 word64* b64 = (word64*)b;
569 word64* y64 = (word64*)y;
570 word64* x64 = (word64*)x;
571#else
572 word32* b32 = (word32*)b;
573 word32* y32 = (word32*)y;
574 word32* x32 = (word32*)x;
575#endif
576 int i;
577 int j;
578
579 /* Step 1. */
580 XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
581 /* Step 2. */
582 for (i = 0; i < 2 * r; i++)
583 {
584#ifdef WORD64_AVAILABLE
585 for (j = 0; j < 8; j++)
586 x64[j] ^= b64[i * 8 + j];
587#else
588 for (j = 0; j < 16; j++)
589 x32[j] ^= b32[i * 16 + j];
590#endif
591 scryptSalsa((word32*)x, (word32*)x);
592 XMEMCPY(y + i * 64, x, sizeof(x));
593 }
594 /* Step 3. */
595 for (i = 0; i < r; i++) {
596#ifdef WORD64_AVAILABLE
597 for (j = 0; j < 8; j++) {
598 b64[i * 8 + j] = y64[2 * i * 8 + j];
599 b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
600 }
601#else
602 for (j = 0; j < 16; j++) {
603 b32[i * 16 + j] = y32[2 * i * 16 + j];
604 b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
605 }
606#endif
607 }
608}
609
610/* Random oracles mix.
611 * Based on RFC 7914: scrypt PBKDF.
612 *
613 * x Data to mix.
614 * v Temporary buffer.
615 * y Temporary buffer for the block mix.
616 * r Block size parameter.
617 * n CPU/Memory cost parameter.
618 */
619static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
620{
621 word32 i;
622 word32 j;
623 word32 k;
624 word32 bSz = 128 * r;
625#ifdef WORD64_AVAILABLE
626 word64* x64 = (word64*)x;
627 word64* v64 = (word64*)v;
628#else
629 word32* x32 = (word32*)x;
630 word32* v32 = (word32*)v;
631#endif
632
633 /* Step 1. X = B (B not needed therefore not implemented) */
634 /* Step 2. */
635 for (i = 0; i < n; i++)
636 {
637 XMEMCPY(v + i * bSz, x, bSz);
638 scryptBlockMix(x, y, r);
639 }
640
641 /* Step 3. */
642 for (i = 0; i < n; i++)
643 {
644#ifdef LITTLE_ENDIAN_ORDER
645#ifdef WORD64_AVAILABLE
646 j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
647#else
648 j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
649#endif
650#else
651 byte* t = x + (2*r - 1) * 64;
652 j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1);
653#endif
654#ifdef WORD64_AVAILABLE
655 for (k = 0; k < bSz / 8; k++)
656 x64[k] ^= v64[j * bSz / 8 + k];
657#else
658 for (k = 0; k < bSz / 4; k++)
659 x32[k] ^= v32[j * bSz / 4 + k];
660#endif
661 scryptBlockMix(x, y, r);
662 }
663 /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
664}
665
666/* Generates an key derived from a password and salt using a memory hard
667 * algorithm.
668 * Implements RFC 7914: scrypt PBKDF.
669 *
670 * output The derived key.
671 * passwd The password to derive key from.
672 * passLen The length of the password.
673 * salt The key specific data.
674 * saltLen The length of the salt data.
675 * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1)
676 * (Iterations = 2^cost)
677 * blockSize The number of 128 byte octets in a working block.
678 * parallel The number of parallel mix operations to perform.
679 * (Note: this implementation does not use threads.)
680 * dkLen The length of the derived key in bytes.
681 * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost.
682 */
683int wc_scrypt(byte* output, const byte* passwd, int passLen,
684 const byte* salt, int saltLen, int cost, int blockSize,
685 int parallel, int dkLen)
686{
687 int ret = 0;
688 int i;
689 byte* v = NULL;
690 byte* y = NULL;
691 byte* blocks = NULL;
692 word32 blocksSz;
693 word32 bSz;
694
695 if (blockSize > 8)
696 return BAD_FUNC_ARG;
697
698 if (cost < 1 || cost >= 128 * blockSize / 8)
699 return BAD_FUNC_ARG;
700
701 bSz = 128 * blockSize;
702 blocksSz = bSz * parallel;
703 blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
704 if (blocks == NULL)
705 goto end;
706 /* Temporary for scryptROMix. */
707 v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
708 if (v == NULL)
709 goto end;
710 /* Temporary for scryptBlockMix. */
711 y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
712 if (y == NULL)
713 goto end;
714
715 /* Step 1. */
716 ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz,
717 WC_SHA256);
718 if (ret != 0)
719 goto end;
720
721 /* Step 2. */
722 for (i = 0; i < parallel; i++)
723 scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost);
724
725 /* Step 3. */
726 ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen,
727 WC_SHA256);
728end:
729 if (blocks != NULL)
730 XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
731 if (v != NULL)
732 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
733 if (y != NULL)
734 XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
735
736 return ret;
737}
738#endif
739
740#undef WC_MAX_DIGEST_SIZE
741
742#endif /* NO_PWDBASED */
743
Note: See TracBrowser for help on using the repository browser.