Coverage Report

Created: 2026-11-12 06:59

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