Coverage Report

Created: 2026-09-04 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/wolfcrypt/src/pwdbased.c
Line
Count
Source
1
/* pwdbased.c
2
 *
3
 * Copyright (C) 2006-2026 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 3 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
#define WC_FIPS_LL_CRYPTO
23
#define _WC_BUILDING_PWDBASED_C
24
25
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
26
27
#ifndef NO_PWDBASED
28
29
#if FIPS_VERSION3_GE(6,0,0)
30
       #ifdef USE_WINDOWS_API
31
               #pragma code_seg(".fipsA$h")
32
               #pragma const_seg(".fipsB$h")
33
       #endif
34
#endif
35
36
#include <wolfssl/wolfcrypt/pwdbased.h>
37
#include <wolfssl/wolfcrypt/hmac.h>
38
#include <wolfssl/wolfcrypt/hash.h>
39
#include <wolfssl/wolfcrypt/wolfmath.h>
40
41
#ifdef NO_INLINE
42
    #include <wolfssl/wolfcrypt/misc.h>
43
#else
44
    #define WOLFSSL_MISC_INCLUDED
45
    #include <wolfcrypt/src/misc.c>
46
#endif
47
48
#if FIPS_VERSION3_GE(6,0,0)
49
    const unsigned int wolfCrypt_FIPS_pbkdf_ro_sanity[2] =
50
                                                     { 0x1a2b3c4d, 0x00000010 };
51
    int wolfCrypt_FIPS_PBKDF_sanity(void)
52
    {
53
        return 0;
54
    }
55
#endif
56
57
static int current_wc_pbkdf_max_iterations = WC_PBKDF_DEFAULT_MAX_ITERATIONS;
58
59
int wc_PBKDF_max_iterations_set(int iters)
60
0
{
61
0
    if (iters <= 0)
62
0
        return BAD_FUNC_ARG;
63
0
    else {
64
0
        int prev = current_wc_pbkdf_max_iterations;
65
0
        current_wc_pbkdf_max_iterations = iters;
66
0
        return prev;
67
0
    }
68
0
}
69
70
int wc_PBKDF_max_iterations_get(void)
71
0
{
72
0
    return current_wc_pbkdf_max_iterations;
73
0
}
74
75
#ifdef HAVE_PBKDF1
76
77
/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */
78
int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen,
79
    const byte* passwd, int passwdLen, const byte* salt, int saltLen,
80
    int iterations, int hashType, void* heap)
81
0
{
82
0
    int  err;
83
0
    int  keyLeft, ivLeft, i;
84
0
    int  store;
85
0
    int  keyOutput = 0;
86
0
    int  digestLen;
87
0
    byte digest[WC_MAX_DIGEST_SIZE];
88
0
    WC_DECLARE_VAR(hash, wc_HashAlg, 1, 0);
89
0
    enum wc_HashType hashT;
90
91
0
    (void)heap;
92
93
0
    if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){
94
0
        return BAD_FUNC_ARG;
95
0
    }
96
97
0
    if (keyLen > INT_MAX - ivLen)
98
0
        return BAD_FUNC_ARG;
99
100
0
    if (iterations <= 0)
101
0
        return BAD_FUNC_ARG;
102
103
0
    if (iterations > current_wc_pbkdf_max_iterations) {
104
0
        WOLFSSL_MSG("PBKDF1 iteration count exceeds current_wc_pbkdf_max_iterations");
105
0
        return BAD_FUNC_ARG;
106
0
    }
107
108
0
    hashT = wc_HashTypeConvert(hashType);
109
0
    err = wc_HashGetDigestSize(hashT);
110
0
    if (err < 0)
111
0
        return err;
112
0
    digestLen = err;
113
114
    /* initialize hash */
115
0
    WC_ALLOC_VAR_EX(hash, wc_HashAlg, 1, heap, DYNAMIC_TYPE_HASHCTX,
116
0
        return MEMORY_E);
117
118
0
    err = wc_HashInit_ex(hash, hashT, heap, INVALID_DEVID);
119
0
    if (err != 0) {
120
0
        WC_FREE_VAR_EX(hash, heap, DYNAMIC_TYPE_HASHCTX);
121
0
        return err;
122
0
    }
123
124
#ifdef WOLFSSL_CHECK_MEM_ZERO
125
    /* poison so a missed ForceZero on any path is caught by the check */
126
    XMEMSET(digest, 0xff, sizeof(digest));
127
    wc_MemZero_Add("wc_PBKDF1_ex digest", digest, sizeof(digest));
128
#endif
129
130
0
    keyLeft = keyLen;
131
0
    ivLeft  = ivLen;
132
0
    while (keyOutput < (keyLen + ivLen)) {
133
0
        int digestLeft = digestLen;
134
        /* D_(i - 1) */
135
0
        if (keyOutput) { /* first time D_0 is empty */
136
0
            err = wc_HashUpdate(hash, hashT, digest, (word32)digestLen);
137
0
            if (err != 0) break;
138
0
        }
139
140
        /* data */
141
0
        err = wc_HashUpdate(hash, hashT, passwd, (word32)passwdLen);
142
0
        if (err != 0) break;
143
144
        /* salt */
145
0
        if (salt) {
146
0
            err = wc_HashUpdate(hash, hashT, salt, (word32)saltLen);
147
0
            if (err != 0) break;
148
0
        }
149
150
0
        err = wc_HashFinal(hash, hashT, digest);
151
0
        if (err != 0) break;
152
153
        /* count */
154
0
        for (i = 1; i < iterations; i++) {
155
0
            err = wc_HashUpdate(hash, hashT, digest, (word32)digestLen);
156
0
            if (err != 0) break;
157
158
0
            err = wc_HashFinal(hash, hashT, digest);
159
0
            if (err != 0) break;
160
0
        }
161
162
0
        if (err != 0) break;
163
164
0
        if (keyLeft) {
165
0
            store = (int)min((word32)keyLeft, (word32)digestLen);
166
0
            XMEMCPY(&key[keyLen - keyLeft], digest, (size_t)store);
167
168
0
            keyOutput  += store;
169
0
            keyLeft    -= store;
170
0
            digestLeft -= store;
171
0
        }
172
173
0
        if (ivLeft && digestLeft) {
174
0
            store = (int)min((word32)ivLeft, (word32)digestLeft);
175
0
            if (iv != NULL)
176
0
                XMEMCPY(&iv[ivLen - ivLeft],
177
0
                        &digest[digestLen - digestLeft], (size_t)store);
178
0
            keyOutput += store;
179
0
            ivLeft    -= store;
180
0
        }
181
0
    }
