Coverage Report

Created: 2026-05-18 06:53

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