Coverage Report

Created: 2026-04-01 07:25

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