182
183
0
    wc_HashFree(hash, hashT);
184
185
0
    WC_FREE_VAR_EX(hash, heap, DYNAMIC_TYPE_HASHCTX);
186
187
0
    ForceZero(digest, sizeof(digest));
188
#ifdef WOLFSSL_CHECK_MEM_ZERO
189
    wc_MemZero_Check(digest, sizeof(digest));
190
#endif
191
192
0
    if (err != 0)
193
0
        return err;
194
195
0
    if (keyOutput != (keyLen + ivLen))
196
0
        return BUFFER_E;
197
198
0
    return err;
199
0
}
200
201
/* PKCS#5 v1.5 */
202
int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt,
203
           int sLen, int iterations, int kLen, int hashType)
204
0
{
205
206
0
    return wc_PBKDF1_ex(output, kLen, NULL, 0,
207
0
        passwd, pLen, salt, sLen, iterations, hashType, NULL);
208
0
}
209
210
#endif /* HAVE_PKCS5 */
211
212
#if defined(HAVE_PBKDF2) && !defined(NO_HMAC)
213
214
int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt,
215
           int sLen, int iterations, int kLen, int hashType, void* heap, int devId)
216
0
{
217
0
    int    hLen;
218
0
    int    ret;
219
#ifdef WOLFSSL_SMALL_STACK
220
    byte*  buffer;
221
    Hmac*  hmac;
222
#else
223
0
    byte   buffer[WC_MAX_DIGEST_SIZE];
224
0
    Hmac   hmac[1];
225
0
#endif
226
0
    enum wc_HashType hashT;
227
228
0
    if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) {
229
0
        return BAD_FUNC_ARG;
230
0
    }
231
232
#if FIPS_VERSION3_GE(6,0,0)
233
    /* Per SP800-132 section 5 "The kLen value shall be at least 112 bits in
234
     * length", ensure the returned bits for the derived master key are at a
235
     * minimum 14-bytes or 112-bits after stretching and strengthening
236
     * (iterations) */
237
    if (kLen < HMAC_FIPS_MIN_KEY)
238
        return BAD_LENGTH_E;
239
#endif
240
241
#if FIPS_VERSION3_GE(6,0,0) && defined(DEBUG_WOLFSSL)
242
    /* SP800-132 section 5.2 recommends an iteration count of 1000 but this is
243
     * not strictly enforceable and is listed in Appendix B Table 1 as a
244
     * non-testable requirement. wolfCrypt will log it when appropriate but
245
     * take no action */
246
    if (iterations < 1000) {
247
        WOLFSSL_MSG("WARNING: Iteration < 1,000, see SP800-132 section 5.2");
248
    }
249
#endif
250
0
    if (iterations <= 0)
251
0
        return BAD_FUNC_ARG;
252
253
0
    if (iterations > current_wc_pbkdf_max_iterations) {
254
0
        WOLFSSL_MSG("PBKDF2 iteration count exceeds current_wc_pbkdf_max_iterations");
255
0
        return BAD_FUNC_ARG;
256
0
    }
257
258
0
    hashT = wc_HashTypeConvert(hashType);
259
0
    hLen = wc_HashGetDigestSize(hashT);
260
0
    if (hLen < 0)
261
0
        return BAD_FUNC_ARG;
262
263
#ifdef WOLFSSL_SMALL_STACK
264
    buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
265
    if (buffer == NULL)
266
        return MEMORY_E;
267
    hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC);
268
    if (hmac == NULL) {
269
        XFREE(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
270
        return MEMORY_E;
271
    }
272
#endif
273
274
#ifdef WOLFSSL_CHECK_MEM_ZERO
275
    /* poison so a missed ForceZero on any path is caught by the check */
276
    XMEMSET(buffer, 0xff, (word32)hLen);
277
    wc_MemZero_Add("wc_PBKDF2_ex buffer", buffer, (word32)hLen);
278
#endif
279
280
0
    ret = wc_HmacInit(hmac, heap, devId);
281
0
    if (ret == 0) {
282
0
        word32 i = 1;
283
        /* use int hashType here, since HMAC FIPS uses the old unique value */
284
    #if FIPS_VERSION3_GE(6,0,0)
285
        {
286
            /* Allow passwords that are less than 14-bytes for compatibility
287
             * / interoperability, only since module v6.0.0 */
288
            int allowShortPasswd = 1;
289
            ret = wc_HmacSetKey_ex(hmac, hashType, passwd, (word32)pLen,
290
                                   allowShortPasswd);
291
        }
292
    #else
293
0
        ret = wc_HmacSetKey(hmac, hashType, passwd, (word32)pLen);
294
0
    #endif
295
296
0
        while (ret == 0 && kLen) {
297
0
            int currentLen;
298
0
            int j;
299
300
0
            ret = wc_HmacUpdate(hmac, salt, (word32)sLen);
301
0
            if (ret != 0)
302
0
                break;
303
304
            /* encode i */
305
0
            for (j = 0; j < 4; j++) {
306
0
                byte b = (byte)(i >> ((3-j) * 8));
307
308
0
                ret = wc_HmacUpdate(hmac, &b, 1);
309
0
                if (ret != 0)
310
0
                    break;
311
0
            }
312
313
            /* check ret from inside for loop */
314
0
            if (ret != 0)
315
0
                break;
316
317
0
            ret = wc_HmacFinal(hmac, buffer);
318
0
            if (ret != 0)
319
0
                break;
320
321
0
            currentLen = (int)min((word32)kLen, (word32)hLen);
322
0
            XMEMCPY(output, buffer, (size_t)currentLen);
323
324
0
            for (j = 1; j < iterations; j++) {
325
0
                ret = wc_HmacUpdate(hmac, buffer, (word32)hLen);
326
0
                if (ret != 0)
327
0
                    break;
328
0
                ret = wc_HmacFinal(hmac, buffer);
329
0
                if (ret != 0)
330
0
                    break;
331
0
                xorbuf(output, buffer, (word32)currentLen);
332
0
            }
333
334
            /* check ret from inside for loop */
335
0
            if (ret != 0)
336
0
                break;
337
338
0
            output += currentLen;
339
0
            kLen   -= currentLen;
340
0
            i++;
341
0
        }
342
0
        wc_HmacFree(hmac);
343
0
    }
344
345
0
    ForceZero(buffer, (word32)hLen);
346
#if !defined(WOLFSSL_SMALL_STACK) && defined(WOLFSSL_CHECK_MEM_ZERO)
347
    wc_MemZero_Check(buffer, (word32)hLen);
348
#endif
349
0
    WC_FREE_VAR_EX(buffer, heap, DYNAMIC_TYPE_TMP_BUFFER);
350
0
    WC_FREE_VAR_EX(hmac, heap, DYNAMIC_TYPE_HMAC);
351
352
0
    return ret;
353
0
}
354
355
int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt,
356
           int sLen, int iterations, int kLen, int hashType)
