source: asp3_tinet_ecnl_arm/trunk/wolfssl-3.12.2/wolfcrypt/src/pwdbased.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 21.7 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/integer.h>
34#include <wolfssl/wolfcrypt/error-crypt.h>
35#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
36 #include <wolfssl/wolfcrypt/sha512.h>
37#endif
38
39#ifdef NO_INLINE
40 #include <wolfssl/wolfcrypt/misc.h>
41#else
42 #define WOLFSSL_MISC_INCLUDED
43 #include <wolfcrypt/src/misc.c>
44#endif
45
46
47#ifndef NO_SHA
48/* PBKDF1 needs at least SHA available */
49int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
50 int sLen, int iterations, int kLen, int hashType)
51{
52 wc_Sha sha;
53#ifndef NO_MD5
54 wc_Md5 md5;
55#endif
56 int hLen = (int)WC_SHA_DIGEST_SIZE;
57 int i, ret = 0;
58 byte buffer[WC_SHA_DIGEST_SIZE]; /* max size */
59
60 if (hashType != WC_MD5 && hashType != WC_SHA)
61 return BAD_FUNC_ARG;
62
63#ifndef NO_MD5
64 if (hashType == WC_MD5)
65 hLen = (int)WC_MD5_DIGEST_SIZE;
66#endif
67
68 if ((kLen > hLen) || (kLen < 0))
69 return BAD_FUNC_ARG;
70
71 if (iterations < 1)
72 return BAD_FUNC_ARG;
73
74 switch (hashType) {
75#ifndef NO_MD5
76 case WC_MD5:
77 ret = wc_InitMd5(&md5);
78 if (ret != 0) {
79 return ret;
80 }
81 ret = wc_Md5Update(&md5, passwd, pLen);
82 if (ret != 0) {
83 return ret;
84 }
85 ret = wc_Md5Update(&md5, salt, sLen);
86 if (ret != 0) {
87 return ret;
88 }
89 ret = wc_Md5Final(&md5, buffer);
90 if (ret != 0) {
91 return ret;
92 }
93 break;
94#endif /* NO_MD5 */
95 case WC_SHA:
96 default:
97 ret = wc_InitSha(&sha);
98 if (ret != 0)
99 return ret;
100 wc_ShaUpdate(&sha, passwd, pLen);
101 wc_ShaUpdate(&sha, salt, sLen);
102 wc_ShaFinal(&sha, buffer);
103 break;
104 }
105
106 for (i = 1; i < iterations; i++) {
107 if (hashType == WC_SHA) {
108 wc_ShaUpdate(&sha, buffer, hLen);
109 wc_ShaFinal(&sha, buffer);
110 }
111#ifndef NO_MD5
112 else {
113 ret = wc_Md5Update(&md5, buffer, hLen);
114 if (ret != 0) {
115 return ret;
116 }
117 ret = wc_Md5Final(&md5, buffer);
118 if (ret != 0) {
119 return ret;
120 }
121 }
122#endif
123 }
124 XMEMCPY(output, buffer, kLen);
125
126 return 0;
127}
128#endif /* NO_SHA */
129
130
131int GetDigestSize(int hashType)
132{
133 int hLen;
134
135 switch (hashType) {
136#ifndef NO_MD5
137 case WC_MD5:
138 hLen = WC_MD5_DIGEST_SIZE;
139 break;
140#endif
141#ifndef NO_SHA
142 case WC_SHA:
143 hLen = WC_SHA_DIGEST_SIZE;
144 break;
145#endif
146#ifndef NO_SHA256
147 case WC_SHA256:
148 hLen = WC_SHA256_DIGEST_SIZE;
149 break;
150#endif
151#ifdef WOLFSSL_SHA512
152 case WC_SHA512:
153 hLen = WC_SHA512_DIGEST_SIZE;
154 break;
155#endif
156 default:
157 return BAD_FUNC_ARG;
158 }
159
160 return hLen;
161}
162
163
164int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
165 int sLen, int iterations, int kLen, int hashType)
166{
167 word32 i = 1;
168 int hLen;
169 int j, ret;
170 Hmac hmac;
171#ifdef WOLFSSL_SMALL_STACK
172 byte* buffer;
173#else
174 byte buffer[MAX_DIGEST_SIZE];
175#endif
176
177 hLen = GetDigestSize(hashType);
178 if (hLen < 0)
179 return BAD_FUNC_ARG;
180
181#ifdef WOLFSSL_SMALL_STACK
182 buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
183 if (buffer == NULL)
184 return MEMORY_E;
185#endif
186
187 ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID);
188 if (ret == 0) {
189 ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen);
190
191 while (ret == 0 && kLen) {
192 int currentLen;
193
194 ret = wc_HmacUpdate(&hmac, salt, sLen);
195 if (ret != 0)
196 break;
197
198 /* encode i */
199 for (j = 0; j < 4; j++) {
200 byte b = (byte)(i >> ((3-j) * 8));
201
202 ret = wc_HmacUpdate(&hmac, &b, 1);
203 if (ret != 0)
204 break;
205 }
206
207 /* check ret from inside for loop */
208 if (ret != 0)
209 break;
210
211 ret = wc_HmacFinal(&hmac, buffer);
212 if (ret != 0)
213 break;
214
215 currentLen = min(kLen, hLen);
216 XMEMCPY(output, buffer, currentLen);
217
218 for (j = 1; j < iterations; j++) {
219 ret = wc_HmacUpdate(&hmac, buffer, hLen);
220 if (ret != 0)
221 break;
222 ret = wc_HmacFinal(&hmac, buffer);
223 if (ret != 0)
224 break;
225 xorbuf(output, buffer, currentLen);
226 }
227
228 /* check ret from inside for loop */
229 if (ret != 0)
230 break;
231
232 output += currentLen;
233 kLen -= currentLen;
234 i++;
235 }
236 wc_HmacFree(&hmac);
237 }
238
239#ifdef WOLFSSL_SMALL_STACK
240 XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER);
241#endif
242
243 return ret;
244}
245
246#ifdef WOLFSSL_SHA512
247 #define PBKDF_DIGEST_SIZE WC_SHA512_BLOCK_SIZE
248#elif !defined(NO_SHA256)
249 #define PBKDF_DIGEST_SIZE WC_SHA256_BLOCK_SIZE
250#else
251 #define PBKDF_DIGEST_SIZE WC_SHA_DIGEST_SIZE
252#endif
253
254/* helper for wc_PKCS12_PBKDF(), sets block and digest sizes */
255int GetPKCS12HashSizes(int hashType, word32* v, word32* u)
256{
257 if (!v || !u)
258 return BAD_FUNC_ARG;
259
260 switch (hashType) {
261#ifndef NO_MD5
262 case WC_MD5:
263 *v = WC_MD5_BLOCK_SIZE;
264 *u = WC_MD5_DIGEST_SIZE;
265 break;
266#endif
267#ifndef NO_SHA
268 case WC_SHA:
269 *v = WC_SHA_BLOCK_SIZE;
270 *u = WC_SHA_DIGEST_SIZE;
271 break;
272#endif
273#ifndef NO_SHA256
274 case WC_SHA256:
275 *v = WC_SHA256_BLOCK_SIZE;
276 *u = WC_SHA256_DIGEST_SIZE;
277 break;
278#endif
279#ifdef WOLFSSL_SHA512
280 case WC_SHA512:
281 *v = WC_SHA512_BLOCK_SIZE;
282 *u = WC_SHA512_DIGEST_SIZE;
283 break;
284#endif
285 default:
286 return BAD_FUNC_ARG;
287 }
288
289 return 0;
290}
291
292/* helper for PKCS12_PBKDF(), does hash operation */
293int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen,
294 byte* Ai, word32 u, int iterations)
295{
296 int i;
297 int ret = 0;
298
299 if (buffer == NULL || Ai == NULL)
300 return BAD_FUNC_ARG;
301
302 switch (hashType) {
303#ifndef NO_MD5
304 case WC_MD5:
305 {
306 wc_Md5 md5;
307 ret = wc_InitMd5(&md5);
308 if (ret != 0) {
309 break;
310 }
311 ret = wc_Md5Update(&md5, buffer, totalLen);
312 if (ret != 0) {
313 break;
314 }
315 ret = wc_Md5Final(&md5, Ai);
316 if (ret != 0) {
317 break;
318 }
319
320 for (i = 1; i < iterations; i++) {
321 ret = wc_Md5Update(&md5, Ai, u);
322 if (ret != 0) {
323 break;
324 }
325 ret = wc_Md5Final(&md5, Ai);
326 if (ret != 0) {
327 break;
328 }
329 }
330 }
331 break;
332#endif /* NO_MD5 */
333#ifndef NO_SHA
334 case WC_SHA:
335 {
336 wc_Sha sha;
337 ret = wc_InitSha(&sha);
338 if (ret != 0)
339 break;
340 ret = wc_ShaUpdate(&sha, buffer, totalLen);
341 if (ret != 0) {
342 break;
343 }
344 ret = wc_ShaFinal(&sha, Ai);
345 if (ret != 0) {
346 break;
347 }
348
349 for (i = 1; i < iterations; i++) {
350 ret = wc_ShaUpdate(&sha, Ai, u);
351 if (ret != 0) {
352 break;
353 }
354 ret = wc_ShaFinal(&sha, Ai);
355 if (ret != 0) {
356 break;
357 }
358 }
359 }
360 break;
361#endif /* NO_SHA */
362#ifndef NO_SHA256
363 case WC_SHA256:
364 {
365 wc_Sha256 sha256;
366 ret = wc_InitSha256(&sha256);
367 if (ret != 0)
368 break;
369
370 ret = wc_Sha256Update(&sha256, buffer, totalLen);
371 if (ret != 0)
372 break;
373
374 ret = wc_Sha256Final(&sha256, Ai);
375 if (ret != 0)
376 break;
377
378 for (i = 1; i < iterations; i++) {
379 ret = wc_Sha256Update(&sha256, Ai, u);
380 if (ret != 0)
381 break;
382
383 ret = wc_Sha256Final(&sha256, Ai);
384 if (ret != 0)
385 break;
386 }
387 }
388 break;
389#endif /* NO_SHA256 */
390#ifdef WOLFSSL_SHA512
391 case WC_SHA512:
392 {
393 wc_Sha512 sha512;
394 ret = wc_InitSha512(&sha512);
395 if (ret != 0)
396 break;
397
398 ret = wc_Sha512Update(&sha512, buffer, totalLen);
399 if (ret != 0)
400 break;
401
402 ret = wc_Sha512Final(&sha512, Ai);
403 if (ret != 0)
404 break;
405
406 for (i = 1; i < iterations; i++) {
407 ret = wc_Sha512Update(&sha512, Ai, u);
408 if (ret != 0)
409 break;
410
411 ret = wc_Sha512Final(&sha512, Ai);
412 if (ret != 0)
413 break;
414 }
415 }
416 break;
417#endif /* WOLFSSL_SHA512 */
418
419 default:
420 ret = BAD_FUNC_ARG;
421 break;
422 }
423
424 return ret;
425}
426
427
428int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt,
429 int saltLen, int iterations, int kLen, int hashType, int id)
430{
431 return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
432 iterations, kLen, hashType, id, NULL);
433}
434
435
436/* extended API that allows a heap hint to be used */
437int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
438 const byte* salt, int saltLen, int iterations, int kLen,
439 int hashType, int id, void* heap)
440{
441 /* all in bytes instead of bits */
442 word32 u, v, dLen, pLen, iLen, sLen, totalLen;
443 int dynamic = 0;
444 int ret = 0;
445 int i;
446 byte *D, *S, *P, *I;
447#ifdef WOLFSSL_SMALL_STACK
448 byte staticBuffer[1]; /* force dynamic usage */
449#else
450 byte staticBuffer[1024];
451#endif
452 byte* buffer = staticBuffer;
453
454#ifdef WOLFSSL_SMALL_STACK
455 byte* Ai;
456 byte* B;
457#else
458 byte Ai[PBKDF_DIGEST_SIZE];
459 byte B[PBKDF_DIGEST_SIZE];
460#endif
461
462 if (!iterations)
463 iterations = 1;
464
465 ret = GetPKCS12HashSizes(hashType, &v, &u);
466 if (ret < 0)
467 return BAD_FUNC_ARG;
468
469#ifdef WOLFSSL_SMALL_STACK
470 Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
471 if (Ai == NULL)
472 return MEMORY_E;
473
474 B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
475 if (B == NULL) {
476 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
477 return MEMORY_E;
478 }
479#endif
480
481 XMEMSET(Ai, 0, PBKDF_DIGEST_SIZE);
482 XMEMSET(B, 0, PBKDF_DIGEST_SIZE);
483
484 dLen = v;
485 sLen = v * ((saltLen + v - 1) / v);
486 if (passLen)
487 pLen = v * ((passLen + v - 1) / v);
488 else
489 pLen = 0;
490 iLen = sLen + pLen;
491
492 totalLen = dLen + sLen + pLen;
493
494 if (totalLen > sizeof(staticBuffer)) {
495 buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
496 if (buffer == NULL) {
497#ifdef WOLFSSL_SMALL_STACK
498 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
499 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
500#endif
501 return MEMORY_E;
502 }
503 dynamic = 1;
504 }
505
506 D = buffer;
507 S = D + dLen;
508 P = S + sLen;
509 I = S;
510
511 XMEMSET(D, id, dLen);
512
513 for (i = 0; i < (int)sLen; i++)
514 S[i] = salt[i % saltLen];
515 for (i = 0; i < (int)pLen; i++)
516 P[i] = passwd[i % passLen];
517
518 while (kLen > 0) {
519 word32 currentLen;
520 mp_int B1;
521
522 ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations);
523 if (ret < 0)
524 break;
525
526 for (i = 0; i < (int)v; i++)
527 B[i] = Ai[i % u];
528
529 if (mp_init(&B1) != MP_OKAY)
530 ret = MP_INIT_E;
531 else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY)
532 ret = MP_READ_E;
533 else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY)
534 ret = MP_ADD_E;
535
536 if (ret != 0) {
537 mp_clear(&B1);
538 break;
539 }
540
541 for (i = 0; i < (int)iLen; i += v) {
542 int outSz;
543 mp_int i1;
544 mp_int res;
545
546 if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) {
547 ret = MP_INIT_E;
548 break;
549 }
550 if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY)
551 ret = MP_READ_E;
552 else if (mp_add(&i1, &B1, &res) != MP_OKAY)
553 ret = MP_ADD_E;
554 else if ( (outSz = mp_unsigned_bin_size(&res)) < 0)
555 ret = MP_TO_E;
556 else {
557 if (outSz > (int)v) {
558 /* take off MSB */
559 byte tmp[129];
560 ret = mp_to_unsigned_bin(&res, tmp);
561 XMEMCPY(I + i, tmp + 1, v);
562 }
563 else if (outSz < (int)v) {
564 XMEMSET(I + i, 0, v - outSz);
565 ret = mp_to_unsigned_bin(&res, I + i + v - outSz);
566 }
567 else
568 ret = mp_to_unsigned_bin(&res, I + i);
569 }
570
571 mp_clear(&i1);
572 mp_clear(&res);
573 if (ret < 0) break;
574 }
575
576 currentLen = min(kLen, (int)u);
577 XMEMCPY(output, Ai, currentLen);
578 output += currentLen;
579 kLen -= currentLen;
580 mp_clear(&B1);
581 }
582
583 if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
584
585#ifdef WOLFSSL_SMALL_STACK
586 XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER);
587 XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER);
588#endif
589
590 return ret;
591}
592
593#ifdef HAVE_SCRYPT
594/* Rotate the 32-bit value a by b bits to the left.
595 *
596 * a 32-bit value.
597 * b Number of bits to rotate.
598 * returns rotated value.
599 */
600#define R(a, b) rotlFixed(a, b)
601
602/* One round of Salsa20/8.
603 * Code taken from RFC 7914: scrypt PBKDF.
604 *
605 * out Output buffer.
606 * in Input data to hash.
607 */
608static void scryptSalsa(word32* out, word32* in)
609{
610 int i;
611 word32 x[16];
612
613#ifdef LITTLE_ENDIAN_ORDER
614 for (i = 0; i < 16; ++i)
615 x[i] = in[i];
616#else
617 for (i = 0; i < 16; i++)
618 x[i] = ByteReverseWord32(in[i]);
619#endif
620 for (i = 8; i > 0; i -= 2) {
621 x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9);
622 x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18);
623 x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9);
624 x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18);
625 x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9);
626 x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18);
627 x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9);
628 x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18);
629 x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9);
630 x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18);
631 x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9);
632 x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18);
633 x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9);
634 x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18);
635 x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9);
636 x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18);
637 }
638#ifdef LITTLE_ENDIAN_ORDER
639 for (i = 0; i < 16; ++i)
640 out[i] = in[i] + x[i];
641#else
642 for (i = 0; i < 16; i++)
643 out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
644#endif
645}
646
647/* Mix a block using Salsa20/8.
648 * Based on RFC 7914: scrypt PBKDF.
649 *
650 * b Blocks to mix.
651 * y Temporary storage.
652 * r Size of the block.
653 */
654static void scryptBlockMix(byte* b, byte* y, int r)
655{
656 byte x[64];
657#ifdef WORD64_AVAILABLE
658 word64* b64 = (word64*)b;
659 word64* y64 = (word64*)y;
660 word64* x64 = (word64*)x;
661#else
662 word32* b32 = (word32*)b;
663 word32* y32 = (word32*)y;
664 word32* x32 = (word32*)x;
665#endif
666 int i;
667 int j;
668
669 /* Step 1. */
670 XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
671 /* Step 2. */
672 for (i = 0; i < 2 * r; i++)
673 {
674#ifdef WORD64_AVAILABLE
675 for (j = 0; j < 8; j++)
676 x64[j] ^= b64[i * 8 + j];
677#else
678 for (j = 0; j < 16; j++)
679 x32[j] ^= b32[i * 16 + j];
680#endif
681 scryptSalsa((word32*)x, (word32*)x);
682 XMEMCPY(y + i * 64, x, sizeof(x));
683 }
684 /* Step 3. */
685 for (i = 0; i < r; i++) {
686#ifdef WORD64_AVAILABLE
687 for (j = 0; j < 8; j++) {
688 b64[i * 8 + j] = y64[2 * i * 8 + j];
689 b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
690 }
691#else
692 for (j = 0; j < 16; j++) {
693 b32[i * 16 + j] = y32[2 * i * 16 + j];
694 b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
695 }
696#endif
697 }
698}
699
700/* Random oracles mix.
701 * Based on RFC 7914: scrypt PBKDF.
702 *
703 * x Data to mix.
704 * v Temporary buffer.
705 * y Temporary buffer for the block mix.
706 * r Block size parameter.
707 * n CPU/Memory cost parameter.
708 */
709static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
710{
711 word32 i;
712 word32 j;
713 word32 k;
714 word32 bSz = 128 * r;
715#ifdef WORD64_AVAILABLE
716 word64* x64 = (word64*)x;
717 word64* v64 = (word64*)v;
718#else
719 word32* x32 = (word32*)x;
720 word32* v32 = (word32*)v;
721#endif
722
723 /* Step 1. X = B (B not needed therefore not implemented) */
724 /* Step 2. */
725 for (i = 0; i < n; i++)
726 {
727 XMEMCPY(v + i * bSz, x, bSz);
728 scryptBlockMix(x, y, r);
729 }
730
731 /* Step 3. */
732 for (i = 0; i < n; i++)
733 {
734#ifdef LITTLE_ENDIAN_ORDER
735#ifdef WORD64_AVAILABLE
736 j = *(word64*)(x + (2*r - 1) * 64) & (n-1);
737#else
738 j = *(word32*)(x + (2*r - 1) * 64) & (n-1);
739#endif
740#else
741 byte* t = x + (2*r - 1) * 64;
742 j = (t[0] | (t[1] << 8) | (t[2] << 16) | (t[3] << 24)) & (n-1);
743#endif
744#ifdef WORD64_AVAILABLE
745 for (k = 0; k < bSz / 8; k++)
746 x64[k] ^= v64[j * bSz / 8 + k];
747#else
748 for (k = 0; k < bSz / 4; k++)
749 x32[k] ^= v32[j * bSz / 4 + k];
750#endif
751 scryptBlockMix(x, y, r);
752 }
753 /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
754}
755
756/* Generates an key derived from a password and salt using a memory hard
757 * algorithm.
758 * Implements RFC 7914: scrypt PBKDF.
759 *
760 * output The derived key.
761 * passwd The password to derive key from.
762 * passLen The length of the password.
763 * salt The key specific data.
764 * saltLen The length of the salt data.
765 * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1)
766 * (Iterations = 2^cost)
767 * blockSize The number of 128 byte octets in a working block.
768 * parallel The number of parallel mix operations to perform.
769 * (Note: this implementation does not use threads.)
770 * dkLen The length of the derived key in bytes.
771 * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost.
772 */
773int wc_scrypt(byte* output, const byte* passwd, int passLen,
774 const byte* salt, int saltLen, int cost, int blockSize,
775 int parallel, int dkLen)
776{
777 int ret = 0;
778 int i;
779 byte* v = NULL;
780 byte* y = NULL;
781 byte* blocks = NULL;
782 word32 blocksSz;
783 word32 bSz;
784
785 if (blockSize > 8)
786 return BAD_FUNC_ARG;
787
788 if (cost < 1 || cost >= 128 * blockSize / 8)
789 return BAD_FUNC_ARG;
790
791 bSz = 128 * blockSize;
792 blocksSz = bSz * parallel;
793 blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
794 if (blocks == NULL)
795 goto end;
796 /* Temporary for scryptROMix. */
797 v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
798 if (v == NULL)
799 goto end;
800 /* Temporary for scryptBlockMix. */
801 y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
802 if (y == NULL)
803 goto end;
804
805 /* Step 1. */
806 ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz,
807 WC_SHA256);
808 if (ret != 0)
809 goto end;
810
811 /* Step 2. */
812 for (i = 0; i < parallel; i++)
813 scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost);
814
815 /* Step 3. */
816 ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen,
817 WC_SHA256);
818end:
819 if (blocks != NULL)
820 XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
821 if (v != NULL)
822 XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
823 if (y != NULL)
824 XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
825
826 return ret;
827}
828#endif
829
830#undef PBKDF_DIGEST_SIZE
831
832#endif /* NO_PWDBASED */
833
Note: See TracBrowser for help on using the repository browser.