Coverage Report

Created: 2026-10-16 06:40

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