357
0
{
358
0
    return wc_PBKDF2_ex(output, passwd, pLen, salt, sLen, iterations, kLen,
359
0
        hashType, NULL, INVALID_DEVID);
360
0
}
361
362
#endif /* HAVE_PBKDF2 && !NO_HMAC */
363
364
#ifdef HAVE_PKCS12
365
366
/* helper for PKCS12_PBKDF(), does hash operation.
367
 * buffer and Ai are guaranteed non-NULL by the caller: each is either a stack
368
 * array or an XMALLOC result whose failure returns MEMORY_E before the call. */
369
static int DoPKCS12Hash(enum wc_HashType hashT, byte* buffer, word32 totalLen,
370
    byte* Ai, word32 u, int iterations)
371
0
{
372
0
    int i;
373
0
    int ret = 0;
374
0
    WC_DECLARE_VAR(hash, wc_HashAlg, 1, 0);
375
376
    /* initialize hash */
377
0
    WC_ALLOC_VAR_EX(hash, wc_HashAlg, 1, NULL, DYNAMIC_TYPE_HASHCTX,
378
0
        return MEMORY_E);
379
380
0
    ret = wc_HashInit(hash, hashT);
381
0
    if (ret == 0) {
382
0
        ret = wc_HashUpdate(hash, hashT, buffer, totalLen);
383
0
        if (ret == 0)
384
0
            ret = wc_HashFinal(hash, hashT, Ai);
385
386
0
        for (i = 1; i < iterations; i++) {
387
0
            if (ret == 0)
388
0
                ret = wc_HashUpdate(hash, hashT, Ai, u);
389
0
            if (ret == 0)
390
0
                ret = wc_HashFinal(hash, hashT, Ai);
391
0
        }
392
393
0
        wc_HashFree(hash, hashT);
394
0
    }
395
396
0
    WC_FREE_VAR_EX(hash, NULL, DYNAMIC_TYPE_HASHCTX);
397
0
    return ret;
398
0
}
399
400
401
int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,
402
    const byte* salt, int saltLen, int iterations, int kLen, int hashType,
403
    int id)
404
0
{
405
0
    return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen,
406
0
                              iterations, kLen, hashType, id, NULL);
407
0
}
408
409
410
#ifdef WC_PKCS12_PBKDF_USING_MP_API
411
/* extended API that allows a heap hint to be used */
412
int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
413
                       const byte* salt, int saltLen, int iterations, int kLen,
414
                       int hashType, int id, void* heap)
415
{
416
    /* all in bytes instead of bits */
417
    word32 u, v, dLen, pLen, iLen, sLen, totalLen;
418
    int    dynamic = 0;
419
    int    ret = 0;
420
    word32 i;
421
    byte   *D, *S, *P, *I;
422
#ifdef WOLFSSL_SMALL_STACK
423
    byte   staticBuffer[1]; /* force dynamic usage */
424
#else
425
    byte   staticBuffer[1024];
426
#endif
427
    byte*  buffer = staticBuffer;
428
429
#ifdef WOLFSSL_SMALL_STACK
430
    byte*  Ai = NULL;
431
    byte*  B = NULL;
432
    mp_int *B1 = NULL;
433
    mp_int *i1 = NULL;
434
    mp_int *res = NULL;
435
#else
436
    byte   Ai[WC_MAX_DIGEST_SIZE];
437
    byte   B[WC_MAX_BLOCK_SIZE];
438
    mp_int B1[1];
439
    mp_int i1[1];
440
    mp_int res[1];
441
#endif
442
    enum wc_HashType hashT;
443
444
    (void)heap;
445
446
    if (output == NULL || passLen <= 0 || saltLen <= 0 || kLen < 0) {
447
        return BAD_FUNC_ARG;
448
    }
449
450
    if (iterations <= 0)
451
        return BAD_FUNC_ARG;
452
453
    if (iterations > current_wc_pbkdf_max_iterations) {
454
        WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds "
455
                    "current_wc_pbkdf_max_iterations");
456
        return BAD_FUNC_ARG;
457
    }
458
459
    hashT = wc_HashTypeConvert(hashType);
460
    ret = wc_HashGetDigestSize(hashT);
461
    if (ret < 0)
462
        return ret;
463
    if (ret == 0)
464
        return BAD_STATE_E;
465
    u = (word32)ret;
466
467
    ret = wc_HashGetBlockSize(hashT);
