source: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/pwdbased.c@ 464

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

WolfSSLとAzure IoT SDKを更新

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