468
    if (ret < 0)
469
        return ret;
470
    if (ret == 0)
471
        return BAD_STATE_E;
472
    v = (word32)ret;
473
    /* the block size must not be mistaken for a result when kLen is 0 and the
474
     * derivation loop below never runs */
475
    ret = 0;
476
477
#ifdef WOLFSSL_SMALL_STACK
478
    Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
479
    if (Ai == NULL)
480
        return MEMORY_E;
481
482
    B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
483
    if (B == NULL) {
484
        XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
485
        return MEMORY_E;
486
    }
487
#endif
488
489
    XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE);
490
    XMEMSET(B,  0, WC_MAX_BLOCK_SIZE);
491
492
    dLen = v;
493
    sLen = v * (((word32)saltLen + v - 1) / v);
494
495
    /* with passLen checked at the top of the function for >= 0 then passLen
496
     * must be 1 or greater here and is always 'true' */
497
    pLen = v * (((word32)passLen + v - 1) / v);
498
499
    if (! WC_SAFE_SUM_UNSIGNED(word32, sLen, pLen, iLen)) {
500
        WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
501
        WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
502
        return BAD_FUNC_ARG;
503
    }
504
505
    /* the working buffer holds D || S || P, so totalLen is dLen + iLen */
506
    if (! WC_SAFE_SUM_UNSIGNED(word32, dLen, iLen, totalLen)) {
507
        WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
508
        WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
509
        return BAD_FUNC_ARG;
510
    }
511
512
    if (totalLen > sizeof(staticBuffer)) {
513
        buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
514
        if (buffer == NULL) {
515
            WC_FREE_VAR_EX(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
516
            WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
517
            return MEMORY_E;
518
        }
519
        dynamic = 1;
520
    }
521
522
    D = buffer;
523
    S = D + dLen;
524
    P = S + sLen;
525
    I = S;
526
527
    XMEMSET(D, id, dLen);
528
529
    for (i = 0; i < sLen; i++)
530
        S[i] = salt[i % (word32)saltLen];
531
    for (i = 0; i < pLen; i++)
532
        P[i] = passwd[i % (word32)passLen];
533
534
#ifdef WOLFSSL_CHECK_MEM_ZERO
535
    wc_MemZero_Add("wc_PKCS12_PBKDF_ex Ai", Ai, WC_MAX_DIGEST_SIZE);
536
    wc_MemZero_Add("wc_PKCS12_PBKDF_ex B", B, WC_MAX_BLOCK_SIZE);
537
    wc_MemZero_Add("wc_PKCS12_PBKDF_ex buffer", buffer, totalLen);
538
#endif
539
540
#ifdef WOLFSSL_SMALL_STACK
541
    if (((B1 = (mp_int *)XMALLOC(sizeof(*B1), heap, DYNAMIC_TYPE_TMP_BUFFER))
542
         == NULL) ||
543
        ((i1 = (mp_int *)XMALLOC(sizeof(*i1), heap, DYNAMIC_TYPE_TMP_BUFFER))
544
         == NULL) ||
545
        ((res = (mp_int *)XMALLOC(sizeof(*res), heap, DYNAMIC_TYPE_TMP_BUFFER))
546
         == NULL)) {
547
        ret = MEMORY_E;
548
        goto out;
549
    }
550
#endif
551
552
    while (kLen > 0) {
553
        word32 currentLen;
554
555
        ret = DoPKCS12Hash(hashT, buffer, totalLen, Ai, u, iterations);
556
        if (ret != 0)
557
            break;
558
559
        for (i = 0; i < v; i++)
560
            B[i] = Ai[(word32)i % u];
561
562
        if (mp_init(B1) != MP_OKAY)
563
            ret = MP_INIT_E;
564
        else if (mp_read_unsigned_bin(B1, B, v) != MP_OKAY)
565
            ret = MP_READ_E;
566
        else if (mp_add_d(B1, (mp_digit)1, B1) != MP_OKAY)
567
            ret = MP_ADD_E;
568
569
        if (ret != 0) {
570
            mp_clear(B1);
571
            break;
572
        }
573
574
        for (i = 0; i < iLen; i += v) {
575
            int    outSz;
576
577
            if (mp_init_multi(i1, res, NULL, NULL, NULL, NULL) != MP_OKAY) {
578
                ret = MP_INIT_E;
579
                break;
580
            }
581
            if (mp_read_unsigned_bin(i1, I + i, v) != MP_OKAY)
582
                ret = MP_READ_E;
583
            else if (mp_add(i1, B1, res) != MP_OKAY)
584
                ret = MP_ADD_E;
585
            else if ( (outSz = mp_unsigned_bin_size(res)) < 0)
586
                ret = MP_TO_E;
587
            else {
588
                if (outSz > (int)v) {
589
                    /* take off MSB */
590
                    byte  tmp[WC_MAX_BLOCK_SIZE + 1];
591
                    ret = mp_to_unsigned_bin(res, tmp);
592
                    XMEMCPY(I + i, tmp + 1, v);
593
                }
594
                else if (outSz < (int)v) {
595
                    XMEMSET(I + i, 0, v - (word32)outSz);
596
                    ret = mp_to_unsigned_bin(res, I + i + v - (word32)outSz);
597
                }
598
                else
599
                    ret = mp_to_unsigned_bin(res, I + i);
600
            }
601
602
            mp_clear(i1);
603
            mp_clear(res);
604
            if (ret < 0) break;
605
        }
606
607
        if (ret < 0) {
608
            mp_clear(B1);
609
            break;
610
        }
611
612
        currentLen = min((word32)kLen, u);
613
        XMEMCPY(output, Ai, currentLen);
614
        output += currentLen;
615
        kLen   -= (int)currentLen;
616
        mp_clear(B1);
617
    }
618
619
#ifdef WOLFSSL_SMALL_STACK
620
  out:
621
622
    ForceZero(Ai, WC_MAX_DIGEST_SIZE);
623
    XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER);
624
    ForceZero(B, WC_MAX_BLOCK_SIZE);
625
    XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
626
    XFREE(B1, heap, DYNAMIC_TYPE_TMP_BUFFER);
627
    XFREE(i1, heap, DYNAMIC_TYPE_TMP_BUFFER);
628
    XFREE(res, heap, DYNAMIC_TYPE_TMP_BUFFER);
629
#else
630
    ForceZero(Ai, WC_MAX_DIGEST_SIZE);
631
    ForceZero(B, WC_MAX_BLOCK_SIZE);
632
#if defined(WOLFSSL_CHECK_MEM_ZERO)
633
    wc_MemZero_Check(Ai, WC_MAX_DIGEST_SIZE);
634
    wc_MemZero_Check(B, WC_MAX_BLOCK_SIZE);
635
#endif
636
#endif
637
638
    ForceZero(buffer, totalLen);
639
#if defined(WOLFSSL_CHECK_MEM_ZERO)
640
    if (!dynamic)
641
        wc_MemZero_Check(buffer, totalLen);
642
#endif
643
    if (dynamic)
644
        XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
645
646
    return ret;
647
}
648
#else
649
650
#if defined(WC_64BIT_CPU) && defined(HAVE___UINT128_T) && \
651
    !defined(NO_INT128)
652
0
    #define PKCS12_DWORD                        word128
653
0
    #define PKCS12_WORD                         word64
654
0
    #define PKCS12_ByteReverseWords             ByteReverseWords64
655
#elif defined(WC_32BIT_CPU) || defined(WC_64BIT_CPU)
656
    #define PKCS12_DWORD                        word64
657
    #define PKCS12_WORD                         word32
658
    #define PKCS12_ByteReverseWords             ByteReverseWords
659
#else
660
    #define PKCS12_DWORD                        word16
661
    #define PKCS12_WORD                         word8
662
    /* No need to byte reverse when handling 1 byte at a time. */
663
    #define PKCS12_ByteReverseWords(r, a, n)    WC_DO_NOTHING
664
#endif
665
666
/* extended API that allows a heap hint to be used */
667
int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen,
668
                       const byte* salt, int saltLen, int iterations, int kLen,
669
                       int hashType, int id, void* heap)
670
0
{
671
0
    word32 u, v, pLen, iLen, sLen, totalLen;
672
    /* nwc:     v / sizeof(PKCS12_WORD) - words per v-byte block
673
     *          (v is always a multiple of sizeof(PKCS12_WORD))
674
     * nBlocks: iLen / v - number of v-byte blocks in I */
675
0
    word32 nwc, nBlocks;
676
0
    int    ret = 0;
677
0
    word32 i, k, blk;
678
0
    byte*        I;
679
0
    PKCS12_WORD* Bw;
680
#ifdef WOLFSSL_SMALL_STACK
681
    byte   staticBuffer[1]; /* force dynamic usage */
682
    byte*  B   = NULL;
683
#else
684
0
    ALIGN8 byte   staticBuffer[1024];
685
0
    ALIGN8 byte   B[WC_MAX_BLOCK_SIZE];
686
0
#endif
687
0
    byte*  buffer = staticBuffer;
688
0
    enum wc_HashType hashT;
689
690
0
    (void)heap;
691
692
0
    if ((output == NULL) || (passLen <= 0) || (saltLen <= 0) || (kLen < 0)) {
693
0
        return BAD_FUNC_ARG;
694
0
    }
695
696
0
    if (iterations <= 0) {
697
0
        return BAD_FUNC_ARG;
698
0
    }
699
700
0
    if (iterations > current_wc_pbkdf_max_iterations) {
701
0
        WOLFSSL_MSG("PKCS12 PBKDF iteration count exceeds "
702
0
                    "current_wc_pbkdf_max_iterations");
703
0
        return BAD_FUNC_ARG;
704
0
    }
705
706
    /* u = hash output size. */
707
0
    hashT = wc_HashTypeConvert(hashType);
708
0
    ret = wc_HashGetDigestSize(hashT);
709
0
    if (ret < 0)
710
0
        return ret;
711
0
    if (ret == 0)
712
0
        return BAD_STATE_E;
713
0
    u = (word32)ret;
714
715
    /* v = hash block size. */
716
0
    ret = wc_HashGetBlockSize(hashT);
717
0
    if (ret < 0)
718
0
        return ret;
719
0
    if (ret == 0)
720
0
        return BAD_STATE_E;
721
0
    v = (word32)ret;
722
723
    /* RFC 7292 B.2 step 2: S = salt repeated to ceil(saltLen/v)*v bytes */
724
0
    sLen = v * (((word32)saltLen + v - 1) / v);
725
    /* RFC 7292 B.2 step 3: P = password repeated to ceil(passLen/v)*v bytes */
726
0
    pLen = v * (((word32)passLen + v - 1) / v);
727
728
    /* RFC 7292 B.2 step 4: I = S || P */
729
0
    if (! WC_SAFE_SUM_UNSIGNED(word32, sLen, pLen, iLen)) {
730
0
        return BAD_FUNC_ARG;
731
0
    }
732
733
0
    if (! WC_SAFE_SUM_UNSIGNED(word32, v, iLen, totalLen)) {
734
0
        return BAD_FUNC_ARG;
735
0
    }
736
737
0
    nwc     = v / (word32)sizeof(PKCS12_WORD);
738
0
    nBlocks = iLen / v;
739
740
#ifdef WOLFSSL_SMALL_STACK
741
    B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER);
742
    if (B == NULL)
743
        return MEMORY_E;
744
#endif
745
0
    Bw = (PKCS12_WORD*)B;
746
747
0
    if (totalLen > sizeof(staticBuffer)) {
748
0
        buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY);
749
0
        if (buffer == NULL) {
750
0
            WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
751
0
            return MEMORY_E;
752
0
        }
753
0
    }
754
755
    /* RFC 7292 B.2 step 1: D = v bytes each set to ID */
756
    /* RFC 7292 B.2 step 4: I = S || P; buffer = D || I */
757
0
    I = buffer + v;
758
0
    XMEMSET(buffer, id, v);
759
0
    for (i = 0; i < sLen; i++)
760
0
        I[i] = salt[i % (word32)saltLen];
761
0
    for (i = 0; i < pLen; i++)
762
0
        I[sLen + i] = passwd[i % (word32)passLen];
763
764
#ifdef WOLFSSL_CHECK_MEM_ZERO
765
    wc_MemZero_Add("wc_PKCS12_PBKDF_ex buffer", buffer, totalLen);
766
#endif
767
768
0
    ret = 0;
769
0
    while ((ret == 0) && (kLen > 0)) {
770
        /* RFC 7292 B.2 step 6a: A_i = H^r(D || I) */
771
0
        ret = DoPKCS12Hash(hashT, buffer, totalLen, B, u, iterations);
772
0
        if (ret != 0)
773
0
            break;
774
775
        /* RFC 7292 B.2 step 7: output A_i bytes (up to kLen) */
776
0
        i = min((word32)kLen, u);
777
0
        XMEMCPY(output, B, i);
778
0
        output += i;
779
0
        kLen -= (int)i;
780
0
        if (kLen == 0)
781
0
            break;
782
783
        /* RFC 7292 B.2 step 6b: B = A_i repeated to length v */
784
0
        for (i = u; i < v; i++)
785
0
            B[i] = B[i % u];
786
787
        /* RFC 7292 B.2 step 6c: I_j = (I_j + B + 1) mod 2^(8v). */
788
0
#ifndef BIG_ENDIAN_ORDER
789
0
        PKCS12_ByteReverseWords(Bw, Bw, v);
790
0
#endif
791
        /* Increment B by 1. */
792
0
        for (k = nwc; k > 0; ) {
793
0
            --k;
794
0
            ++Bw[k];
795
0
            if (Bw[k] != 0)
796
0
                break;
797
0
        }
798
799
0
#ifndef BIG_ENDIAN_ORDER
800
0
        PKCS12_ByteReverseWords((PKCS12_WORD*)I, (PKCS12_WORD*)I, nBlocks * v);
801
0
#endif
802
        /* Add B+1 to each I_j block. */
803
0
        for (blk = 0; blk < nBlocks; blk++) {
804
0
            PKCS12_DWORD c  = 0;
805
0
            PKCS12_WORD* Iw = (PKCS12_WORD*)(I + blk * v);
806
0
            for (k = nwc; k-- > 0; ) {
807
0
                c     += (PKCS12_DWORD)Iw[k];
808
0
                c     += (PKCS12_DWORD)Bw[k];
809
0
                Iw[k]  = (PKCS12_WORD)c;
810
0
                c    >>= 8 * sizeof(PKCS12_WORD);
811
0
            }
812
0
        }
813
0
#ifndef BIG_ENDIAN_ORDER
814
0
        PKCS12_ByteReverseWords((PKCS12_WORD*)I, (PKCS12_WORD*)I, nBlocks * v);
815
0
#endif
816
0
    }
817
818
0
    ForceZero(B, WC_MAX_BLOCK_SIZE);
819
0
    WC_FREE_VAR_EX(B, heap, DYNAMIC_TYPE_TMP_BUFFER);
820
0
    ForceZero(buffer, totalLen);
821
#if defined(WOLFSSL_CHECK_MEM_ZERO)
822
    if (buffer == staticBuffer)
823
        wc_MemZero_Check(buffer, totalLen);
824
#endif
825
0
    if (buffer != staticBuffer) {
826
0
        XFREE(buffer, heap, DYNAMIC_TYPE_KEY);
827
0
    }
828
829
0
    return ret;
830
0
}
831
832
#undef PKCS12_DWORD
833
#undef PKCS12_WORD
834
#undef PKCS12_ByteReverseWords
835
836
#endif
837
838
#endif /* HAVE_PKCS12 */
839
840
#ifdef HAVE_SCRYPT
841
#ifdef NO_HMAC
842
   #error scrypt requires HMAC
843
#endif
844
845
/* Rotate the 32-bit value a by b bits to the left.
846
 *
847
 * a  32-bit value.
848
 * b  Number of bits to rotate.
849
 * returns rotated value.
850
 */
851
#define R(a, b) rotlFixed(a, b)
852
853
/* (2^32 - 1) */
854
#define SCRYPT_WORD32_MAX 4294967295U
855
856
/* One round of Salsa20/8.
857
 * Code taken from RFC 7914: scrypt PBKDF.
858
 *
859
 * out  Output buffer.
860
 * in   Input data to hash.
861
 */
862
static void scryptSalsa(word32* out, word32* in)
863
{
864
    int    i;
865
    word32 x[16];
866
867
#ifdef LITTLE_ENDIAN_ORDER
868
    XMEMCPY(x, in, sizeof(x));
869
#else
870
    for (i = 0; i < 16; i++)
871
        x[i] = ByteReverseWord32(in[i]);
872
#endif
873
    for (i = 8; i > 0; i -= 2) {
874
        x[ 4] ^= R(x[ 0] + x[12],  7);  x[ 8] ^= R(x[ 4] + x[ 0],  9);
875
        x[12] ^= R(x[ 8] + x[ 4], 13);  x[ 0] ^= R(x[12] + x[ 8], 18);
876
        x[ 9] ^= R(x[ 5] + x[ 1],  7);  x[13] ^= R(x[ 9] + x[ 5],  9);
877
        x[ 1] ^= R(x[13] + x[ 9], 13);  x[ 5] ^= R(x[ 1] + x[13], 18);
878
        x[14] ^= R(x[10] + x[ 6],  7);  x[ 2] ^= R(x[14] + x[10],  9);
879
        x[ 6] ^= R(x[ 2] + x[14], 13);  x[10] ^= R(x[ 6] + x[ 2], 18);
880
        x[ 3] ^= R(x[15] + x[11],  7);  x[ 7] ^= R(x[ 3] + x[15],  9);
881
        x[11] ^= R(x[ 7] + x[ 3], 13);  x[15] ^= R(x[11] + x[ 7], 18);
882
        x[ 1] ^= R(x[ 0] + x[ 3],  7);  x[ 2] ^= R(x[ 1] + x[ 0],  9);
883
        x[ 3] ^= R(x[ 2] + x[ 1], 13);  x[ 0] ^= R(x[ 3] + x[ 2], 18);
884
        x[ 6] ^= R(x[ 5] + x[ 4],  7);  x[ 7] ^= R(x[ 6] + x[ 5],  9);
885
        x[ 4] ^= R(x[ 7] + x[ 6], 13);  x[ 5] ^= R(x[ 4] + x[ 7], 18);
886
        x[11] ^= R(x[10] + x[ 9],  7);  x[ 8] ^= R(x[11] + x[10],  9);
887
        x[ 9] ^= R(x[ 8] + x[11], 13);  x[10] ^= R(x[ 9] + x[ 8], 18);
888
        x[12] ^= R(x[15] + x[14],  7);  x[13] ^= R(x[12] + x[15],  9);
889
        x[14] ^= R(x[13] + x[12], 13);  x[15] ^= R(x[14] + x[13], 18);
890
    }
891
#ifdef LITTLE_ENDIAN_ORDER
892
    for (i = 0; i < 16; ++i)
893
        out[i] = in[i] + x[i];
894
#else
895
    for (i = 0; i < 16; i++)
896
        out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]);
897
#endif
898
}
899
900
/* Mix a block using Salsa20/8.
901
 * Based on RFC 7914: scrypt PBKDF.
902
 *
903
 * b  Blocks to mix.
904
 * y  Temporary storage.
905
 * r  Size of the block.
906
 */
907
static void scryptBlockMix(byte* b, byte* y, int r)
908
{
909
#ifdef WORD64_AVAILABLE
910
    word64  x[8];
911
    word64* b64 = (word64*)b;
912
    word64* y64 = (word64*)y;
913
#else
914
    word32  x[16];
915
    word32* b32 = (word32*)b;
916
    word32* y32 = (word32*)y;
917
#endif
918
    int  i;
919
    int  j;
920
921
    /* Step 1. */
922
    XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x));
923
    /* Step 2. */
924
    for (i = 0; i < 2 * r; i++)
925
    {
926
#ifdef WORD64_AVAILABLE
927
        for (j = 0; j < 8; j++)
928
            x[j] ^= b64[i * 8 + j];
929
930
#else
931
        for (j = 0; j < 16; j++)
932
            x[j] ^= b32[i * 16 + j];
933
#endif
934
        scryptSalsa((word32*)x, (word32*)x);
935
        XMEMCPY(y + i * 64, x, sizeof(x));
936
    }
937
    /* Step 3. */
938
    for (i = 0; i < r; i++) {
939
#ifdef WORD64_AVAILABLE
940
        for (j = 0; j < 8; j++) {
941
            b64[i * 8 + j] = y64[2 * i * 8 + j];
942
            b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j];
943
        }
944
#else
945
        for (j = 0; j < 16; j++) {
946
            b32[i * 16 + j] = y32[2 * i * 16 + j];
947
            b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j];
948
        }
949
#endif
950
    }
951
}
952
953
/* Random oracles mix.
954
 * Based on RFC 7914: scrypt PBKDF.
955
 *
956
 * x  Data to mix.
957
 * v  Temporary buffer.
958
 * y  Temporary buffer for the block mix.
959
 * r  Block size parameter.
960
 * n  CPU/Memory cost parameter.
961
 */
962
static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n)
963
{
964
    word32 i;
965
    word32 j;
966
    word32 k;
967
    word32 bSz = (word32)(128 * r);
968
#ifdef WORD64_AVAILABLE
969
    word64* x64 = (word64*)x;
970
    word64* v64 = (word64*)v;
971
#else
972
    word32* x32 = (word32*)x;
973
    word32* v32 = (word32*)v;
974
#endif
975
976
    /* Step 1. X = B (B not needed therefore not implemented) */
977
    /* Step 2. */
978
    for (i = 0; i < n; i++)
979
    {
980
        XMEMCPY(v + i * bSz, x, bSz);
981
        scryptBlockMix(x, y, r);
982
    }
983
984
    /* Step 3. */
985
    for (i = 0; i < n; i++)
986
    {
987
#ifdef LITTLE_ENDIAN_ORDER
988
        /* x is an allocator byte array; the big-endian path below already
989
         * assembles this byte-wise. */
990
#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS)
991
        j = (word32)(readUnalignedWord64(x + (2*r - 1) * 64) & (n-1));
992
#else
993
        j = readUnalignedWord32(x + (2*r - 1) * 64) & (n-1);
994
#endif
995
#else
996
        byte* t = x + (2*r - 1) * 64;
997
        j = ((word32)t[0] | ((word32)t[1] << 8) | ((word32)t[2] << 16) |
998
                ((word32)t[3] << 24)) & (n-1);
999
#endif
1000
#ifdef WORD64_AVAILABLE
1001
        for (k = 0; k < bSz / 8; k++)
1002
            x64[k] ^= v64[j * bSz / 8 + k];
1003
#else
1004
        for (k = 0; k < bSz / 4; k++)
1005
            x32[k] ^= v32[j * bSz / 4 + k];
1006
#endif
1007
        scryptBlockMix(x, y, r);
1008
    }
1009
    /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */
1010
}
1011
1012
/* Generates an key derived from a password and salt using a memory hard
1013
 * algorithm.
1014
 * Implements RFC 7914: scrypt PBKDF.
1015
 *
1016
 * output     The derived key.
1017
 * passwd     The password to derive key from.
1018
 * passLen    The length of the password.
1019
 * salt       The key specific data.
1020
 * saltLen    The length of the salt data.
1021
 * cost       The CPU/memory cost parameter. Range: 1..(128*r/8-1)
1022
 *            (Iterations = 2^cost)
1023
 * blockSize  The number of 128 byte octets in a working block.
1024
 * parallel   The number of parallel mix operations to perform.
1025
 *            (Note: this implementation does not use threads.)
1026
 * dkLen      The length of the derived key in bytes.
1027
 * returns BAD_FUNC_ARG when: blockSize is too large for cost.
1028
 */
1029
int wc_scrypt(byte* output, const byte* passwd, int passLen,
1030
              const byte* salt, int saltLen, int cost, int blockSize,
1031
              int parallel, int dkLen)
1032
{
1033
    int    ret = 0;
1034
    int    i;
1035
    byte*  v = NULL;
1036
    byte*  y = NULL;
1037
    byte*  blocks = NULL;
1038
    word32 blocksSz;
1039
    word32 bSz;
1040
1041
    if (blockSize > 8)
1042
        return BAD_FUNC_ARG;
1043
1044
    if (cost < 1 || cost >= 128 * blockSize / 8 || parallel < 1 || dkLen < 1)
1045
        return BAD_FUNC_ARG;
1046
1047
    /* The following comparison used to be:
1048
     *    ((word32)parallel > (SCRYPT_MAX / (128 * blockSize)))
1049
     * where SCRYPT_MAX is (2^32 - 1) * 32. For some compilers, the RHS of
1050
     * the comparison is greater than parallel's type. It wouldn't promote
1051
     * both sides to word64. What follows is just arithmetic simplification.
1052
     */
1053
    if (parallel > (int)((SCRYPT_WORD32_MAX / 4) / (word32)blockSize))
1054
        return BAD_FUNC_ARG;
1055
1056
    bSz = 128 * (word32)blockSize;
1057
    if (parallel > (int)(SCRYPT_WORD32_MAX / bSz))
1058
        return BAD_FUNC_ARG;
1059
    blocksSz = bSz * (word32)parallel;
1060
    blocks = (byte*)XMALLOC((size_t)blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1061
    if (blocks == NULL) {
1062
        ret = MEMORY_E;
1063
        goto end;
1064
    }
1065
1066
    /* Check that (1 << cost) * bSz won't overflow or exceed allowed max */
1067
    if (((size_t)1 << cost) * (size_t)bSz > SCRYPT_WORD32_MAX) {
1068
        ret = BAD_FUNC_ARG;
1069
        goto end;
1070
    }
1071
1072
    /* Temporary for scryptROMix. */
1073
    v = (byte*)XMALLOC(((size_t)1 << cost) * (size_t)bSz, NULL,
1074
                         DYNAMIC_TYPE_TMP_BUFFER);
1075
    if (v == NULL) {
1076
        ret = MEMORY_E;
1077
        goto end;
1078
    }
1079
    /* Temporary for scryptBlockMix. */
1080
    y = (byte*)XMALLOC((size_t)(blockSize * 128), NULL,
1081
                       DYNAMIC_TYPE_TMP_BUFFER);
1082
    if (y == NULL) {
1083
        ret = MEMORY_E;
1084
        goto end;
1085
    }
1086
1087
    XMEMSET(y, 0, (size_t)(blockSize * 128));
1088
1089
    /* Step 1. */
1090
    ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, (int)blocksSz,
1091
                    WC_SHA256);
1092
    if (ret != 0)
1093
        goto end;
1094
1095
    /* Step 2. */
1096
    for (i = 0; i < parallel; i++)
1097
        scryptROMix(blocks + i * (int)bSz, v, y, (int)blockSize,
1098
                    (word32)((size_t)1 << cost));
1099
1100
    /* Step 3. */
1101
    ret = wc_PBKDF2(output, passwd, passLen, blocks, (int)blocksSz, 1, dkLen,
1102
                    WC_SHA256);
1103
end:
1104
    if (blocks != NULL) {
1105
        ForceZero(blocks, blocksSz);
1106
    }
1107
    if (v != NULL) {
1108
        ForceZero(v, ((size_t)1 << cost) * (size_t)bSz);
1109
    }
1110
    if (y != NULL) {
1111
        ForceZero(y, (size_t)blockSize * 128);
1112
    }
1113
1114
    XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1115
    XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1116
    XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1117
1118
    return ret;
1119
}
1120
1121
/* Generates an key derived from a password and salt using a memory hard
1122
 * algorithm.
1123
 * Implements RFC 7914: scrypt PBKDF.
1124
 *
1125
 * output      Derived key.
1126
 * passwd      Password to derive key from.
1127
 * passLen     Length of the password.
1128
 * salt        Key specific data.
1129
 * saltLen     Length of the salt data.
1130
 * iterations  Number of iterations to perform. Range: 1 << (1..(128*r/8-1))
1131
 * blockSize   Number of 128 byte octets in a working block.
1132
 * parallel    Number of parallel mix operations to perform.
1133
 *             (Note: this implementation does not use threads.)
1134
 * dkLen       Length of the derived key in bytes.
1135
 * returns BAD_FUNC_ARG when: iterations is not a power of 2 or blockSize is too
1136
 *                            large for iterations.
1137
 */
1138
int wc_scrypt_ex(byte* output, const byte* passwd, int passLen,
1139
                 const byte* salt, int saltLen, word32 iterations,
1140
                 int blockSize, int parallel, int dkLen)
1141
{
1142
    int cost;
1143
1144
    /* Iterations must be a power of 2. */
1145
    if ((iterations & (iterations - 1)) != 0)
1146
        return BAD_FUNC_ARG;
1147
1148
    for (cost = -1; iterations != 0; cost++) {
1149
        iterations >>= 1;
1150
    }
1151
1152
    return wc_scrypt(output, passwd, passLen, salt, saltLen, cost, blockSize,
1153
                     parallel, dkLen);
1154
}
1155
#endif /* HAVE_SCRYPT */
1156
1157
#endif /* NO_PWDBASED */