Coverage Report

Created: 2026-07-22 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/wolfcrypt/src/random.c
Line
Count
Source
1
/* random.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
/*
23
24
DESCRIPTION
25
This library contains implementation for the random number generator.
26
27
*/
28
29
/*
30
 * Random Number Generator Build Options:
31
 *
32
 * Core RNG:
33
 * WC_NO_RNG:               Disable RNG support entirely         default: off
34
 * HAVE_HASHDRBG:            Enable Hash-based DRBG (SP 800-90A) default: on
35
 * WC_RNG_BLOCKING:          Make RNG operations blocking         default: off
36
 * WC_VERBOSE_RNG:           Enable verbose RNG debug output      default: off
37
 * WC_RNG_SEED_CB:           Use custom seed callback function    default: off
38
 * WC_RNG_BANK_SUPPORT:      Enable RNG bank (pre-generated)     default: off
39
 *                            random data support
40
 * WOLFSSL_RNG_USE_FULL_SEED: Use full-length seed for DRBG      default: off
41
 * WOLFSSL_GENSEED_FORTEST:  Use deterministic seed for testing   default: off
42
 *                            WARNING: not for production use
43
 * WOLFSSL_KEEP_RNG_SEED_FD_OPEN: Keep /dev/random fd open       default: off
44
 *                            between seed operations
45
 *
46
 * Custom RNG Sources:
47
 * CUSTOM_RAND_GENERATE:     Custom random word generator func    default: off
48
 * CUSTOM_RAND_GENERATE_BLOCK: Custom block random generator      default: off
49
 * CUSTOM_RAND_GENERATE_SEED: Custom seed generator function      default: off
50
 * CUSTOM_RAND_GENERATE_SEED_OS: Custom OS-level seed generator   default: off
51
 *
52
 * Entropy Sources:
53
 * HAVE_ENTROPY_MEMUSE:      Enable memory-use based entropy      default: off
54
 *                            source for DRBG seeding
55
 * ENTROPY_MEMUSE_FORCE_FAILURE: Force entropy failure (testing)  default: off
56
 * HAVE_GETRANDOM:           Use Linux getrandom() syscall        default: auto
57
 * WOLFSSL_GETRANDOM:        Use getrandom() for seed source      default: auto
58
 * FORCE_FAILURE_GETRANDOM:  Force getrandom failure (testing)    default: off
59
 * NO_DEV_RANDOM:            Don't use /dev/random for seeding    default: off
60
 * NO_DEV_URANDOM:           Don't use /dev/urandom for seeding   default: off
61
 * HAVE_INTEL_RDRAND:        Use Intel RDRAND instruction         default: off
62
 * HAVE_INTEL_RDSEED:        Use Intel RDSEED instruction         default: off
63
 * HAVE_AMD_RDSEED:          Use AMD RDSEED instruction           default: off
64
 * IDIRECT_DEV_RANDOM:       iDirect custom /dev/random path      default: off
65
 * WIN_REUSE_CRYPT_HANDLE:   Reuse Windows CryptContext handle    default: off
66
 *
67
 * Entropy Tuning (for HAVE_ENTROPY_MEMUSE):
68
 * ENTROPY_NUM_UPDATE:       Number of updates per sample         default: 18
69
 *                            More updates = better entropy but slower
70
 * ENTROPY_NUM_UPDATES_BITS: Bits to represent ENTROPY_NUM_UPDATE default: 5
71
 *                            = upper(log2(ENTROPY_NUM_UPDATE))
72
 * ENTROPY_NUM_WORDS_BITS:   State size as 2^N entries            default: 14
73
 *                            Range: 8-30. Base on cache sizes.
74
 *                            Larger = more cache misses = better entropy
75
 *                            but more static memory usage.
76
 *
77
 * DRBG Health Tests:
78
 * WC_RNG_SEED_APT_CUTOFF:  Adaptive proportion test cutoff      default: auto
79
 * WC_RNG_SEED_APT_WINDOW:  Adaptive proportion test window size  default: auto
80
 * WC_RNG_SEED_RCT_CUTOFF:  Repetition count test cutoff         default: auto
81
 *
82
 * Hardware RNG:
83
 * STM32_RNG:                STM32 hardware RNG                   default: off
84
 * STM32_NUTTX_RNG:          STM32 RNG via NuttX                  default: off
85
 * WOLFSSL_STM32F427_RNG:    STM32F427 hardware RNG               default: off
86
 * WOLFSSL_STM32_RNG_NOLIB:  STM32 RNG without HAL library        default: off
87
 * WOLFSSL_PIC32MZ_RNG:      PIC32MZ hardware RNG                 default: off
88
 * FREESCALE_RNGA:           Freescale RNGA                       default: off
89
 * FREESCALE_K70_RNGA:       Freescale K70 RNGA                   default: off
90
 * FREESCALE_RNGB:           Freescale RNGB                       default: off
91
 * FREESCALE_KSDK_2_0_RNGA:  Freescale KSDK 2.0 RNGA             default: off
92
 * FREESCALE_KSDK_2_0_TRNG:  Freescale KSDK 2.0 TRNG             default: off
93
 * MAX3266X_RNG:             MAX3266X hardware RNG                 default: off
94
 * QAT_ENABLE_RNG:           Intel QAT hardware RNG               default: off
95
 * WOLFSSL_ATECC_RNG:        ATECC508/608 hardware RNG             default: off
96
 * WOLFSSL_SILABS_TRNG:      Silicon Labs TRNG                    default: off
97
 * WOLFSSL_SCE_NO_TRNG:      Disable Renesas SCE TRNG             default: off
98
 * WOLFSSL_SCE_TRNG_HANDLE:  Renesas SCE TRNG handle              default: off
99
 * WOLFSSL_SE050_NO_TRNG:    Disable SE050 TRNG                   default: off
100
 * WOLFSSL_PSA_NO_RNG:       Disable PSA RNG                      default: off
101
 * HAVE_IOTSAFE_HWRNG:       IoT-Safe hardware RNG                default: off
102
 * WOLFSSL_XILINX_CRYPT_VERSAL: Xilinx Versal crypto RNG          default: off
103
 */
104
105
#define _WC_BUILDING_RANDOM_C
106
107
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
108
109
/* on HPUX 11 you may need to install /dev/random see
110
   http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
111
112
*/
113
#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
114
    #include <esp_random.h>
115
#endif
116
117
#if defined(HAVE_FIPS) && \
118
    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
119
120
    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
121
    #define FIPS_NO_WRAPPERS
122
123
    #ifdef USE_WINDOWS_API
124
        #pragma code_seg(".fipsA$i")
125
        #pragma const_seg(".fipsB$i")
126
    #endif
127
#endif
128
129
130
#include <wolfssl/wolfcrypt/random.h>
131
#ifdef WC_RNG_BANK_SUPPORT
132
    #include <wolfssl/wolfcrypt/rng_bank.h>
133
#endif
134
#include <wolfssl/wolfcrypt/cpuid.h>
135
136
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
137
138
#ifndef NO_SHA256
139
    #include <wolfssl/wolfcrypt/sha256.h>
140
#endif
141
#ifdef WOLFSSL_DRBG_SHA512
142
    #include <wolfssl/wolfcrypt/sha512.h>
143
#endif
144
145
#ifdef WOLF_CRYPTO_CB
146
    #include <wolfssl/wolfcrypt/cryptocb.h>
147
#endif
148
149
#ifdef NO_INLINE
150
    #include <wolfssl/wolfcrypt/misc.h>
151
#else
152
    #define WOLFSSL_MISC_INCLUDED
153
    #include <wolfcrypt/src/misc.c>
154
#endif
155
156
#if defined(WOLFSSL_SGX)
157
    #include <sgx_trts.h>
158
#elif defined(USE_WINDOWS_API)
159
    #ifndef _WIN32_WINNT
160
        #define _WIN32_WINNT 0x0400
161
    #endif
162
    #define _WINSOCKAPI_ /* block inclusion of winsock.h header file */
163
    #include <windows.h>
164
    #include <wincrypt.h>
165
    #undef _WINSOCKAPI_ /* undefine it for MINGW winsock2.h header file */
166
#elif defined(HAVE_WNR)
167
    #include <wnr.h>
168
    wolfSSL_Mutex wnr_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wnr_mutex);    /* global netRandom mutex */
169
    int wnr_timeout     = 0;    /* entropy timeout, milliseconds */
170
    #ifndef WOLFSSL_MUTEX_INITIALIZER
171
    int wnr_mutex_inited = 0;   /* flag for mutex init */
172
    #endif
173
    int wnr_inited = 0;    /* flag for whether wc_InitNetRandom() has been called */
174
    wnr_context*  wnr_ctx;      /* global netRandom context */
175
#elif defined(FREESCALE_KSDK_2_0_TRNG)
176
    #include "fsl_trng.h"
177
#elif defined(FREESCALE_KSDK_2_0_RNGA)
178
    #include "fsl_rnga.h"
179
#elif defined(WOLFSSL_WICED)
180
    #include "wiced_crypto.h"
181
#elif defined(WOLFSSL_NETBURNER)
182
    #include <predef.h>
183
    #include <basictypes.h>
184
    #include <random.h>
185
#elif defined(WOLFSSL_XILINX_CRYPT_VERSAL)
186
    #include "wolfssl/wolfcrypt/port/xilinx/xil-versal-trng.h"
187
#elif defined(WOLFSSL_RPIPICO)
188
    #include "wolfssl/wolfcrypt/port/rpi_pico/pico.h"
189
#elif defined(NO_DEV_RANDOM)
190
#elif defined(CUSTOM_RAND_GENERATE)
191
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
192
#elif defined(CUSTOM_RAND_GENERATE_SEED)
193
#elif defined(WOLFSSL_GENSEED_FORTEST)
194
#elif defined(WOLFSSL_MDK_ARM)
195
#elif defined(WOLFSSL_IAR_ARM)
196
#elif defined(WOLFSSL_ROWLEY_ARM)
197
#elif defined(WOLFSSL_EMBOS)
198
#elif defined(WOLFSSL_DEOS)
199
#elif defined(MICRIUM)
200
#elif defined(WOLFSSL_NUCLEUS)
201
#elif defined(WOLFSSL_PB)
202
#elif defined(WOLFSSL_ZEPHYR)
203
#elif defined(WOLFSSL_TELIT_M2MB)
204
#elif defined(WOLFSSL_RENESAS_TSIP)
205
    /* for wc_tsip_GenerateRandBlock */
206
    #include "wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h"
207
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
208
#elif defined(WOLFSSL_IMXRT1170_CAAM)
209
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
210
    #include "cyhal_trng.h" /* Infineon/Cypress HAL RNG implementation */
211
#elif defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
212
    #include "wolfssl/wolfcrypt/port/maxim/max3266x.h"
213
#else
214
    #include <errno.h>
215
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
216
        #include <sys/random.h>
217
    #endif
218
    /* include headers that may be needed to get good seed */
219
    #include <fcntl.h>
220
    #ifndef EBSNET
221
        #include <unistd.h>
222
    #endif
223
#endif
224
225
#if defined(WOLFSSL_SILABS_SE_ACCEL)
226
#include <wolfssl/wolfcrypt/port/silabs/silabs_random.h>
227
#endif
228
229
#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_IOTSAFE_HWRNG)
230
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
231
#endif
232
233
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_RNG)
234
#include <wolfssl/wolfcrypt/port/psa/psa.h>
235
#endif
236
237
#if FIPS_VERSION3_GE(6,0,0)
238
    const unsigned int wolfCrypt_FIPS_drbg_ro_sanity[2] =
239
                                                     { 0x1a2b3c4d, 0x00000011 };
240
    int wolfCrypt_FIPS_DRBG_sanity(void)
241
    {
242
        return 0;
243
    }
244
#endif
245
246
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
247
    defined(HAVE_AMD_RDSEED)
248
    static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER;
249
    static void wc_InitRng_IntelRD(void)
250
    {
251
        cpuid_get_flags_ex(&intel_flags);
252
    }
253
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
254
    static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
255
    #endif
256
    #ifdef HAVE_INTEL_RDRAND
257
    static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
258
    #endif
259
260
#ifdef USE_WINDOWS_API
261
    #define USE_INTEL_INTRINSICS
262
#elif !defined __GNUC__ || defined __clang__ || __GNUC__ > 4
263
    #define USE_INTEL_INTRINSICS
264
#else
265
    #undef USE_INTEL_INTRINSICS
266
#endif
267
268
#ifdef USE_INTEL_INTRINSICS
269
    #include <immintrin.h>
270
    /* Before clang 7 or GCC 9, immintrin.h did not define _rdseed64_step() */
271
    #ifndef HAVE_INTEL_RDSEED
272
    #elif defined __clang__ && __clang_major__ > 6
273
    #elif !defined __GNUC__
274
    #elif __GNUC__ > 8
275
    #else
276
        #ifndef __clang__
277
            #pragma GCC push_options
278
            #pragma GCC target("rdseed")
279
        #else
280
            #define __RDSEED__
281
        #endif
282
        #include <x86intrin.h>
283
        #ifndef __clang__
284
            #pragma GCC pop_options
285
        #endif
286
    #endif
287
#endif /* USE_WINDOWS_API */
288
#endif
289
290
/* Start NIST DRBG code */
291
#ifdef HAVE_HASHDRBG
292
293
0
#define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
294
#define MAX_REQUEST_LEN   (0x10000)
295
296
#ifdef WC_RNG_SEED_CB
297
298
#ifndef HAVE_FIPS
299
static wc_RngSeed_Cb seedCb = wc_GenerateSeed;
300
#else
301
static wc_RngSeed_Cb seedCb = NULL;
302
#endif
303
304
int wc_SetSeed_Cb(wc_RngSeed_Cb cb)
305
{
306
    seedCb = cb;
307
    return 0;
308
}
309
310
#endif
311
312
313
/* Internal return codes */
314
4.58M
#define DRBG_SUCCESS      0
315
1.14M
#define DRBG_FAILURE      1
316
239k
#define DRBG_NEED_RESEED  2
317
15.2k
#define DRBG_CONT_FAILURE 3
318
#define DRBG_NO_SEED_CB   4
319
320
/* RNG health states */
321
235k
#define DRBG_NOT_INIT     WC_DRBG_NOT_INIT
322
347k
#define DRBG_OK           WC_DRBG_OK
323
20.0k
#define DRBG_FAILED       WC_DRBG_FAILED
324
967
#define DRBG_CONT_FAILED  WC_DRBG_CONT_FAILED
325
326
115k
#define SEED_SZ           WC_DRBG_SEED_SZ
327
115k
#define MAX_SEED_SZ       WC_DRBG_MAX_SEED_SZ
328
329
/* Verify max gen block len */
330
#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
331
    #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
332
#endif
333
334
enum {
335
    drbgInitC     = 0,
336
    drbgReseed    = 1,
337
    drbgGenerateW = 2,
338
    drbgGenerateH = 3,
339
    drbgInitV     = 4
340
};
341
342
#ifndef NO_SHA256
343
typedef struct DRBG_internal DRBG_internal;
344
#endif
345
346
#ifdef WOLFSSL_DRBG_SHA512
347
typedef struct DRBG_SHA512_internal DRBG_SHA512_internal;
348
349
static int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg, const byte* seed,
350
                               word32 seedSz,
351
                               const byte* additional, word32 additionalSz);
352
static int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg, byte* out,
353
                                 word32 outSz,
354
                                 const byte* additional, word32 additionalSz);
355
static int Hash512_DRBG_Instantiate(DRBG_SHA512_internal* drbg,
356
                                    const byte* seed, word32 seedSz,
357
                                    const byte* nonce, word32 nonceSz,
358
                                    const byte* perso, word32 persoSz,
359
                                    void* heap, int devId);
360
static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg);
361
#endif
362
363
/* Runtime DRBG disable state.
364
 * These flags control which DRBG type is used for new WC_RNG instances and
365
 * may be toggled at runtime (e.g. NSA Suite 2.0 threads disable SHA-256).
366
 * A mutex protects the check-then-set in disable functions so concurrent
367
 * calls cannot bypass the mutual-exclusion guard and disable both DRBG types.
368
 * _InitRng also holds the mutex while reading the flags to get a consistent
369
 * snapshot, and returns BAD_STATE_E if both are somehow disabled. */
370
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
371
#ifndef NO_SHA256
372
#ifdef WOLFSSL_NO_SHA256_DRBG
373
static int sha256DrbgDisabled = 1;
374
#else
375
static int sha256DrbgDisabled = 0;
376
#endif /* WOLFSSL_NO_SHA256_DRBG */
377
#endif /* !NO_SHA256 */
378
#ifdef WOLFSSL_DRBG_SHA512
379
static int sha512DrbgDisabled = 0;
380
#endif /* WOLFSSL_DRBG_SHA512 */
381
382
#ifndef SINGLE_THREADED
383
static wolfSSL_Mutex drbgStateMutex
384
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(drbgStateMutex);
385
#ifndef WOLFSSL_MUTEX_INITIALIZER
386
static int drbgStateMutex_inited = 0;
387
#endif
388
#endif /* !SINGLE_THREADED */
389
390
int wc_DrbgState_MutexInit(void)
391
5.48k
{
392
5.48k
#ifndef SINGLE_THREADED
393
#ifndef WOLFSSL_MUTEX_INITIALIZER
394
    if (!drbgStateMutex_inited) {
395
        int ret = wc_InitMutex(&drbgStateMutex);
396
        if (ret != 0)
397
            return ret;
398
        drbgStateMutex_inited = 1;
399
    }
400
#endif
401
5.48k
#endif
402
5.48k
    return 0;
403
5.48k
}
404
405
int wc_DrbgState_MutexFree(void)
406
5.48k
{
407
5.48k
#ifndef SINGLE_THREADED
408
#ifndef WOLFSSL_MUTEX_INITIALIZER
409
    if (drbgStateMutex_inited) {
410
        int ret = wc_FreeMutex(&drbgStateMutex);
411
        drbgStateMutex_inited = 0;
412
        return ret;
413
    }
414
#endif
415
5.48k
#endif
416
5.48k
    return 0;
417
5.48k
}
418
419
static int LockDrbgState(void)
420
126k
{
421
126k
#ifndef SINGLE_THREADED
422
126k
    return wc_LockMutex(&drbgStateMutex);
423
#else
424
    return 0;
425
#endif
426
126k
}
427
428
static int UnlockDrbgState(void)
429
126k
{
430
126k
#ifndef SINGLE_THREADED
431
126k
    return wc_UnLockMutex(&drbgStateMutex);
432
#else
433
    return 0;
434
#endif
435
126k
}
436
437
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
438
439
static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap,
440
                                  int devId);
441
442
#ifdef WOLFSSL_DRBG_SHA512
443
static int wc_RNG_HealthTest_SHA512_ex_internal(DRBG_SHA512_internal* drbg,
444
                                  int reseed, const byte* nonce, word32 nonceSz,
445
                                  const byte* perso, word32 persoSz,
446
                                  const byte* seedA, word32 seedASz,
447
                                  const byte* seedB, word32 seedBSz,
448
                                  const byte* additionalA, word32 additionalASz,
449
                                  const byte* additionalB, word32 additionalBSz,
450
                                  byte* output, word32 outputSz,
451
                                  void* heap, int devId);
452
#endif
453
454
/* The SHA-256 Hash_DRBG core (Hash_df, Hash_DRBG_*) operates on
455
 * DRBG_internal, which random.h defines only when SHA-256 is compiled in.
456
 * Wrap the whole block so a NO_SHA256 + WOLFSSL_DRBG_SHA512 build (the
457
 * SHA-512-only DRBG configuration) still compiles. The SHA-512 DRBG core
458
 * lives below in its own #ifdef WOLFSSL_DRBG_SHA512 section. */
459
#ifndef NO_SHA256
460
461
/* Hash Derivation Function */
462
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
463
static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
464
                                                  const byte* inA, word32 inASz,
465
                                                  const byte* inB, word32 inBSz,
466
                                                  const byte* inC, word32 inCSz)
467
0
{
468
0
    int ret = DRBG_FAILURE;
469
0
    byte ctr;
470
0
    word32 i;
471
0
    word32 len;
472
0
    word32 bits = (outSz * 8); /* reverse byte order */
473
#ifdef WOLFSSL_SMALL_STACK_CACHE
474
    wc_Sha256* sha = &drbg->sha256;
475
#else
476
0
    wc_Sha256 sha[1];
477
0
#endif
478
#if defined(WOLFSSL_SMALL_STACK_CACHE)
479
    byte* digest = drbg->digest_scratch;
480
#elif defined(WOLFSSL_SMALL_STACK)
481
    byte* digest;
482
#else
483
    byte digest[WC_SHA256_DIGEST_SIZE];
484
#endif
485
486
0
    if (drbg == NULL) {
487
0
        return DRBG_FAILURE;
488
0
    }
489
490
0
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
491
0
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
492
0
        DYNAMIC_TYPE_DIGEST);
493
0
    if (digest == NULL)
494
0
        return DRBG_FAILURE;
495
0
#endif
496
497
0
#ifdef LITTLE_ENDIAN_ORDER
498
0
    bits = ByteReverseWord32(bits);
499
0
#endif
500
0
    len = (outSz / OUTPUT_BLOCK_LEN)
501
0
        + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
502
503
0
    ctr = 1;
504
0
    for (i = 0; i < len; i++) {
505
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
506
0
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
507
0
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
508
    #else
509
        ret = wc_InitSha256(sha);
510
    #endif
511
0
        if (ret != 0)
512
0
            break;
513
0
#endif
514
0
        ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
515
0
        if (ret == 0) {
516
0
            ctr++;
517
0
            ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
518
0
        }
519
520
0
        if (ret == 0) {
521
            /* churning V is the only string that doesn't have the type added */
522
0
            if (type != drbgInitV)
523
0
                ret = wc_Sha256Update(sha, &type, sizeof(type));
524
0
        }
525
0
        if (ret == 0)
526
0
            ret = wc_Sha256Update(sha, inA, inASz);
527
0
        if (ret == 0) {
528
0
            if (inB != NULL && inBSz > 0)
529
0
                ret = wc_Sha256Update(sha, inB, inBSz);
530
0
        }
531
0
        if (ret == 0) {
532
0
            if (inC != NULL && inCSz > 0)
533
0
                ret = wc_Sha256Update(sha, inC, inCSz);
534
0
        }
535
0
        if (ret == 0)
536
0
            ret = wc_Sha256Final(sha, digest);
537
538
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
539
0
        wc_Sha256Free(sha);
540
0
#endif
541
0
        if (ret == 0) {
542
0
            if (outSz > OUTPUT_BLOCK_LEN) {
543
0
                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
544
0
                outSz -= OUTPUT_BLOCK_LEN;
545
0
                out += OUTPUT_BLOCK_LEN;
546
0
            }
547
0
            else {
548
0
                XMEMCPY(out, digest, outSz);
549
0
            }
550
0
        }
551
0
    }
552
553
0
    ForceZero(digest, WC_SHA256_DIGEST_SIZE);
554
555
0
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
556
0
    XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
557
0
#endif
558
559
#ifdef WC_VERBOSE_RNG
560
    if (ret != 0)
561
        WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __func__,
562
                             ret);
563
#endif
564
565
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
566
0
}
567
568
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
569
static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz,
570
                            const byte* additional, word32 additionalSz)
571
0
{
572
0
    int ret;
573
0
    WC_DECLARE_VAR(newV, byte, DRBG_SEED_LEN, 0);
574
575
0
    if (drbg == NULL) {
576
0
        return DRBG_FAILURE;
577
0
    }
578
579
#ifdef WOLFSSL_SMALL_STACK_CACHE
580
    newV = drbg->seed_scratch;
581
#else
582
0
    WC_ALLOC_VAR_EX(newV, byte, DRBG_SEED_LEN, drbg->heap,
583
0
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
584
0
#endif
585
0
    XMEMSET(newV, 0, DRBG_SEED_LEN);
586
587
0
    ret = Hash_df(drbg, newV, DRBG_SEED_LEN, drbgReseed,
588
0
                drbg->V, sizeof(drbg->V), seed, seedSz,
589
0
                additional, additionalSz);
590
0
    if (ret == DRBG_SUCCESS) {
591
0
        XMEMCPY(drbg->V, newV, sizeof(drbg->V));
592
593
0
        ret = Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
594
0
                                    sizeof(drbg->V), NULL, 0, NULL, 0);
595
0
    }
596
0
    if (ret == DRBG_SUCCESS) {
597
0
        drbg->reseedCtr = 1;
598
0
    }
599
600
0
    ForceZero(newV, DRBG_SEED_LEN);
601
602
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
603
0
    WC_FREE_VAR_EX(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
604
0
#endif
605
606
    #ifdef WC_VERBOSE_RNG
607
    if (ret != 0)
608
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Reseed failed with err %d.",
609
                             ret);
610
    #endif
611
612
0
    return ret;
613
0
}
614
615
#endif /* !NO_SHA256 - close before wc_RNG_DRBG_Reseed (dual-DRBG-aware)
616
        *              and array_add_one (shared utility) which both must
617
        *              remain available to SHA-512-only builds */
618
619
/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
620
int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
621
0
{
622
0
    if (rng == NULL || seed == NULL) {
623
0
        return BAD_FUNC_ARG;
624
0
    }
625
626
0
#ifndef NO_SHA256
627
0
    if (rng->drbgType == WC_DRBG_SHA256) {
628
0
        if (rng->drbg == NULL) {
629
        #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
630
            if (IS_INTEL_RDRAND(intel_flags)) {
631
                /* using RDRAND not DRBG, so return success */
632
                return 0;
633
            }
634
        #endif
635
0
            return BAD_FUNC_ARG;
636
0
        }
637
0
        return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz,
638
0
                                NULL, 0);
639
0
    }
640
0
#endif
641
0
#ifdef WOLFSSL_DRBG_SHA512
642
0
    if (rng->drbgType == WC_DRBG_SHA512) {
643
0
        if (rng->drbg512 == NULL) {
644
        #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
645
            if (IS_INTEL_RDRAND(intel_flags)) {
646
                /* using RDRAND not DRBG, so return success */
647
                return 0;
648
            }
649
        #endif
650
0
            return BAD_FUNC_ARG;
651
0
        }
652
0
        return Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512,
653
0
                                   seed, seedSz, NULL, 0);
654
0
    }
655
0
#endif
656
657
    /* No DRBG type matched; if using RDRAND, that's OK */
658
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
659
    if (IS_INTEL_RDRAND(intel_flags)) {
660
        return 0;
661
    }
662
#endif
663
664
0
    return BAD_FUNC_ARG;
665
0
}
666
667
/* Generic byte-array helper -- shared by both SHA-256 and SHA-512 DRBG
668
 * cores. Lives outside the NO_SHA256 guard so SHA-512-only builds
669
 * still link. */
670
static WC_INLINE void array_add_one(byte* data, word32 dataSz)
671
1.02M
{
672
1.02M
    int i;
673
1.02M
    for (i = (int)dataSz - 1; i >= 0; i--) {
674
1.02M
        data[i]++;
675
1.02M
        if (data[i] != 0) break;
676
1.02M
    }
677
1.02M
}
678
679
#ifndef NO_SHA256 /* re-open SHA-256 Hash_DRBG core */
680
681
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
682
static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V)
683
0
{
684
0
    int ret = DRBG_FAILURE;
685
0
    word32 i;
686
0
    word32 len;
687
#if defined(WOLFSSL_SMALL_STACK_CACHE)
688
    wc_Sha256* sha = &drbg->sha256;
689
    byte* data = drbg->seed_scratch;
690
    byte* digest = drbg->digest_scratch;
691
#elif defined(WOLFSSL_SMALL_STACK)
692
    wc_Sha256 sha[1];
693
0
    byte* data = NULL;
694
0
    byte* digest = NULL;
695
#else
696
    wc_Sha256 sha[1];
697
    byte data[DRBG_SEED_LEN];
698
    byte digest[WC_SHA256_DIGEST_SIZE];
699
#endif
700
701
0
    if (drbg == NULL) {
702
0
        return DRBG_FAILURE;
703
0
    }
704
705
0
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
706
0
    data = (byte*)XMALLOC(DRBG_SEED_LEN, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
707
0
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
708
0
        DYNAMIC_TYPE_DIGEST);
709
0
    if (data == NULL || digest == NULL) {
710
0
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
711
0
        XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
712
0
        return DRBG_FAILURE;
713
0
    }
714
0
#endif
715
716
    /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
717
     * the continuous test. */
718
719
0
    if (outSz == 0) {
720
0
        outSz = 1;
721
0
    }
722
723
0
    len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
724
725
0
    XMEMCPY(data, V, DRBG_SEED_LEN);
726
0
    for (i = 0; i < len; i++) {
727
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
728
0
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
729
0
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
730
    #else
731
        ret = wc_InitSha256(sha);
732
    #endif
733
0
        if (ret == 0)
734
0
#endif
735
0
            ret = wc_Sha256Update(sha, data, DRBG_SEED_LEN);
736
0
        if (ret == 0)
737
0
            ret = wc_Sha256Final(sha, digest);
738
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
739
0
        wc_Sha256Free(sha);
740
0
#endif
741
742
0
        if (ret == 0) {
743
0
            if (out != NULL && outSz != 0) {
744
0
                if (outSz >= OUTPUT_BLOCK_LEN) {
745
0
                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
746
0
                    outSz -= OUTPUT_BLOCK_LEN;
747
0
                    out += OUTPUT_BLOCK_LEN;
748
0
                    array_add_one(data, DRBG_SEED_LEN);
749
0
                }
750
0
                else {
751
0
                    XMEMCPY(out, digest, outSz);
752
0
                    outSz = 0;
753
0
                }
754
0
            }
755
0
        }
756
0
        else {
757
            /* wc_Sha256Update or wc_Sha256Final returned error */
758
0
            break;
759
0
        }
760
0
    }
761
0
    ForceZero(data, DRBG_SEED_LEN);
762
763
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
764
0
    WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
765
0
    WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
766
0
#endif
767
768
    #ifdef WC_VERBOSE_RNG
769
    if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
770
        /* Note, if we're just going to return DRBG_FAILURE to the caller, then
771
         * there's no point printing it out here because (1) the lower-level
772
         * code that was remapped to DRBG_FAILURE already got printed before the
773
         * remapping, so a DRBG_FAILURE message would just be spamming the log,
774
         * and (2) the caller will actually see the DRBG_FAILURE code, and is
775
         * free to (and probably will) log it itself.
776
         */
777
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_gen failed with err %d.", ret);
778
    }
779
    #endif
780
781
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
782
0
}
783
784
#endif /* !NO_SHA256 - close to expose array_add to SHA-512 below */
785
786
/* Generic multi-byte add. Shared by SHA-256 and SHA-512 DRBG cores;
787
 * lives outside the NO_SHA256 guard so SHA-512-only builds still link. */
788
static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
789
1.45M
{
790
1.45M
    if (dLen > 0 && sLen > 0 && dLen >= sLen) {
791
1.45M
        int sIdx, dIdx;
792
1.45M
        word16 carry = 0;
793
794
1.45M
        dIdx = (int)dLen - 1;
795
90.0M
        for (sIdx = (int)sLen - 1; sIdx >= 0; sIdx--) {
796
88.6M
            carry = (word16)(carry + d[dIdx] + s[sIdx]);
797
88.6M
            d[dIdx] = (byte)carry;
798
88.6M
            carry >>= 8;
799
88.6M
            dIdx--;
800
88.6M
        }
801
802
74.1M
        for (; dIdx >= 0; dIdx--) {
803
72.6M
            carry = (word16)(carry + d[dIdx]);
804
72.6M
            d[dIdx] = (byte)carry;
805
72.6M
            carry >>= 8;
806
72.6M
        }
807
1.45M
    }
808
1.45M
}
809
810
#ifndef NO_SHA256 /* re-open SHA-256 Hash_DRBG core */
811
812
/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
813
static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz,
814
                              const byte* additional, word32 additionalSz)
815
0
{
816
0
    int ret;
817
#ifdef WOLFSSL_SMALL_STACK_CACHE
818
    wc_Sha256* sha = &drbg->sha256;
819
#else
820
0
    wc_Sha256 sha[1];
821
0
#endif
822
0
    byte type;
823
0
#ifdef WORD64_AVAILABLE
824
0
    word64 reseedCtr;
825
#else
826
    word32 reseedCtr;
827
#endif
828
829
0
    if (drbg == NULL) {
830
0
        return DRBG_FAILURE;
831
0
    }
832
833
0
    if (drbg->reseedCtr >= WC_RESEED_INTERVAL) {
834
    #if (defined(DEBUG_WOLFSSL) || defined(DEBUG_DRBG_RESEEDS)) && \
835
        defined(WOLFSSL_DEBUG_PRINTF)
836
        WOLFSSL_DEBUG_PRINTF("DRBG reseed triggered, reseedCtr == %lu",
837
                (unsigned long)drbg->reseedCtr);
838
    #endif
839
0
        return DRBG_NEED_RESEED;
840
0
    }
841
0
    else {
842
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
843
        byte* digest = drbg->digest_scratch;
844
    #elif defined(WOLFSSL_SMALL_STACK)
845
0
        byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
846
0
            DYNAMIC_TYPE_DIGEST);
847
0
        if (digest == NULL)
848
0
            return DRBG_FAILURE;
849
    #else
850
        byte digest[WC_SHA256_DIGEST_SIZE];
851
    #endif
852
853
0
        type = drbgGenerateH;
854
0
        reseedCtr = drbg->reseedCtr;
855
856
        /* SP 800-90A 10.1.1.4 step 2: if additional_input != Null,
857
         * w = Hash(0x02 || V || additional_input), V = (V + w) mod 2^seedlen */
858
0
        if (additional != NULL && additionalSz > 0) {
859
0
            byte addType = drbgGenerateW;
860
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
861
0
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
862
0
            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
863
        #else
864
            ret = wc_InitSha256(sha);
865
        #endif
866
0
            if (ret != 0) {
867
0
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
868
0
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
869
0
            #endif
870
0
                return DRBG_FAILURE;
871
0
            }
872
#else
873
            ret = 0;
874
#endif
875
0
            if (ret == 0)
876
0
                ret = wc_Sha256Update(sha, &addType, sizeof(addType));
877
0
            if (ret == 0)
878
0
                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
879
0
            if (ret == 0)
880
0
                ret = wc_Sha256Update(sha, additional, additionalSz);
881
0
            if (ret == 0)
882
0
                ret = wc_Sha256Final(sha, digest);
883
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
884
0
            wc_Sha256Free(sha);
885
0
#endif
886
0
            if (ret == 0) {
887
0
                array_add(drbg->V, sizeof(drbg->V), digest,
888
0
                          WC_SHA256_DIGEST_SIZE);
889
0
            }
890
0
            else {
891
0
                ForceZero(digest, WC_SHA256_DIGEST_SIZE);
892
0
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
893
0
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
894
0
            #endif
895
0
                return DRBG_FAILURE;
896
0
            }
897
0
        }
898
899
0
        ret = Hash_gen(drbg, out, outSz, drbg->V);
900
0
        if (ret == DRBG_SUCCESS) {
901
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
902
0
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
903
0
            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
904
        #else
905
            ret = wc_InitSha256(sha);
906
        #endif
907
0
            if (ret == 0)
908
0
#endif
909
0
                ret = wc_Sha256Update(sha, &type, sizeof(type));
910
0
            if (ret == 0)
911
0
                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
912
0
            if (ret == 0)
913
0
                ret = wc_Sha256Final(sha, digest);
914
915
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
916
0
            wc_Sha256Free(sha);
917
0
#endif
918
919
0
            if (ret == 0) {
920
0
                array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
921
0
                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
922
0
            #ifdef LITTLE_ENDIAN_ORDER
923
0
                #ifdef WORD64_AVAILABLE
924
0
                reseedCtr = ByteReverseWord64(reseedCtr);
925
                #else
926
                reseedCtr = ByteReverseWord32(reseedCtr);
927
                #endif
928
0
            #endif
929
0
                array_add(drbg->V, sizeof(drbg->V),
930
0
                                          (byte*)&reseedCtr, sizeof(reseedCtr));
931
0
                ret = DRBG_SUCCESS;
932
0
            }
933
0
            drbg->reseedCtr++;
934
0
        }
935
0
        ForceZero(digest, WC_SHA256_DIGEST_SIZE);
936
0
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
937
0
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
938
0
    #endif
939
0
    }
940
941
    #ifdef WC_VERBOSE_RNG
942
    if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
943
        /* see note above regarding log spam reduction */
944
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Generate failed with err %d.",
945
                             ret);
946
    }
947
    #endif
948
949
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
950
0
}
951
952
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
953
static int Hash_DRBG_Init(DRBG_internal* drbg, const byte* seed, word32 seedSz,
954
                                             const byte* nonce, word32 nonceSz,
955
                                             const byte* perso, word32 persoSz)
956
0
{
957
0
    if (seed == NULL)
958
0
        return DRBG_FAILURE;
959
960
0
    if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
961
0
                                              nonce, nonceSz,
962
0
                                              perso, persoSz) == DRBG_SUCCESS &&
963
0
        Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
964
0
                                    sizeof(drbg->V), NULL, 0,
965
0
                                    NULL, 0) == DRBG_SUCCESS) {
966
967
0
        drbg->reseedCtr = 1;
968
0
        return DRBG_SUCCESS;
969
0
    }
970
0
    else {
971
0
        return DRBG_FAILURE;
972
0
    }
973
0
}
974
975
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
976
static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed,
977
                                 word32 seedSz, const byte* nonce,
978
                                 word32 nonceSz, const byte* perso,
979
                                 word32 persoSz, void* heap, int devId)
980
0
{
981
0
    int ret = DRBG_FAILURE;
982
983
0
    XMEMSET(drbg, 0, sizeof(DRBG_internal));
984
0
    drbg->heap = heap;
985
0
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
986
0
    drbg->devId = devId;
987
#else
988
    (void)devId;
989
#endif
990
991
#ifdef WOLFSSL_SMALL_STACK_CACHE
992
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
993
        ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
994
    #else
995
        ret = wc_InitSha256(&drbg->sha256);
996
    #endif
997
    if (ret != 0)
998
        return ret;
999
#endif
1000
1001
0
    if (seed != NULL)
1002
0
        ret = Hash_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz,
1003
0
                             perso, persoSz);
1004
0
    return ret;
1005
0
}
1006
1007
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1008
static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg)
1009
0
{
1010
0
    word32 i;
1011
0
    int    compareSum = 0;
1012
0
    byte*  compareDrbg = (byte*)drbg;
1013
1014
#ifdef WOLFSSL_SMALL_STACK_CACHE
1015
    wc_Sha256Free(&drbg->sha256);
1016
#endif
1017
1018
0
    ForceZero(drbg, sizeof(DRBG_internal));
1019
1020
0
    for (i = 0; i < sizeof(DRBG_internal); i++) {
1021
0
        compareSum |= compareDrbg[i] ^ 0;
1022
0
    }
1023
1024
0
    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1025
0
}
1026
1027
#endif /* !NO_SHA256 - SHA-256 Hash_DRBG core block */
1028
1029
/* ====================================================================== */
1030
/* SHA-512 Hash_DRBG (SP 800-90A Rev 1, Table 2)                          */
1031
/*                                                                         */
1032
/* Internal state (V, C): seedlen = 888 bits = 111 bytes each              */
1033
/* Output block length:   512 bits = 64 bytes (WC_SHA512_DIGEST_SIZE)      */
1034
/* Security strength:     256 bits                                         */
1035
/*                                                                         */
1036
/* NOTE: The raw entropy seed gathered at instantiation / reseed is        */
1037
/* WC_DRBG_SEED_SZ (1024 bits in FIPS builds), NOT seedlen.  We overseed  */
1038
/* to tolerate weak entropy sources.  Hash_df then compresses the seed     */
1039
/* material down to the 888-bit V and derives C from V.  See random.h.    */
1040
/* ====================================================================== */
1041
#ifdef WOLFSSL_DRBG_SHA512
1042
1043
6.48M
#define OUTPUT_BLOCK_LEN_SHA512  (WC_SHA512_DIGEST_SIZE)  /* 64 bytes */
1044
1045
/* Hash Derivation Function using SHA-512 */
1046
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1047
static int Hash512_df(DRBG_SHA512_internal* drbg, byte* out, word32 outSz,
1048
                      byte type,
1049
                      const byte* inA, word32 inASz,
1050
                      const byte* inB, word32 inBSz,
1051
                      const byte* inC, word32 inCSz)
1052
434k
{
1053
434k
    int ret = DRBG_FAILURE;
1054
434k
    byte ctr;
1055
434k
    word32 i;
1056
434k
    word32 len;
1057
434k
    word32 bits = (outSz * 8);
1058
#ifdef WOLFSSL_SMALL_STACK_CACHE
1059
    wc_Sha512* sha = &drbg->sha512;
1060
#else
1061
434k
    wc_Sha512 sha[1];
1062
434k
#endif
1063
#if defined(WOLFSSL_SMALL_STACK_CACHE)
1064
    byte* digest = drbg->digest_scratch;
1065
#elif defined(WOLFSSL_SMALL_STACK)
1066
    byte* digest;
1067
#else
1068
#if defined(__GNUC__) && !defined(__clang__) && defined(__AVX512F__)
1069
    /* Use a jumbo alignment to work around a gcc compiler/optimizer bug that
1070
     * assumes AVX512 alignment in an object sized correctly for AVX512 passed
1071
     * to builtin memcpy(), which promptly crashes if not thus aligned.
1072
     */
1073
    byte digest[WC_SHA512_DIGEST_SIZE] WOLFSSL_ALIGN(WC_SHA512_DIGEST_SIZE);
1074
#else
1075
    byte digest[WC_SHA512_DIGEST_SIZE];
1076
#endif
1077
#endif
1078
1079
434k
    if (drbg == NULL) {
1080
0
        return DRBG_FAILURE;
1081
0
    }
1082
1083
434k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1084
434k
    digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
1085
434k
        DYNAMIC_TYPE_DIGEST);
1086
434k
    if (digest == NULL)
1087
144
        return DRBG_FAILURE;
1088
434k
#endif
1089
1090
434k
#ifdef LITTLE_ENDIAN_ORDER
1091
434k
    bits = ByteReverseWord32(bits);
1092
434k
#endif
1093
434k
    len = (outSz / OUTPUT_BLOCK_LEN_SHA512)
1094
434k
        + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0);
1095
1096
434k
    ctr = 1;
1097
1.30M
    for (i = 0; i < len; i++) {
1098
868k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1099
868k
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1100
868k
        ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
1101
    #else
1102
        ret = wc_InitSha512(sha);
1103
    #endif
1104
868k
        if (ret != 0)
1105
0
            break;
1106
868k
#endif
1107
868k
        ret = wc_Sha512Update(sha, &ctr, sizeof(ctr));
1108
868k
        if (ret == 0) {
1109
868k
            ctr++;
1110
868k
            ret = wc_Sha512Update(sha, (byte*)&bits, sizeof(bits));
1111
868k
        }
1112
1113
868k
        if (ret == 0) {
1114
            /* churning V is the only string that doesn't have the type added */
1115
868k
            if (type != drbgInitV)
1116
434k
                ret = wc_Sha512Update(sha, &type, sizeof(type));
1117
868k
        }
1118
868k
        if (ret == 0)
1119
868k
            ret = wc_Sha512Update(sha, inA, inASz);
1120
868k
        if (ret == 0) {
1121
868k
            if (inB != NULL && inBSz > 0)
1122
0
                ret = wc_Sha512Update(sha, inB, inBSz);
1123
868k
        }
1124
868k
        if (ret == 0) {
1125
868k
            if (inC != NULL && inCSz > 0)
1126
0
                ret = wc_Sha512Update(sha, inC, inCSz);
1127
868k
        }
1128
868k
        if (ret == 0)
1129
868k
            ret = wc_Sha512Final(sha, digest);
1130
1131
868k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1132
868k
        wc_Sha512Free(sha);
1133
868k
#endif
1134
868k
        if (ret == 0) {
1135
844k
            if (outSz > OUTPUT_BLOCK_LEN_SHA512) {
1136
434k
                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512);
1137
434k
                outSz -= OUTPUT_BLOCK_LEN_SHA512;
1138
434k
                out += OUTPUT_BLOCK_LEN_SHA512;
1139
434k
            }
1140
410k
            else {
1141
410k
                XMEMCPY(out, digest, outSz);
1142
410k
            }
1143
844k
        }
1144
868k
    }
1145
1146
434k
    ForceZero(digest, WC_SHA512_DIGEST_SIZE);
1147
1148
434k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1149
434k
    XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1150
434k
#endif
1151
1152
#ifdef WC_VERBOSE_RNG
1153
    if (ret != 0)
1154
        WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __func__,
1155
                             ret);
1156
#endif
1157
1158
434k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1159
434k
}
1160
1161
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1162
static int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg, const byte* seed,
1163
                               word32 seedSz,
1164
                               const byte* additional, word32 additionalSz)
1165
0
{
1166
0
    int ret;
1167
0
    WC_DECLARE_VAR(newV, byte, DRBG_SHA512_SEED_LEN, 0);
1168
1169
0
    if (drbg == NULL) {
1170
0
        return DRBG_FAILURE;
1171
0
    }
1172
1173
#ifdef WOLFSSL_SMALL_STACK_CACHE
1174
    newV = drbg->seed_scratch;
1175
#else
1176
0
    WC_ALLOC_VAR_EX(newV, byte, DRBG_SHA512_SEED_LEN, drbg->heap,
1177
0
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
1178
0
#endif
1179
0
    XMEMSET(newV, 0, DRBG_SHA512_SEED_LEN);
1180
1181
0
    ret = Hash512_df(drbg, newV, DRBG_SHA512_SEED_LEN, drbgReseed,
1182
0
                drbg->V, sizeof(drbg->V), seed, seedSz,
1183
0
                additional, additionalSz);
1184
0
    if (ret == DRBG_SUCCESS) {
1185
0
        XMEMCPY(drbg->V, newV, sizeof(drbg->V));
1186
1187
0
        ret = Hash512_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
1188
0
                                    sizeof(drbg->V), NULL, 0,
1189
0
                                    NULL, 0);
1190
0
    }
1191
0
    if (ret == DRBG_SUCCESS) {
1192
0
        drbg->reseedCtr = 1;
1193
0
    }
1194
1195
0
    ForceZero(newV, DRBG_SHA512_SEED_LEN);
1196
1197
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1198
0
    WC_FREE_VAR_EX(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1199
0
#endif
1200
1201
0
    return ret;
1202
0
}
1203
1204
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1205
static int Hash512_gen(DRBG_SHA512_internal* drbg, byte* out, word32 outSz,
1206
                       const byte* V)
1207
453k
{
1208
453k
    int ret = DRBG_FAILURE;
1209
453k
    word32 i;
1210
453k
    word32 len;
1211
#if defined(WOLFSSL_SMALL_STACK_CACHE)
1212
    wc_Sha512* sha = &drbg->sha512;
1213
    byte* data = drbg->seed_scratch;
1214
    byte* digest = drbg->digest_scratch;
1215
#elif defined(WOLFSSL_SMALL_STACK)
1216
    wc_Sha512 sha[1];
1217
453k
    byte* data = NULL;
1218
453k
    byte* digest = NULL;
1219
#else
1220
    wc_Sha512 sha[1];
1221
    byte data[DRBG_SHA512_SEED_LEN];
1222
    byte digest[WC_SHA512_DIGEST_SIZE];
1223
#endif
1224
1225
453k
    if (drbg == NULL) {
1226
0
        return DRBG_FAILURE;
1227
0
    }
1228
1229
453k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1230
453k
    data = (byte*)XMALLOC(DRBG_SHA512_SEED_LEN, drbg->heap,
1231
453k
        DYNAMIC_TYPE_TMP_BUFFER);
1232
453k
    digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
1233
453k
        DYNAMIC_TYPE_DIGEST);
1234
453k
    if (data == NULL || digest == NULL) {
1235
2.18k
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1236
2.18k
        XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1237
2.18k
        return DRBG_FAILURE;
1238
2.18k
    }
1239
450k
#endif
1240
1241
    /* Special case: outSz is 0 and out is NULL. Generate a block to save for
1242
     * the continuous test. */
1243
450k
    if (outSz == 0) {
1244
0
        outSz = 1;
1245
0
    }
1246
1247
450k
    len = (outSz / OUTPUT_BLOCK_LEN_SHA512)
1248
450k
        + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0);
1249
1250
450k
    XMEMCPY(data, V, DRBG_SHA512_SEED_LEN);
1251
1.59M
    for (i = 0; i < len; i++) {
1252
1.14M
#ifndef WOLFSSL_SMALL_STACK_CACHE
1253
1.14M
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1254
1.14M
        ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
1255
    #else
1256
        ret = wc_InitSha512(sha);
1257
    #endif
1258
1.14M
        if (ret == 0)
1259
1.14M
#endif
1260
1.14M
            ret = wc_Sha512Update(sha, data, DRBG_SHA512_SEED_LEN);
1261
1.14M
        if (ret == 0)
1262
1.14M
            ret = wc_Sha512Final(sha, digest);
1263
1.14M
#ifndef WOLFSSL_SMALL_STACK_CACHE
1264
1.14M
        wc_Sha512Free(sha);
1265
1.14M
#endif
1266
1267
1.14M
        if (ret == 0) {
1268
1.14M
            if (out != NULL && outSz != 0) {
1269
1.14M
                if (outSz >= OUTPUT_BLOCK_LEN_SHA512) {
1270
927k
                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512);
1271
927k
                    outSz -= OUTPUT_BLOCK_LEN_SHA512;
1272
927k
                    out += OUTPUT_BLOCK_LEN_SHA512;
1273
927k
                    array_add_one(data, DRBG_SHA512_SEED_LEN);
1274
927k
                }
1275
220k
                else {
1276
220k
                    XMEMCPY(out, digest, outSz);
1277
220k
                    outSz = 0;
1278
220k
                }
1279
1.14M
            }
1280
1.14M
        }
1281
501
        else {
1282
501
            break;
1283
501
        }
1284
1.14M
    }
1285
450k
    ForceZero(data, DRBG_SHA512_SEED_LEN);
1286
1287
450k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1288
450k
    WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1289
450k
    WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1290
450k
#endif
1291
1292
450k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1293
453k
}
1294
1295
/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
1296
static int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg, byte* out,
1297
                                 word32 outSz,
1298
                                 const byte* additional, word32 additionalSz)
1299
456k
{
1300
456k
    int ret;
1301
#ifdef WOLFSSL_SMALL_STACK_CACHE
1302
    wc_Sha512* sha = &drbg->sha512;
1303
#else
1304
456k
    wc_Sha512 sha[1];
1305
456k
#endif
1306
456k
    byte type;
1307
456k
    word64 reseedCtr;
1308
1309
456k
    if (drbg == NULL) {
1310
0
        return DRBG_FAILURE;
1311
0
    }
1312
1313
456k
    if (drbg->reseedCtr >= WC_RESEED_INTERVAL) {
1314
0
        return DRBG_NEED_RESEED;
1315
0
    }
1316
456k
    else {
1317
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
1318
        byte* digest = drbg->digest_scratch;
1319
    #elif defined(WOLFSSL_SMALL_STACK)
1320
456k
        byte* digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
1321
456k
            DYNAMIC_TYPE_DIGEST);
1322
456k
        if (digest == NULL)
1323
3.87k
            return DRBG_FAILURE;
1324
    #else
1325
        byte digest[WC_SHA512_DIGEST_SIZE];
1326
    #endif
1327
1328
453k
        type = drbgGenerateH;
1329
453k
        reseedCtr = drbg->reseedCtr;
1330
1331
        /* SP 800-90A Section 10.1.1.4 step 2:
1332
         * If additional_input != Null, w = Hash(0x02 || V || additional_input),
1333
         * V = (V + w) mod 2^seedlen */
1334
453k
        ret = DRBG_SUCCESS;
1335
453k
        if (additional != NULL && additionalSz > 0) {
1336
0
            byte addType = drbgGenerateW; /* 0x02 */
1337
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1338
0
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1339
0
            ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
1340
        #else
1341
            ret = wc_InitSha512(sha);
1342
        #endif
1343
0
            if (ret == 0)
1344
0
#endif
1345
0
                ret = wc_Sha512Update(sha, &addType, sizeof(addType));
1346
0
            if (ret == 0)
1347
0
                ret = wc_Sha512Update(sha, drbg->V, sizeof(drbg->V));
1348
0
            if (ret == 0)
1349
0
                ret = wc_Sha512Update(sha, additional, additionalSz);
1350
0
            if (ret == 0)
1351
0
                ret = wc_Sha512Final(sha, digest);
1352
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1353
0
            wc_Sha512Free(sha);
1354
0
#endif
1355
0
            if (ret == 0)
1356
0
                array_add(drbg->V, sizeof(drbg->V), digest,
1357
0
                          WC_SHA512_DIGEST_SIZE);
1358
0
        }
1359
1360
453k
        if (ret == 0)
1361
453k
            ret = Hash512_gen(drbg, out, outSz, drbg->V);
1362
453k
        if (ret == DRBG_SUCCESS) {
1363
450k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1364
450k
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1365
450k
            ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
1366
        #else
1367
            ret = wc_InitSha512(sha);
1368
        #endif
1369
450k
            if (ret == 0)
1370
450k
#endif
1371
450k
                ret = wc_Sha512Update(sha, &type, sizeof(type));
1372
450k
            if (ret == 0)
1373
450k
                ret = wc_Sha512Update(sha, drbg->V, sizeof(drbg->V));
1374
450k
            if (ret == 0)
1375
450k
                ret = wc_Sha512Final(sha, digest);
1376
1377
450k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1378
450k
            wc_Sha512Free(sha);
1379
450k
#endif
1380
1381
450k
            if (ret == 0) {
1382
449k
                array_add(drbg->V, sizeof(drbg->V), digest,
1383
449k
                          WC_SHA512_DIGEST_SIZE);
1384
449k
                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
1385
449k
            #ifdef LITTLE_ENDIAN_ORDER
1386
449k
                reseedCtr = ByteReverseWord64(reseedCtr);
1387
449k
            #endif
1388
449k
                array_add(drbg->V, sizeof(drbg->V),
1389
449k
                                          (byte*)&reseedCtr, sizeof(reseedCtr));
1390
449k
                ret = DRBG_SUCCESS;
1391
449k
            }
1392
450k
            drbg->reseedCtr++;
1393
450k
        }
1394
453k
        ForceZero(digest, WC_SHA512_DIGEST_SIZE);
1395
453k
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1396
453k
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1397
453k
    #endif
1398
453k
    }
1399
1400
453k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1401
456k
}
1402
1403
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1404
static int Hash512_DRBG_Init(DRBG_SHA512_internal* drbg, const byte* seed,
1405
                             word32 seedSz, const byte* nonce, word32 nonceSz,
1406
                             const byte* perso, word32 persoSz)
1407
238k
{
1408
238k
    if (seed == NULL)
1409
0
        return DRBG_FAILURE;
1410
1411
238k
    if (Hash512_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
1412
238k
                                              nonce, nonceSz,
1413
238k
                                              perso, persoSz) == DRBG_SUCCESS &&
1414
238k
        Hash512_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
1415
238k
                                    sizeof(drbg->V), NULL, 0,
1416
238k
                                    NULL, 0) == DRBG_SUCCESS) {
1417
1418
238k
        drbg->reseedCtr = 1;
1419
238k
        return DRBG_SUCCESS;
1420
238k
    }
1421
300
    else {
1422
300
        return DRBG_FAILURE;
1423
300
    }
1424
238k
}
1425
1426
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1427
static int Hash512_DRBG_Instantiate(DRBG_SHA512_internal* drbg,
1428
                                    const byte* seed, word32 seedSz,
1429
                                    const byte* nonce, word32 nonceSz,
1430
                                    const byte* perso, word32 persoSz,
1431
                                    void* heap, int devId)
1432
238k
{
1433
238k
    int ret = DRBG_FAILURE;
1434
1435
238k
    XMEMSET(drbg, 0, sizeof(DRBG_SHA512_internal));
1436
238k
    drbg->heap = heap;
1437
238k
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1438
238k
    drbg->devId = devId;
1439
#else
1440
    (void)devId;
1441
#endif
1442
1443
#ifdef WOLFSSL_SMALL_STACK_CACHE
1444
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1445
        ret = wc_InitSha512_ex(&drbg->sha512, drbg->heap, drbg->devId);
1446
    #else
1447
        ret = wc_InitSha512(&drbg->sha512);
1448
    #endif
1449
    if (ret != 0)
1450
        return ret;
1451
#endif
1452
1453
238k
    if (seed != NULL)
1454
238k
        ret = Hash512_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz,
1455
238k
                                perso, persoSz);
1456
238k
    return ret;
1457
238k
}
1458
1459
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1460
static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg)
1461
238k
{
1462
238k
    word32 i;
1463
238k
    int    compareSum = 0;
1464
238k
    byte*  compareDrbg = (byte*)drbg;
1465
1466
#ifdef WOLFSSL_SMALL_STACK_CACHE
1467
    wc_Sha512Free(&drbg->sha512);
1468
#endif
1469
1470
238k
    ForceZero(drbg, sizeof(DRBG_SHA512_internal));
1471
1472
59.3M
    for (i = 0; i < sizeof(DRBG_SHA512_internal); i++) {
1473
59.0M
        compareSum |= compareDrbg[i] ^ 0;
1474
59.0M
    }
1475
1476
238k
    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1477
238k
}
1478
1479
#endif /* WOLFSSL_DRBG_SHA512 */
1480
1481
1482
/* FIPS 140-3 IG 10.3.A / SP800-90B Health Tests for Seed Data
1483
 *
1484
 * These tests replace the older FIPS 140-2 Continuous Random Number Generator
1485
 * Test (CRNGT) with more mathematically robust statistical tests per
1486
 * ISO 19790 / SP800-90B requirements.
1487
 *
1488
 * When HAVE_ENTROPY_MEMUSE is defined, the wolfentropy.c jitter-based TRNG
1489
 * performs another set of these health tests, but those are on the noise not
1490
 * the conditioned output so we still need to retest here even in that case
1491
 * to evaluate the conditioned output for the same behavior. These tests ensure
1492
 * the seed data meets basic entropy requirements regardless of the source.
1493
 */
1494
1495
/* SP800-90B 4.4.1 - Repetition Count Test
1496
 * Detects if the noise source becomes "stuck" producing repeated output.
1497
 *
1498
 * C = 1 + ceil(-log2(alpha) / H)
1499
 * For alpha = 2^-30 (false positive probability) and H = 1 (min entropy):
1500
 * C = 1 + ceil(30 / 1) = 31
1501
 */
1502
#ifndef WC_RNG_SEED_RCT_CUTOFF
1503
5.52M
    #define WC_RNG_SEED_RCT_CUTOFF 31
1504
#endif
1505
1506
/* SP800-90B 4.4.2 - Adaptive Proportion Test
1507
 * Monitors if a particular sample value appears too frequently within a
1508
 * window of samples, indicating loss of entropy.
1509
 *
1510
 * Window size W = 512 for non-binary alphabet (byte values 0-255)
1511
 * C = 1 + CRITBINOM(W, 2^(-H), 1-alpha)
1512
 * For alpha = 2^-30 and H = 1, W = 512:
1513
 * C = 1 + CRITBINOM(512, 0.5, 1-2^-30) = 325
1514
 */
1515
#ifndef WC_RNG_SEED_APT_WINDOW
1516
108k
    #define WC_RNG_SEED_APT_WINDOW 512
1517
#endif
1518
#ifndef WC_RNG_SEED_APT_CUTOFF
1519
27.7M
    #define WC_RNG_SEED_APT_CUTOFF 325
1520
#endif
1521
1522
int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
1523
108k
{
1524
108k
    int ret = 0;
1525
1526
108k
    word32 i;
1527
108k
    int rctFailed = 0;
1528
108k
    int aptFailed = 0;
1529
1530
108k
    if (seed == NULL || seedSz < SEED_BLOCK_SZ) {
1531
0
        return BAD_FUNC_ARG;
1532
0
    }
1533
1534
    /* SP800-90B 4.4.1 - Repetition Count Test (RCT)
1535
     * Check for consecutive identical bytes that would indicate a stuck
1536
     * entropy source. Fail if we see WC_RNG_SEED_RCT_CUTOFF or more
1537
     * consecutive identical values.
1538
     *
1539
     * Constant-time implementation: always process full seed, accumulate
1540
     * failure status without early exit to prevent timing side-channels.
1541
     */
1542
108k
    {
1543
108k
        int repCount = 1;
1544
108k
        byte prevByte = seed[0];
1545
1546
5.63M
        for (i = 1; i < seedSz; i++) {
1547
            /* Constant-time: always evaluate both branches effects */
1548
5.52M
            int match = (seed[i] == prevByte);
1549
            /* If match, increment count, if not, reset to 1 */
1550
5.52M
            repCount = (match * (repCount + 1)) + (!match * 1);
1551
            /* Update prevByte only when not matching (new value) */
1552
5.52M
            prevByte = (byte) ((match * prevByte) + (!match * seed[i]));
1553
            /* Accumulate failure flag - once set, stays set */
1554
5.52M
            rctFailed |= (repCount >= WC_RNG_SEED_RCT_CUTOFF);
1555
5.52M
        }
1556
108k
    }
1557
1558
    /* SP800-90B 4.4.2 - Adaptive Proportion Test (APT)
1559
     * Check that no single byte value appears too frequently within
1560
     * a sliding window. This detects bias in the entropy source.
1561
     *
1562
     * For seeds smaller than the window size, we test the entire seed.
1563
     * For larger seeds, we use a sliding window approach.
1564
     *
1565
     * Constant-time implementation: always process full seed and check
1566
     * all counts to prevent timing side-channels.
1567
     */
1568
108k
    {
1569
108k
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1570
108k
        word16* byteCounts = NULL;
1571
    #else
1572
        word16 byteCounts[MAX_ENTROPY_BITS];
1573
    #endif
1574
108k
        word32 windowSize = min(seedSz, (word32)WC_RNG_SEED_APT_WINDOW);
1575
108k
        word32 windowStart = 0;
1576
108k
        word32 newIdx;
1577
1578
108k
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1579
108k
        byteCounts = (word16*)XMALLOC(MAX_ENTROPY_BITS * sizeof(word16), NULL,
1580
108k
                                      DYNAMIC_TYPE_TMP_BUFFER);
1581
108k
        if (byteCounts == NULL)
1582
8
            return MEMORY_E;
1583
108k
    #endif
1584
108k
        XMEMSET(byteCounts, 0, MAX_ENTROPY_BITS * sizeof(word16));
1585
1586
        /* Initialize counts for first window */
1587
5.74M
        for (i = 0; i < windowSize; i++) {
1588
5.63M
            byteCounts[seed[i]]++;
1589
5.63M
        }
1590
1591
        /* Check first window - scan all 256 counts */
1592
27.8M
        for (i = 0; i < MAX_ENTROPY_BITS; i++) {
1593
27.7M
            aptFailed |= (byteCounts[i] >= WC_RNG_SEED_APT_CUTOFF);
1594
27.7M
        }
1595
1596
        /* Slide window through remaining seed data */
1597
108k
        while ((windowStart + windowSize) < seedSz) {
1598
            /* Remove byte leaving the window */
1599
0
            byteCounts[seed[windowStart]]--;
1600
0
            windowStart++;
1601
1602
            /* Add byte entering the window */
1603
0
            newIdx = windowStart + windowSize - 1;
1604
0
            byteCounts[seed[newIdx]]++;
1605
1606
            /* Accumulate failure flag for new byte's count */
1607
0
            aptFailed |= (byteCounts[seed[newIdx]] >= WC_RNG_SEED_APT_CUTOFF);
1608
0
        }
1609
1610
108k
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1611
108k
        XFREE(byteCounts, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1612
108k
    #endif
1613
108k
    }
1614
1615
    /* Set return code based on accumulated failure flags */
1616
108k
    if (rctFailed) {
1617
0
        ret = ENTROPY_RT_E;
1618
0
    }
1619
108k
    else if (aptFailed) {
1620
0
        ret = ENTROPY_APT_E;
1621
0
    }
1622
1623
108k
    return ret;
1624
108k
}
1625
/* Runtime DRBG disable/enable API -- only available in non-selftest and
1626
 * FIPS v7+ builds (older FIPS/selftest random.c doesn't have these) */
1627
#if !defined(HAVE_SELFTEST) && \
1628
    (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
1629
#ifndef NO_SHA256
1630
int wc_Sha256Drbg_Disable(void)
1631
0
{
1632
0
    int ret;
1633
0
#ifdef WOLFSSL_DRBG_SHA512
1634
0
    ret = LockDrbgState();
1635
0
    if (ret != 0)
1636
0
        return ret;
1637
0
    if (sha512DrbgDisabled) {
1638
0
        UnlockDrbgState();
1639
0
        return BAD_STATE_E;  /* can't disable both */
1640
0
    }
1641
0
    sha256DrbgDisabled = 1;
1642
0
    UnlockDrbgState();
1643
0
    return 0;
1644
#else
1645
    (void)ret;
1646
    return NOT_COMPILED_IN;
1647
#endif
1648
0
}
1649
1650
int wc_Sha256Drbg_Enable(void)
1651
0
{
1652
0
    int ret = LockDrbgState();
1653
0
    if (ret != 0)
1654
0
        return ret;
1655
0
    sha256DrbgDisabled = 0;
1656
0
    UnlockDrbgState();
1657
0
    return 0;
1658
0
}
1659
1660
int wc_Sha256Drbg_IsDisabled(void)
1661
0
{
1662
0
    int val;
1663
0
    if (LockDrbgState() != 0)
1664
0
        return 1; /* fail-safe: report disabled on mutex error */
1665
0
    val = sha256DrbgDisabled;
1666
0
    UnlockDrbgState();
1667
0
    return val;
1668
0
}
1669
#else
1670
/* When SHA-256 is not compiled in, these are stubs */
1671
int wc_Sha256Drbg_Disable(void) { return NOT_COMPILED_IN; }
1672
int wc_Sha256Drbg_Enable(void) { return 0; }
1673
int wc_Sha256Drbg_IsDisabled(void) { return 1; } /* always disabled */
1674
#endif /* !NO_SHA256 */
1675
1676
#ifdef WOLFSSL_DRBG_SHA512
1677
int wc_Sha512Drbg_Disable(void)
1678
0
{
1679
0
    int ret = LockDrbgState();
1680
0
    if (ret != 0)
1681
0
        return ret;
1682
0
#ifndef NO_SHA256
1683
0
    if (sha256DrbgDisabled) {
1684
0
        UnlockDrbgState();
1685
0
        return BAD_STATE_E;  /* can't disable both */
1686
0
    }
1687
0
#endif
1688
0
    sha512DrbgDisabled = 1;
1689
0
    UnlockDrbgState();
1690
0
    return 0;
1691
0
}
1692
1693
int wc_Sha512Drbg_Enable(void)
1694
0
{
1695
0
    int ret = LockDrbgState();
1696
0
    if (ret != 0)
1697
0
        return ret;
1698
0
    sha512DrbgDisabled = 0;
1699
0
    UnlockDrbgState();
1700
0
    return 0;
1701
0
}
1702
1703
int wc_Sha512Drbg_IsDisabled(void)
1704
0
{
1705
0
    int val;
1706
0
    if (LockDrbgState() != 0)
1707
0
        return 1; /* fail-safe: report disabled on mutex error */
1708
0
    val = sha512DrbgDisabled;
1709
0
    UnlockDrbgState();
1710
0
    return val;
1711
0
}
1712
#endif /* WOLFSSL_DRBG_SHA512 */
1713
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
1714
#endif /* HAVE_HASHDRBG */
1715
/* End NIST DRBG Code */
1716
1717
1718
static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
1719
                    void* heap, int devId)
1720
115k
{
1721
115k
    int ret = 0;
1722
115k
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
1723
#if !defined(HAVE_FIPS) && defined(WOLFSSL_RNG_USE_FULL_SEED)
1724
    word32 seedSz = SEED_SZ;
1725
#else
1726
115k
    word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
1727
115k
#endif
1728
115k
    WC_DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
1729
#ifdef WOLFSSL_SMALL_STACK_CACHE
1730
    int drbg_scratch_instantiated = 0;
1731
#endif
1732
115k
#endif
1733
1734
115k
    (void)nonce;
1735
115k
    (void)nonceSz;
1736
1737
115k
    if (rng == NULL)
1738
0
        return BAD_FUNC_ARG;
1739
115k
    if (nonce == NULL && nonceSz != 0)
1740
0
        return BAD_FUNC_ARG;
1741
1742
115k
    XMEMSET(rng, 0, sizeof(*rng));
1743
1744
#ifdef WOLFSSL_HEAP_TEST
1745
    rng->heap = (void*)WOLFSSL_HEAP_TEST;
1746
    (void)heap;
1747
#else
1748
115k
    rng->heap = heap;
1749
115k
#endif
1750
115k
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
1751
115k
    rng->pid = getpid();
1752
115k
#endif
1753
115k
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1754
115k
    rng->devId = devId;
1755
115k
    #if defined(WOLF_CRYPTO_CB)
1756
115k
        rng->seed.devId = devId;
1757
115k
    #endif
1758
#else
1759
    (void)devId;
1760
#endif
1761
1762
115k
#ifdef HAVE_HASHDRBG
1763
    /* init the DBRG to known values */
1764
115k
#ifndef NO_SHA256
1765
115k
    rng->drbg = NULL;
1766
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1767
    rng->drbg_scratch = NULL;
1768
    #endif
1769
115k
#endif /* !NO_SHA256 */
1770
115k
#ifdef WOLFSSL_DRBG_SHA512
1771
115k
    rng->drbg512 = NULL;
1772
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1773
    rng->drbg512_scratch = NULL;
1774
    rng->health_check_scratch_512 = NULL;
1775
    #endif
1776
115k
#endif /* WOLFSSL_DRBG_SHA512 */
1777
#ifdef WOLFSSL_SMALL_STACK_CACHE
1778
    rng->newSeed_buf = NULL;
1779
    #ifndef NO_SHA256
1780
    rng->health_check_scratch = NULL;
1781
    #endif /* !NO_SHA256 */
1782
#endif /* WOLFSSL_SMALL_STACK_CACHE */
1783
115k
    rng->status = DRBG_NOT_INIT;
1784
1785
    /* Select DRBG type: prefer SHA-512 unless disabled or not compiled.
1786
     * Hold the mutex for a consistent snapshot of both disable flags. */
1787
115k
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
1788
115k
    ret = LockDrbgState();
1789
115k
    if (ret != 0)
1790
0
        return ret;
1791
115k
    #ifdef WOLFSSL_DRBG_SHA512
1792
115k
    if (!sha512DrbgDisabled)
1793
115k
        rng->drbgType = WC_DRBG_SHA512;
1794
0
    else
1795
0
    #endif /* WOLFSSL_DRBG_SHA512 */
1796
0
    #ifndef NO_SHA256
1797
0
    if (!sha256DrbgDisabled)
1798
0
        rng->drbgType = WC_DRBG_SHA256;
1799
0
    else
1800
0
    #endif /* !NO_SHA256 */
1801
0
    {
1802
0
        UnlockDrbgState();
1803
0
        return BAD_STATE_E; /* no DRBG available */
1804
0
    }
1805
115k
    UnlockDrbgState();
1806
#else
1807
    rng->drbgType = WC_DRBG_SHA256;
1808
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
1809
115k
#endif /* HAVE_HASHDRBG */
1810
1811
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) || \
1812
    defined(HAVE_AMD_RDSEED)
1813
    /* init the intel RD seed and/or rand */
1814
    wc_InitRng_IntelRD();
1815
#endif
1816
1817
    /* configure async RNG source if available */
1818
#ifdef WOLFSSL_ASYNC_CRYPT
1819
    ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
1820
                                                        rng->heap, rng->devId);
1821
    if (ret != 0) {
1822
    #ifdef HAVE_HASHDRBG
1823
        rng->status = DRBG_OK;
1824
    #endif
1825
        return ret;
1826
    }
1827
#endif
1828
1829
#ifdef HAVE_INTEL_RDRAND
1830
    /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
1831
    if (IS_INTEL_RDRAND(intel_flags)) {
1832
    #ifdef HAVE_HASHDRBG
1833
        rng->status = DRBG_OK;
1834
    #endif
1835
        return 0;
1836
    }
1837
#endif
1838
1839
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
1840
    ret = wc_VersalTrngInit(nonce, nonceSz);
1841
    if (ret) {
1842
    #ifdef HAVE_HASHDRBG
1843
        rng->status = DRBG_OK;
1844
    #endif
1845
        return ret;
1846
    }
1847
#endif
1848
1849
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && !defined(USE_WINDOWS_API)
1850
    if (!rng->seed.seedFdOpen)
1851
        rng->seed.fd = XBADFD;
1852
#endif
1853
1854
#ifdef CUSTOM_RAND_GENERATE_BLOCK
1855
    ret = 0; /* success */
1856
#else
1857
1858
 /* not CUSTOM_RAND_GENERATE_BLOCK follows */
1859
115k
#ifdef HAVE_HASHDRBG
1860
115k
    if (nonceSz == 0) {
1861
115k
        seedSz = MAX_SEED_SZ;
1862
115k
    }
1863
1864
115k
#ifndef NO_SHA256
1865
115k
    if (rng->drbgType == WC_DRBG_SHA256) {
1866
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1867
0
        rng->drbg =
1868
0
            (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap,
1869
0
                                  DYNAMIC_TYPE_RNG);
1870
0
        if (rng->drbg == NULL) {
1871
        #if defined(DEBUG_WOLFSSL)
1872
            WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
1873
                           sizeof(DRBG_internal));
1874
        #endif
1875
0
            ret = MEMORY_E;
1876
0
            rng->status = DRBG_FAILED;
1877
0
        }
1878
    #else
1879
        rng->drbg = (struct DRBG*)&rng->drbg_data;
1880
    #endif /* WOLFSSL_NO_MALLOC or WOLFSSL_STATIC_MEMORY */
1881
1882
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1883
        if (ret == 0) {
1884
            rng->drbg_scratch =
1885
                (DRBG_internal *)XMALLOC(sizeof(DRBG_internal), rng->heap,
1886
                                         DYNAMIC_TYPE_RNG);
1887
            if (rng->drbg_scratch == NULL) {
1888
    #if defined(DEBUG_WOLFSSL)
1889
                WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
1890
                               sizeof(DRBG_internal));
1891
    #endif
1892
                ret = MEMORY_E;
1893
                rng->status = DRBG_FAILED;
1894
            }
1895
        }
1896
1897
        if (ret == 0) {
1898
            ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch,
1899
                        NULL, 0, NULL, 0, NULL, 0, rng->heap, devId);
1900
            if (ret == 0)
1901
                drbg_scratch_instantiated = 1;
1902
        }
1903
1904
        if (ret == 0) {
1905
            rng->health_check_scratch =
1906
                (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, rng->heap,
1907
                                DYNAMIC_TYPE_TMP_BUFFER);
1908
            if (rng->health_check_scratch == NULL) {
1909
                ret = MEMORY_E;
1910
                rng->status = DRBG_FAILED;
1911
            }
1912
        }
1913
    #endif /* WOLFSSL_SMALL_STACK_CACHE */
1914
0
    } /* WC_DRBG_SHA256 */
1915
115k
#endif /* !NO_SHA256 */
1916
1917
115k
#ifdef WOLFSSL_DRBG_SHA512
1918
115k
    if (rng->drbgType == WC_DRBG_SHA512) {
1919
115k
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1920
115k
        rng->drbg512 =
1921
115k
            (struct DRBG_SHA512*)XMALLOC(sizeof(DRBG_SHA512_internal),
1922
115k
                                         rng->heap, DYNAMIC_TYPE_RNG);
1923
115k
        if (rng->drbg512 == NULL) {
1924
        #if defined(DEBUG_WOLFSSL)
1925
            WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
1926
                           sizeof(DRBG_SHA512_internal));
1927
        #endif
1928
6.67k
            ret = MEMORY_E;
1929
6.67k
            rng->status = DRBG_FAILED;
1930
6.67k
        }
1931
    #else
1932
        rng->drbg512 = (struct DRBG_SHA512*)&rng->drbg512_data;
1933
    #endif
1934
1935
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1936
        if (ret == 0) {
1937
            rng->drbg512_scratch =
1938
                (DRBG_SHA512_internal *)XMALLOC(sizeof(DRBG_SHA512_internal),
1939
                    rng->heap, DYNAMIC_TYPE_RNG);
1940
            if (rng->drbg512_scratch == NULL) {
1941
                ret = MEMORY_E;
1942
                rng->status = DRBG_FAILED;
1943
            }
1944
        }
1945
1946
        if (ret == 0) {
1947
            ret = Hash512_DRBG_Instantiate(rng->drbg512_scratch,
1948
                        NULL, 0, NULL, 0, NULL, 0, rng->heap, devId);
1949
            if (ret == 0)
1950
                drbg_scratch_instantiated = 1;
1951
        }
1952
1953
        if (ret == 0) {
1954
            rng->health_check_scratch_512 =
1955
                (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE_SHA512, rng->heap,
1956
                                DYNAMIC_TYPE_TMP_BUFFER);
1957
            if (rng->health_check_scratch_512 == NULL) {
1958
                ret = MEMORY_E;
1959
                rng->status = DRBG_FAILED;
1960
            }
1961
        }
1962
    #endif /* WOLFSSL_SMALL_STACK_CACHE */
1963
115k
    } /* WC_DRBG_SHA512 */
1964
115k
#endif /* WOLFSSL_DRBG_SHA512 */
1965
1966
    /* newSeed_buf shared by both DRBG types for PollAndReSeed */
1967
#ifdef WOLFSSL_SMALL_STACK_CACHE
1968
    if (ret == 0) {
1969
        rng->newSeed_buf = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
1970
                           DYNAMIC_TYPE_SEED);
1971
        if (rng->newSeed_buf == NULL) {
1972
            ret = MEMORY_E;
1973
            rng->status = DRBG_FAILED;
1974
        }
1975
    }
1976
#endif /* WOLFSSL_SMALL_STACK_CACHE */
1977
1978
115k
    if (ret == 0) {
1979
109k
        ret = wc_RNG_HealthTestLocal(rng, 0, rng->heap, devId);
1980
109k
        if (ret != 0) {
1981
        #if defined(DEBUG_WOLFSSL)
1982
            WOLFSSL_MSG_EX("wc_RNG_HealthTestLocal failed err = %d", ret);
1983
        #endif
1984
967
            ret = DRBG_CONT_FAILURE;
1985
967
        }
1986
109k
    }
1987
1988
115k
    #ifdef WOLFSSL_SMALL_STACK
1989
115k
    if (ret == 0) {
1990
108k
        WC_ALLOC_VAR_EX(seed, byte, MAX_SEED_SZ, rng->heap, DYNAMIC_TYPE_SEED, WC_DO_NOTHING);
1991
108k
        if (seed == NULL) {
1992
8
            ret = MEMORY_E;
1993
8
            rng->status = DRBG_FAILED;
1994
8
        }
1995
108k
    }
1996
115k
    #endif
1997
1998
115k
    if (ret != 0) {
1999
#if defined(DEBUG_WOLFSSL)
2000
        WOLFSSL_MSG_EX("_InitRng failed. err = %d", ret);
2001
#endif
2002
7.64k
    }
2003
108k
    else {
2004
#ifdef WC_RNG_SEED_CB
2005
            if (seedCb == NULL) {
2006
                ret = DRBG_NO_SEED_CB;
2007
            }
2008
            else {
2009
                ret = seedCb(&rng->seed, seed, seedSz);
2010
                if (ret != 0) {
2011
#ifdef WC_VERBOSE_RNG
2012
                    WOLFSSL_DEBUG_PRINTF(
2013
                        "ERROR: seedCb in _InitRng() failed with err = %d",
2014
                        ret);
2015
#endif
2016
                    ret = DRBG_FAILURE;
2017
                }
2018
            }
2019
#else
2020
108k
            ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
2021
108k
#endif /* WC_RNG_SEED_CB */
2022
108k
            if (ret != 0) {
2023
    #if defined(DEBUG_WOLFSSL)
2024
                WOLFSSL_MSG_EX("Seed generation failed... %d", ret);
2025
    #elif defined(WC_VERBOSE_RNG)
2026
                WOLFSSL_DEBUG_PRINTF(
2027
                    "ERROR: wc_GenerateSeed() in _InitRng() failed with err %d",
2028
                    ret);
2029
    #endif
2030
0
                ret = DRBG_FAILURE;
2031
0
                rng->status = DRBG_FAILED;
2032
0
            }
2033
2034
108k
            if (ret == 0)
2035
108k
                ret = wc_RNG_TestSeed(seed, seedSz);
2036
    #if defined(DEBUG_WOLFSSL)
2037
            if (ret != 0) {
2038
                WOLFSSL_MSG_EX("wc_RNG_TestSeed failed... %d", ret);
2039
            }
2040
    #elif defined(WC_VERBOSE_RNG)
2041
            if (ret != DRBG_SUCCESS) {
2042
                WOLFSSL_DEBUG_PRINTF(
2043
                    "ERROR: wc_RNG_TestSeed() in _InitRng() returned err %d.",
2044
                    ret);
2045
            }
2046
    #endif
2047
2048
108k
            if (ret == DRBG_SUCCESS) {
2049
108k
#ifndef NO_SHA256
2050
108k
                if (rng->drbgType == WC_DRBG_SHA256)
2051
0
                    ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg,
2052
0
                #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED)
2053
0
                                seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
2054
                #else
2055
                                seed, seedSz,
2056
                #endif
2057
0
                                nonce, nonceSz, NULL, 0, rng->heap, devId);
2058
108k
#endif
2059
108k
#ifdef WOLFSSL_DRBG_SHA512
2060
108k
                if (rng->drbgType == WC_DRBG_SHA512)
2061
108k
                    ret = Hash512_DRBG_Instantiate(
2062
108k
                                (DRBG_SHA512_internal *)rng->drbg512,
2063
108k
                #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED)
2064
108k
                                seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
2065
                #else
2066
                                seed, seedSz,
2067
                #endif
2068
108k
                                nonce, nonceSz, NULL, 0, rng->heap, devId);
2069
108k
#endif
2070
108k
            }
2071
108k
    } /* ret == 0 */
2072
2073
115k
    #ifdef WOLFSSL_SMALL_STACK
2074
115k
    if (seed)
2075
108k
    #endif
2076
108k
    {
2077
108k
        ForceZero(seed, seedSz);
2078
108k
    }
2079
115k
    WC_FREE_VAR_EX(seed, rng->heap, DYNAMIC_TYPE_SEED);
2080
2081
115k
    if (ret != DRBG_SUCCESS) {
2082
7.71k
    #ifndef NO_SHA256
2083
7.71k
        if (rng->drbgType == WC_DRBG_SHA256) {
2084
0
        #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
2085
0
            XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
2086
0
        #endif
2087
0
            rng->drbg = NULL;
2088
        #ifdef WOLFSSL_SMALL_STACK_CACHE
2089
            XFREE(rng->health_check_scratch, rng->heap,
2090
                   DYNAMIC_TYPE_TMP_BUFFER);
2091
            rng->health_check_scratch = NULL;
2092
            if (drbg_scratch_instantiated)
2093
                (void)Hash_DRBG_Uninstantiate(
2094
                    (DRBG_internal *)rng->drbg_scratch);
2095
            XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
2096
            rng->drbg_scratch = NULL;
2097
        #endif
2098
0
        }
2099
7.71k
    #endif /* !NO_SHA256 */
2100
7.71k
    #ifdef WOLFSSL_DRBG_SHA512
2101
7.71k
        if (rng->drbgType == WC_DRBG_SHA512) {
2102
7.71k
        #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
2103
7.71k
            XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG);
2104
7.71k
        #endif
2105
7.71k
            rng->drbg512 = NULL;
2106
        #ifdef WOLFSSL_SMALL_STACK_CACHE
2107
            XFREE(rng->health_check_scratch_512, rng->heap,
2108
                   DYNAMIC_TYPE_TMP_BUFFER);
2109
            rng->health_check_scratch_512 = NULL;
2110
            if (drbg_scratch_instantiated)
2111
                (void)Hash512_DRBG_Uninstantiate(rng->drbg512_scratch);
2112
            XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG);
2113
            rng->drbg512_scratch = NULL;
2114
        #endif
2115
7.71k
        }
2116
7.71k
    #endif
2117
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2118
        XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED);
2119
        rng->newSeed_buf = NULL;
2120
    #endif
2121
7.71k
    }
2122
    /* else wc_RNG_HealthTestLocal was successful */
2123
2124
115k
    if (ret == DRBG_SUCCESS) {
2125
#ifdef WOLFSSL_CHECK_MEM_ZERO
2126
    #ifndef NO_SHA256
2127
        if (rng->drbgType == WC_DRBG_SHA256) {
2128
            struct DRBG_internal* drbg = (struct DRBG_internal*)rng->drbg;
2129
            wc_MemZero_Add("DRBG V", &drbg->V, sizeof(drbg->V));
2130
            wc_MemZero_Add("DRBG C", &drbg->C, sizeof(drbg->C));
2131
        }
2132
    #endif
2133
#endif
2134
2135
108k
        rng->status = DRBG_OK;
2136
108k
        ret = 0;
2137
108k
    }
2138
7.71k
    else if (ret == DRBG_CONT_FAILURE) {
2139
967
        rng->status = DRBG_CONT_FAILED;
2140
967
        ret = DRBG_CONT_FIPS_E;
2141
967
    }
2142
6.74k
    else if (ret == DRBG_FAILURE) {
2143
56
        rng->status = DRBG_FAILED;
2144
56
        ret = RNG_FAILURE_E;
2145
56
    }
2146
6.68k
    else {
2147
6.68k
        rng->status = DRBG_FAILED;
2148
6.68k
    }
2149
115k
#endif /* HAVE_HASHDRBG */
2150
115k
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
2151
2152
115k
    return ret;
2153
115k
}
2154
2155
2156
WOLFSSL_ABI
2157
WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap)
2158
0
{
2159
0
    int ret = 0;
2160
0
    WC_RNG* rng = NULL;
2161
2162
    /* Assume if WC_USE_DEVID it is intended for default usage */
2163
#ifdef WC_USE_DEVID
2164
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, WC_USE_DEVID);
2165
#else
2166
0
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, INVALID_DEVID);
2167
0
#endif
2168
2169
0
    if (ret != 0) {
2170
0
        return NULL;
2171
0
    }
2172
2173
0
    return rng;
2174
0
}
2175
2176
2177
int wc_rng_new_ex(WC_RNG **rng, byte* nonce, word32 nonceSz,
2178
                  void* heap, int devId)
2179
0
{
2180
0
    int ret;
2181
2182
0
    if (rng == NULL) {
2183
0
        return BAD_FUNC_ARG;
2184
0
    }
2185
2186
0
    *rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
2187
0
    if (*rng == NULL) {
2188
0
        return MEMORY_E;
2189
0
    }
2190
2191
0
    ret = _InitRng(*rng, nonce, nonceSz, heap, devId);
2192
0
    if (ret != 0) {
2193
0
        XFREE(*rng, heap, DYNAMIC_TYPE_RNG);
2194
0
        *rng = NULL;
2195
0
    }
2196
2197
0
    return ret;
2198
0
}
2199
2200
2201
WOLFSSL_ABI
2202
void wc_rng_free(WC_RNG* rng)
2203
0
{
2204
0
    if (rng) {
2205
0
        void* heap = rng->heap;
2206
2207
0
        wc_FreeRng(rng);
2208
0
        ForceZero(rng, sizeof(WC_RNG));
2209
0
        XFREE(rng, heap, DYNAMIC_TYPE_RNG);
2210
0
        (void)heap;
2211
0
    }
2212
0
}
2213
2214
WOLFSSL_ABI
2215
int wc_InitRng(WC_RNG* rng)
2216
982
{
2217
982
    return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
2218
982
}
2219
2220
2221
int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
2222
125k
{
2223
125k
    return _InitRng(rng, NULL, 0, heap, devId);
2224
125k
}
2225
2226
2227
int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
2228
0
{
2229
0
    return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
2230
0
}
2231
2232
2233
int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
2234
                       void* heap, int devId)
2235
0
{
2236
0
    return _InitRng(rng, nonce, nonceSz, heap, devId);
2237
0
}
2238
2239
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
2240
static int PollAndReSeed(WC_RNG* rng)
2241
0
{
2242
0
    int ret   = DRBG_NEED_RESEED;
2243
0
    int devId = INVALID_DEVID;
2244
0
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2245
0
    devId = rng->devId;
2246
0
#endif
2247
0
    if (wc_RNG_HealthTestLocal(rng, 1, rng->heap, devId) == 0) {
2248
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
2249
        byte* newSeed = rng->newSeed_buf;
2250
        ret = DRBG_SUCCESS;
2251
    #elif defined(WOLFSSL_SMALL_STACK)
2252
0
        byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
2253
0
            DYNAMIC_TYPE_SEED);
2254
0
        ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS;
2255
    #else
2256
        byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
2257
        ret = DRBG_SUCCESS;
2258
    #endif
2259
0
        if (ret == DRBG_SUCCESS) {
2260
        #ifdef WC_RNG_SEED_CB
2261
            if (seedCb == NULL) {
2262
                ret = DRBG_NO_SEED_CB;
2263
            }
2264
            else {
2265
                ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
2266
                if (ret != 0) {
2267
    #ifdef WC_VERBOSE_RNG
2268
                    WOLFSSL_DEBUG_PRINTF("ERROR: seedCb() in PollAndReSeed() "
2269
                                         "failed with err %d", ret);
2270
    #endif
2271
                    ret = DRBG_FAILURE;
2272
                }
2273
            }
2274
        #else
2275
0
            ret = wc_GenerateSeed(&rng->seed, newSeed,
2276
0
                              SEED_SZ + SEED_BLOCK_SZ);
2277
0
            if (ret != 0) {
2278
    #ifdef WC_VERBOSE_RNG
2279
                WOLFSSL_DEBUG_PRINTF(
2280
                    "ERROR: wc_GenerateSeed() in PollAndReSeed() failed with "
2281
                    "err %d", ret);
2282
    #endif
2283
0
                ret = DRBG_FAILURE;
2284
0
            }
2285
0
        #endif
2286
0
        }
2287
0
        if (ret == DRBG_SUCCESS) {
2288
0
            ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
2289
    #ifdef WC_VERBOSE_RNG
2290
            if (ret != DRBG_SUCCESS)
2291
                WOLFSSL_DEBUG_PRINTF(
2292
                    "ERROR: wc_RNG_TestSeed() in PollAndReSeed() returned "
2293
                    "err %d.", ret);
2294
    #endif
2295
0
        }
2296
0
        if (ret == DRBG_SUCCESS) {
2297
0
#ifndef NO_SHA256
2298
0
            if (rng->drbgType == WC_DRBG_SHA256)
2299
0
                ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg,
2300
0
                                       newSeed + SEED_BLOCK_SZ, SEED_SZ,
2301
0
                                       NULL, 0);
2302
0
#endif
2303
0
#ifdef WOLFSSL_DRBG_SHA512
2304
0
            if (rng->drbgType == WC_DRBG_SHA512)
2305
0
                ret = Hash512_DRBG_Reseed(
2306
0
                    (DRBG_SHA512_internal *)rng->drbg512,
2307
0
                    newSeed + SEED_BLOCK_SZ, SEED_SZ, NULL, 0);
2308
0
#endif
2309
0
        }
2310
0
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2311
0
        if (newSeed != NULL) {
2312
0
            ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ);
2313
0
        }
2314
0
        XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED);
2315
    #else
2316
        ForceZero(newSeed, sizeof(newSeed));
2317
    #endif
2318
0
    }
2319
0
    else {
2320
0
        ret = DRBG_CONT_FAILURE;
2321
0
    }
2322
2323
0
    return ret;
2324
0
}
2325
#endif
2326
2327
/* place a generated block in output */
2328
#ifdef WC_RNG_BANK_SUPPORT
2329
static int wc_local_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
2330
#else
2331
WOLFSSL_ABI
2332
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
2333
#endif
2334
247k
{
2335
247k
    int ret;
2336
2337
247k
    if (rng == NULL || output == NULL)
2338
0
        return BAD_FUNC_ARG;
2339
2340
247k
    if (sz == 0)
2341
325
        return 0;
2342
2343
247k
#ifdef WOLF_CRYPTO_CB
2344
247k
    #ifndef WOLF_CRYPTO_CB_FIND
2345
247k
    if (rng->devId != INVALID_DEVID)
2346
7.38k
    #endif
2347
7.38k
    {
2348
7.38k
        ret = wc_CryptoCb_RandomBlock(rng, output, sz);
2349
7.38k
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
2350
7.38k
            return ret;
2351
        /* fall-through when unavailable */
2352
7.38k
    }
2353
239k
#endif
2354
2355
#ifdef HAVE_INTEL_RDRAND
2356
    if (IS_INTEL_RDRAND(intel_flags))
2357
        return wc_GenerateRand_IntelRD(NULL, output, sz);
2358
#endif
2359
2360
#if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_TRNG)
2361
    return silabs_GenerateRand(output, sz);
2362
#endif
2363
2364
#if defined(WOLFSSL_ASYNC_CRYPT)
2365
    if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
2366
        /* these are blocking */
2367
    #ifdef HAVE_CAVIUM
2368
        return NitroxRngGenerateBlock(rng, output, sz);
2369
    #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
2370
        return IntelQaDrbg(&rng->asyncDev, output, sz);
2371
    #else
2372
        /* simulator not supported */
2373
    #endif
2374
    }
2375
#endif
2376
2377
#ifdef CUSTOM_RAND_GENERATE_BLOCK
2378
    XMEMSET(output, 0, sz);
2379
    ret = (int)CUSTOM_RAND_GENERATE_BLOCK(output, sz);
2380
    #ifdef WC_VERBOSE_RNG
2381
    if (ret != 0)
2382
        WOLFSSL_DEBUG_PRINTF(
2383
            "ERROR: CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
2384
    #endif
2385
#else
2386
2387
239k
#ifdef HAVE_HASHDRBG
2388
239k
    if (sz > RNG_MAX_BLOCK_LEN)
2389
0
        return BAD_FUNC_ARG;
2390
2391
239k
    if (rng->status != DRBG_OK)
2392
26
        return RNG_FAILURE_E;
2393
2394
239k
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
2395
239k
    if (rng->pid != getpid()) {
2396
0
        rng->pid = getpid();
2397
0
        ret = PollAndReSeed(rng);
2398
0
        if (ret != DRBG_SUCCESS) {
2399
0
            rng->status = DRBG_FAILED;
2400
0
            return RNG_FAILURE_E;
2401
0
        }
2402
0
    }
2403
239k
#endif
2404
2405
239k
#ifndef NO_SHA256
2406
239k
    if (rng->drbgType == WC_DRBG_SHA256) {
2407
0
        ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz,
2408
0
                                 NULL, 0);
2409
0
        if (ret == DRBG_NEED_RESEED) {
2410
0
            ret = PollAndReSeed(rng);
2411
0
            if (ret == DRBG_SUCCESS)
2412
0
                ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output,
2413
0
                                         sz, NULL, 0);
2414
0
        }
2415
0
    }
2416
239k
    else
2417
239k
#endif
2418
239k
#ifdef WOLFSSL_DRBG_SHA512
2419
239k
    if (rng->drbgType == WC_DRBG_SHA512) {
2420
239k
        ret = Hash512_DRBG_Generate((DRBG_SHA512_internal *)rng->drbg512,
2421
239k
                                    output, sz, NULL, 0);
2422
239k
        if (ret == DRBG_NEED_RESEED) {
2423
0
            ret = PollAndReSeed(rng);
2424
0
            if (ret == DRBG_SUCCESS)
2425
0
                ret = Hash512_DRBG_Generate(
2426
0
                    (DRBG_SHA512_internal *)rng->drbg512, output, sz,
2427
0
                    NULL, 0);
2428
0
        }
2429
239k
    }
2430
0
    else
2431
0
#endif
2432
0
    {
2433
0
        ret = DRBG_FAILURE;
2434
0
    }
2435
2436
239k
    if (ret == DRBG_SUCCESS) {
2437
233k
        ret = 0;
2438
233k
    }
2439
6.60k
    else if (ret == DRBG_CONT_FAILURE) {
2440
0
        ret = DRBG_CONT_FIPS_E;
2441
0
        rng->status = DRBG_CONT_FAILED;
2442
0
    }
2443
6.60k
    else {
2444
6.60k
        ret = RNG_FAILURE_E;
2445
6.60k
        rng->status = DRBG_FAILED;
2446
6.60k
    }
2447
#else
2448
2449
    /* if we get here then there is an RNG configuration error */
2450
    ret = RNG_FAILURE_E;
2451
2452
#endif /* HAVE_HASHDRBG */
2453
239k
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
2454
2455
239k
    return ret;
2456
239k
}
2457
2458
#ifdef WC_RNG_BANK_SUPPORT
2459
WOLFSSL_ABI
2460
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
2461
{
2462
    if (rng == NULL)
2463
        return BAD_FUNC_ARG;
2464
2465
    if (rng->status == WC_DRBG_BANKREF) {
2466
        int ret;
2467
        struct wc_rng_bank_inst *bank_inst = NULL;
2468
2469
        ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst);
2470
        if (ret != 0)
2471
            return ret;
2472
        if (bank_inst == NULL)
2473
            return BAD_STATE_E;
2474
        ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst),
2475
                                         output, sz);
2476
        {
2477
            int checkin_ret = wc_rng_bank_checkin(rng->bankref, &bank_inst);
2478
            if (checkin_ret != 0) {
2479
#ifdef WC_VERBOSE_RNG
2480
                WOLFSSL_DEBUG_PRINTF(
2481
                    "ERROR: wc_RNG_GenerateBlock() wc_rng_bank_checkin() "
2482
                    "failed with err %d.", checkin_ret);
2483
#endif
2484
                if (ret == 0)
2485
                    ret = checkin_ret;
2486
            }
2487
        }
2488
        return ret;
2489
    }
2490
    else
2491
        return wc_local_RNG_GenerateBlock(rng, output, sz);
2492
}
2493
#endif
2494
2495
int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
2496
0
{
2497
0
    return wc_RNG_GenerateBlock(rng, b, 1);
2498
0
}
2499
2500
2501
int wc_FreeRng(WC_RNG* rng)
2502
119k
{
2503
119k
    int ret = 0;
2504
2505
119k
    if (rng == NULL)
2506
0
        return BAD_FUNC_ARG;
2507
2508
#ifdef WC_RNG_BANK_SUPPORT
2509
    if (rng->status == WC_DRBG_BANKREF)
2510
        return wc_BankRef_Release(rng);
2511
#endif /* WC_RNG_BANK_SUPPORT */
2512
2513
#if defined(WOLFSSL_ASYNC_CRYPT)
2514
    wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
2515
#endif
2516
2517
119k
#ifdef HAVE_HASHDRBG
2518
119k
#ifndef NO_SHA256
2519
119k
    if (rng->drbg != NULL) {
2520
0
      if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg) != DRBG_SUCCESS)
2521
0
            ret = RNG_FAILURE_E;
2522
2523
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
2524
0
        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
2525
    #elif defined(WOLFSSL_CHECK_MEM_ZERO)
2526
        wc_MemZero_Check(rng->drbg, sizeof(DRBG_internal));
2527
    #endif
2528
0
        rng->drbg = NULL;
2529
0
    }
2530
2531
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2532
    /* Scratch buffers are tracked independently of rng->drbg so that a
2533
     * partial-construction failure path that nulled rng->drbg early
2534
     * (or any future restructure that does the same) cannot leak them.
2535
     * Free on their own NULL check rather than nesting under drbg. */
2536
    if (rng->drbg_scratch != NULL) {
2537
        if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch)
2538
                            != DRBG_SUCCESS)
2539
            ret = RNG_FAILURE_E;
2540
        XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
2541
        rng->drbg_scratch = NULL;
2542
    }
2543
    if (rng->health_check_scratch != NULL) {
2544
        XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_TMP_BUFFER);
2545
        rng->health_check_scratch = NULL;
2546
    }
2547
    #endif
2548
119k
#endif /* !NO_SHA256 */
2549
2550
119k
#ifdef WOLFSSL_DRBG_SHA512
2551
119k
    if (rng->drbg512 != NULL) {
2552
119k
        if (Hash512_DRBG_Uninstantiate(
2553
119k
                (DRBG_SHA512_internal *)rng->drbg512) != DRBG_SUCCESS)
2554
0
            ret = RNG_FAILURE_E;
2555
2556
119k
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
2557
119k
        XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG);
2558
119k
    #endif
2559
119k
        rng->drbg512 = NULL;
2560
119k
    }
2561
2562
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2563
    /* Same independence rationale as the SHA-256 scratch above. */
2564
    if (rng->drbg512_scratch != NULL) {
2565
        if (Hash512_DRBG_Uninstantiate(rng->drbg512_scratch)
2566
                                != DRBG_SUCCESS)
2567
            ret = RNG_FAILURE_E;
2568
        XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG);
2569
        rng->drbg512_scratch = NULL;
2570
    }
2571
    if (rng->health_check_scratch_512 != NULL) {
2572
        XFREE(rng->health_check_scratch_512, rng->heap,
2573
               DYNAMIC_TYPE_TMP_BUFFER);
2574
        rng->health_check_scratch_512 = NULL;
2575
    }
2576
    #endif
2577
119k
#endif /* WOLFSSL_DRBG_SHA512 */
2578
2579
#ifdef WOLFSSL_SMALL_STACK_CACHE
2580
    XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED);
2581
    rng->newSeed_buf = NULL;
2582
#endif
2583
2584
119k
    rng->status = DRBG_NOT_INIT;
2585
119k
#endif /* HAVE_HASHDRBG */
2586
2587
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
2588
    /* don't overwrite previously set error */
2589
    if (wc_VersalTrngReset() && !ret)
2590
        ret = WC_HW_E;
2591
#endif
2592
2593
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && defined(XCLOSE) && \
2594
    !defined(USE_WINDOWS_API)
2595
    if(rng->seed.seedFdOpen && rng->seed.fd != XBADFD) {
2596
        XCLOSE(rng->seed.fd);
2597
        rng->seed.fd = XBADFD;
2598
        rng->seed.seedFdOpen = 0;
2599
    }
2600
#endif
2601
2602
119k
    return ret;
2603
119k
}
2604
2605
#ifdef HAVE_HASHDRBG
2606
/* The original wc_RNG_HealthTest{,_ex} entry points operate on the SHA-256
2607
 * Hash_DRBG (DRBG_internal). Gate them out under NO_SHA256; SHA-512-only
2608
 * builds use wc_RNG_HealthTest_SHA512_ex declared further down. */
2609
#ifndef NO_SHA256
2610
int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
2611
                                  const byte* seedB, word32 seedBSz,
2612
                                  byte* output, word32 outputSz)
2613
0
{
2614
0
    return wc_RNG_HealthTest_ex(reseed, NULL, 0,
2615
0
                                seedA, seedASz, seedB, seedBSz,
2616
0
                                output, outputSz,
2617
0
                                NULL, INVALID_DEVID);
2618
0
}
2619
2620
2621
static int wc_RNG_HealthTest_ex_internal(DRBG_internal* drbg,
2622
                                  int reseed, const byte* nonce, word32 nonceSz,
2623
                                  const byte* seedA, word32 seedASz,
2624
                                  const byte* seedB, word32 seedBSz,
2625
                                  byte* output, word32 outputSz,
2626
                                  void* heap, int devId)
2627
0
{
2628
0
    int ret = -1;
2629
2630
0
    if (seedA == NULL || output == NULL) {
2631
0
        return BAD_FUNC_ARG;
2632
0
    }
2633
2634
0
    if (reseed != 0 && seedB == NULL) {
2635
0
        return BAD_FUNC_ARG;
2636
0
    }
2637
2638
0
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
2639
0
        return ret;
2640
0
    }
2641
2642
#ifdef WOLFSSL_SMALL_STACK_CACHE
2643
    (void)heap;
2644
    (void)devId;
2645
2646
    if (Hash_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz,
2647
                        NULL, 0) != 0) {
2648
        goto exit_rng_ht;
2649
    }
2650
#else
2651
0
    if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
2652
0
                              NULL, 0, heap, devId) != 0) {
2653
0
        goto exit_rng_ht;
2654
0
    }
2655
0
#endif
2656
2657
0
    if (reseed) {
2658
0
        if (Hash_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0) != 0) {
2659
0
            goto exit_rng_ht;
2660
0
        }
2661
0
    }
2662
2663
    /* This call to generate is prescribed by the NIST DRBGVS
2664
     * procedure. The results are thrown away. The known
2665
     * answer test checks the second block of DRBG out of
2666
     * the generator to ensure the internal state is updated
2667
     * as expected. */
2668
0
    if (Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0) != 0) {
2669
0
        goto exit_rng_ht;
2670
0
    }
2671
2672
0
    if (Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0) != 0) {
2673
0
        goto exit_rng_ht;
2674
0
    }
2675
2676
    /* Mark success */
2677
0
    ret = 0;
2678
2679
0
exit_rng_ht:
2680
2681
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2682
    /* This is safe to call even if Hash_DRBG_Instantiate fails */
2683
0
    if (Hash_DRBG_Uninstantiate(drbg) != 0) {
2684
0
        ret = -1;
2685
0
    }
2686
0
#endif
2687
2688
0
    return ret;
2689
0
}
2690
2691
int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
2692
                                  const byte* seedA, word32 seedASz,
2693
                                  const byte* seedB, word32 seedBSz,
2694
                                  byte* output, word32 outputSz,
2695
                                  void* heap, int devId)
2696
0
{
2697
0
    int ret = -1;
2698
0
    DRBG_internal* drbg;
2699
#ifndef WOLFSSL_SMALL_STACK
2700
    DRBG_internal  drbg_var;
2701
#endif
2702
2703
0
#ifdef WOLFSSL_SMALL_STACK
2704
0
    drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap,
2705
0
        DYNAMIC_TYPE_RNG);
2706
0
    if (drbg == NULL) {
2707
0
        return MEMORY_E;
2708
0
    }
2709
#else
2710
    drbg = &drbg_var;
2711
#endif
2712
2713
#ifdef WOLFSSL_SMALL_STACK_CACHE
2714
    ret = Hash_DRBG_Instantiate(drbg,
2715
                    NULL /* seed */, 0, NULL /* nonce */, 0,
2716
                    NULL /* perso */, 0, heap, devId);
2717
    if (ret == 0)
2718
#endif
2719
0
    {
2720
0
        ret = wc_RNG_HealthTest_ex_internal(
2721
0
                drbg, reseed, nonce, nonceSz, seedA, seedASz,
2722
0
                seedB, seedBSz, output, outputSz, heap, devId);
2723
#ifdef WOLFSSL_SMALL_STACK_CACHE
2724
        Hash_DRBG_Uninstantiate(drbg);
2725
#endif
2726
0
    }
2727
0
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_RNG);
2728
2729
0
    return ret;
2730
0
}
2731
#endif /* !NO_SHA256 - wc_RNG_HealthTest{,_ex,_ex_internal} */
2732
2733
2734
const FLASH_QUALIFIER byte seedA_data[] = {
2735
    0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
2736
    0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
2737
    0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
2738
    0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
2739
};
2740
2741
const FLASH_QUALIFIER byte reseedSeedA_data[] = {
2742
    0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
2743
    0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
2744
    0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
2745
};
2746
2747
const FLASH_QUALIFIER byte outputA_data[] = {
2748
    0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
2749
    0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
2750
    0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
2751
    0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
2752
    0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
2753
    0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
2754
    0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
2755
    0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
2756
    0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
2757
    0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
2758
    0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
2759
};
2760
2761
const FLASH_QUALIFIER byte seedB_data[] = {
2762
    0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
2763
    0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
2764
    0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
2765
    0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
2766
    0xdb, 0xcb, 0xcc, 0x2e
2767
};
2768
2769
const FLASH_QUALIFIER byte outputB_data[] = {
2770
    0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
2771
    0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
2772
    0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
2773
    0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
2774
    0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
2775
    0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
2776
    0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
2777
    0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
2778
    0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
2779
    0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
2780
    0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
2781
};
2782
2783
2784
/* SHA-512 DRBG KAT vectors for local health test.
2785
 * Source: NIST CAVP Hash_DRBG.rsp, [SHA-512], PredictionResistance=False,
2786
 * EntropyInputLen=256, NonceLen=128, PersonalizationStringLen=0,
2787
 * AdditionalInputLen=0, ReturnedBitsLen=2048. */
2788
#ifdef WOLFSSL_DRBG_SHA512
2789
2790
/* Reseed test vectors (COUNT=0 from reseed section) */
2791
static const byte sha512_seedA_data[] = {
2792
    /* EntropyInput (32 bytes) || Nonce (16 bytes) */
2793
    0x31, 0x44, 0xe1, 0x7a, 0x10, 0xc8, 0x56, 0x12,
2794
    0x97, 0x64, 0xf5, 0x8f, 0xd8, 0xe4, 0x23, 0x10,
2795
    0x20, 0x54, 0x69, 0x96, 0xc0, 0xbf, 0x6c, 0xff,
2796
    0x8e, 0x91, 0xc2, 0x4e, 0xe0, 0x9b, 0xe3, 0x33,
2797
    0xb1, 0x6f, 0xcb, 0x1c, 0xf0, 0xc0, 0x10, 0xf3,
2798
    0x1f, 0xea, 0xb7, 0x33, 0x58, 0x8b, 0x8e, 0x04
2799
};
2800
static const byte sha512_reseedSeedA_data[] = {
2801
    /* EntropyInputReseed (32 bytes) */
2802
    0xa0, 0xb3, 0x58, 0x4c, 0x2c, 0x84, 0x12, 0xf6,
2803
    0x18, 0x40, 0x68, 0x34, 0x40, 0x4d, 0x1e, 0xb0,
2804
    0xce, 0x99, 0x9b, 0xa2, 0x89, 0x66, 0x05, 0x4d,
2805
    0x7e, 0x49, 0x7e, 0x0d, 0xb6, 0x08, 0xb9, 0x67
2806
};
2807
static const byte sha512_outputA_data[] = {
2808
    0xef, 0xa3, 0x5d, 0xd0, 0x36, 0x2a, 0xdb, 0x76,
2809
    0x26, 0x45, 0x6b, 0x36, 0xfa, 0xc7, 0x4d, 0x3c,
2810
    0x28, 0xd0, 0x1d, 0x92, 0x64, 0x20, 0x27, 0x5a,
2811
    0x28, 0xbe, 0xa9, 0xc9, 0xdd, 0x75, 0x47, 0xc1,
2812
    0x5e, 0x79, 0x31, 0x85, 0x2a, 0xc1, 0x27, 0x70,
2813
    0x76, 0x56, 0x75, 0x35, 0x23, 0x9c, 0x1f, 0x42,
2814
    0x9c, 0x7f, 0x75, 0xcf, 0x74, 0xc2, 0x26, 0x7d,
2815
    0xeb, 0x6a, 0x3e, 0x59, 0x6c, 0xf3, 0x26, 0x15,
2816
    0x6c, 0x79, 0x69, 0x41, 0x28, 0x3b, 0x8d, 0x58,
2817
    0x3f, 0x17, 0x1c, 0x2f, 0x6e, 0x33, 0x23, 0xf7,
2818
    0x55, 0x5e, 0x1b, 0x18, 0x1f, 0xfd, 0xa3, 0x05,
2819
    0x07, 0x21, 0x0c, 0xb1, 0xf5, 0x89, 0xb2, 0x3c,
2820
    0xd7, 0x18, 0x80, 0xfd, 0x44, 0x37, 0x0c, 0xac,
2821
    0xf4, 0x33, 0x75, 0xb0, 0xdb, 0x7e, 0x33, 0x6f,
2822
    0x12, 0xb3, 0x09, 0xbf, 0xd4, 0xf6, 0x10, 0xbb,
2823
    0x8f, 0x20, 0xe1, 0xa1, 0x5e, 0x25, 0x3a, 0x4f,
2824
    0xe5, 0x11, 0xa0, 0x27, 0x96, 0x8d, 0xf0, 0xb1,
2825
    0x05, 0xa1, 0xd7, 0x3a, 0xff, 0x7c, 0x7a, 0x82,
2826
    0x6d, 0x39, 0xf6, 0x40, 0xdf, 0xb8, 0xf5, 0x22,
2827
    0x25, 0x9e, 0xd4, 0x02, 0x28, 0x2e, 0x2c, 0x2e,
2828
    0x9d, 0x3a, 0x49, 0x8f, 0x51, 0x72, 0x5f, 0xe4,
2829
    0x14, 0x1b, 0x06, 0xda, 0x55, 0x98, 0xa4, 0x2a,
2830
    0xc1, 0xe0, 0x49, 0x4e, 0x99, 0x7d, 0x56, 0x6a,
2831
    0x1a, 0x39, 0xb6, 0x76, 0xb9, 0x6a, 0x60, 0x03,
2832
    0xa4, 0xc5, 0xdb, 0x84, 0xf2, 0x46, 0x58, 0x4e,
2833
    0xe6, 0x5a, 0xf7, 0x0f, 0xf2, 0x16, 0x02, 0x78,
2834
    0x16, 0x6d, 0xa1, 0x6d, 0x91, 0xc9, 0xb8, 0xf2,
2835
    0xde, 0xb0, 0x27, 0x51, 0xa1, 0x08, 0x8a, 0xd6,
2836
    0xbe, 0x4e, 0x80, 0xef, 0x96, 0x6e, 0xb7, 0x3e,
2837
    0x66, 0xbc, 0x87, 0xca, 0xd8, 0x7c, 0x77, 0xc0,
2838
    0xb3, 0x4a, 0x21, 0xba, 0x1d, 0xa0, 0xba, 0x6d,
2839
    0x16, 0xca, 0x50, 0x46, 0xdc, 0x4a, 0xbd, 0xa0
2840
};
2841
2842
/* No-reseed test vectors (COUNT=0 from no-reseed section) */
2843
static const byte sha512_seedB_data[] = {
2844
    /* EntropyInput (32 bytes) || Nonce (16 bytes) */
2845
    0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
2846
    0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
2847
    0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
2848
    0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
2849
    0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
2850
    0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25
2851
};
2852
static const byte sha512_outputB_data[] = {
2853
    0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
2854
    0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
2855
    0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
2856
    0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
2857
    0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
2858
    0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
2859
    0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
2860
    0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
2861
    0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
2862
    0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
2863
    0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
2864
    0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
2865
    0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
2866
    0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
2867
    0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
2868
    0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
2869
    0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
2870
    0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
2871
    0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
2872
    0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
2873
    0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
2874
    0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
2875
    0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
2876
    0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
2877
    0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
2878
    0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
2879
    0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
2880
    0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
2881
    0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
2882
    0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
2883
    0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
2884
    0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2
2885
};
2886
#endif /* WOLFSSL_DRBG_SHA512 */
2887
2888
2889
static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap,
2890
                                  int devId)
2891
109k
{
2892
109k
    int ret = 0;
2893
2894
109k
#ifdef WOLFSSL_DRBG_SHA512
2895
    /* SHA-512 DRBG health test path */
2896
109k
    if (rng->drbgType == WC_DRBG_SHA512) {
2897
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2898
        byte *check512 = rng->health_check_scratch_512;
2899
        DRBG_SHA512_internal* drbg512 = rng->drbg512_scratch;
2900
    #else
2901
109k
        WC_DECLARE_VAR(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, 0);
2902
109k
        WC_DECLARE_VAR(drbg512, DRBG_SHA512_internal, 1, 0);
2903
2904
109k
        WC_ALLOC_VAR_EX(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
2905
109k
            heap, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
2906
109k
        WC_ALLOC_VAR_EX(drbg512, DRBG_SHA512_internal, 1, heap,
2907
109k
            DYNAMIC_TYPE_TMP_BUFFER, WC_DO_NOTHING);
2908
109k
        #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
2909
109k
        if (drbg512 == NULL) {
2910
86
            WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER);
2911
86
            return MEMORY_E;
2912
86
        }
2913
108k
        #endif
2914
108k
    #endif
2915
2916
108k
        if (reseed) {
2917
            /* Reseed test with NIST CAVP SHA-512 vectors */
2918
0
            ret = wc_RNG_HealthTest_SHA512_ex_internal(
2919
0
                        drbg512, 1, NULL, 0, NULL, 0,
2920
0
                        sha512_seedA_data, sizeof(sha512_seedA_data),
2921
0
                        sha512_reseedSeedA_data,
2922
0
                        sizeof(sha512_reseedSeedA_data),
2923
0
                        NULL, 0, NULL, 0,
2924
0
                        check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
2925
0
                        heap, devId);
2926
0
            if (ret == 0) {
2927
0
                if (ConstantCompare(check512, sha512_outputA_data,
2928
0
                                    RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0)
2929
0
                    ret = -1;
2930
0
            }
2931
0
        }
2932
108k
        else {
2933
            /* No-reseed test with NIST CAVP SHA-512 vectors */
2934
108k
            ret = wc_RNG_HealthTest_SHA512_ex_internal(
2935
108k
                        drbg512, 0, NULL, 0, NULL, 0,
2936
108k
                        sha512_seedB_data, sizeof(sha512_seedB_data),
2937
108k
                        NULL, 0,
2938
108k
                        NULL, 0, NULL, 0,
2939
108k
                        check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
2940
108k
                        heap, devId);
2941
108k
            if (ret == 0) {
2942
108k
                if (ConstantCompare(check512, sha512_outputB_data,
2943
108k
                                    RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0)
2944
12
                    ret = -1;
2945
108k
            }
2946
108k
        }
2947
2948
108k
    #ifndef WOLFSSL_SMALL_STACK_CACHE
2949
108k
        WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER);
2950
108k
        WC_FREE_VAR_EX(drbg512, heap, DYNAMIC_TYPE_TMP_BUFFER);
2951
108k
    #endif
2952
108k
        return ret;
2953
109k
    }
2954
0
#endif /* WOLFSSL_DRBG_SHA512 */
2955
2956
    /* SHA-256 DRBG health test path (original) */
2957
0
#ifndef NO_SHA256
2958
0
    {
2959
#ifdef WOLFSSL_SMALL_STACK_CACHE
2960
    byte *check = rng->health_check_scratch;
2961
    DRBG_internal* drbg = (DRBG_internal *)rng->drbg_scratch;
2962
#else
2963
0
    WC_DECLARE_VAR(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, 0);
2964
0
    WC_DECLARE_VAR(drbg, DRBG_internal, 1, 0);
2965
2966
0
    (void)rng;
2967
2968
0
    WC_ALLOC_VAR_EX(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, heap,
2969
0
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
2970
0
    WC_ALLOC_VAR_EX(drbg, DRBG_internal, 1, heap,
2971
0
        DYNAMIC_TYPE_TMP_BUFFER, WC_DO_NOTHING);
2972
0
    #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
2973
0
    if (drbg == NULL) {
2974
0
        WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
2975
0
        return MEMORY_E;
2976
0
    }
2977
0
    #endif
2978
0
#endif
2979
2980
0
    if (reseed) {
2981
#ifdef WOLFSSL_USE_FLASHMEM
2982
        byte* seedA = (byte*)XMALLOC(sizeof(seedA_data), heap,
2983
                             DYNAMIC_TYPE_TMP_BUFFER);
2984
        byte* reseedSeedA = (byte*)XMALLOC(sizeof(reseedSeedA_data), heap,
2985
                             DYNAMIC_TYPE_TMP_BUFFER);
2986
        byte* outputA = (byte*)XMALLOC(sizeof(outputA_data), heap,
2987
                             DYNAMIC_TYPE_TMP_BUFFER);
2988
2989
        if (!seedA || !reseedSeedA || !outputA) {
2990
            XFREE(seedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
2991
            XFREE(reseedSeedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
2992
            XFREE(outputA, heap, DYNAMIC_TYPE_TMP_BUFFER);
2993
            ret = MEMORY_E;
2994
        }
2995
        else {
2996
            XMEMCPY_P(seedA, seedA_data, sizeof(seedA_data));
2997
            XMEMCPY_P(reseedSeedA, reseedSeedA_data, sizeof(reseedSeedA_data));
2998
            XMEMCPY_P(outputA, outputA_data, sizeof(outputA_data));
2999
#else
3000
0
        const byte* seedA = seedA_data;
3001
0
        const byte* reseedSeedA = reseedSeedA_data;
3002
0
        const byte* outputA = outputA_data;
3003
0
#endif
3004
0
        ret = wc_RNG_HealthTest_ex_internal(drbg, 1, NULL, 0,
3005
0
                                   seedA, sizeof(seedA_data),
3006
0
                                   reseedSeedA, sizeof(reseedSeedA_data),
3007
0
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
3008
0
                                   heap, devId);
3009
0
        if (ret == 0) {
3010
0
            if (ConstantCompare(check, outputA,
3011
0
                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
3012
0
                ret = -1;
3013
0
        }
3014
3015
#ifdef WOLFSSL_USE_FLASHMEM
3016
            XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3017
            XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3018
            XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3019
        }
3020
#endif
3021
0
    }
3022
0
    else {
3023
#ifdef WOLFSSL_USE_FLASHMEM
3024
        byte* seedB = (byte*)XMALLOC(sizeof(seedB_data), heap,
3025
                             DYNAMIC_TYPE_TMP_BUFFER);
3026
        byte* outputB = (byte*)XMALLOC(sizeof(outputB_data), heap,
3027
                               DYNAMIC_TYPE_TMP_BUFFER);
3028
3029
        if (!seedB || !outputB) {
3030
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
3031
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
3032
            ret = MEMORY_E;
3033
        }
3034
        else {
3035
            XMEMCPY_P(seedB, seedB_data, sizeof(seedB_data));
3036
            XMEMCPY_P(outputB, outputB_data, sizeof(outputB_data));
3037
#else
3038
0
        const byte* seedB = seedB_data;
3039
0
        const byte* outputB = outputB_data;
3040
0
#endif
3041
#if defined(DEBUG_WOLFSSL)
3042
        WOLFSSL_MSG_EX("RNG_HEALTH_TEST_CHECK_SIZE = %d",
3043
                        RNG_HEALTH_TEST_CHECK_SIZE);
3044
        WOLFSSL_MSG_EX("sizeof(seedB_data)         = %d",
3045
                        (int)sizeof(outputB_data));
3046
#endif
3047
0
        ret = wc_RNG_HealthTest_ex_internal(drbg, 0, NULL, 0,
3048
0
                                   seedB, sizeof(seedB_data),
3049
0
                                   NULL, 0,
3050
0
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
3051
0
                                   heap, devId);
3052
0
        if (ret != 0) {
3053
            #if defined(DEBUG_WOLFSSL)
3054
            WOLFSSL_MSG_EX("RNG_HealthTest failed: err = %d", ret);
3055
            #endif
3056
0
        }
3057
0
        else {
3058
0
            ret = ConstantCompare(check, outputB,
3059
0
                                RNG_HEALTH_TEST_CHECK_SIZE);
3060
0
            if (ret != 0) {
3061
                #if defined(DEBUG_WOLFSSL)
3062
                WOLFSSL_MSG_EX("Random ConstantCompare failed: err = %d", ret);
3063
                #endif
3064
0
                ret = -1;
3065
0
            }
3066
0
        }
3067
3068
        /* The previous test cases use a large seed instead of a seed and nonce.
3069
         * seedB is actually from a test case with a seed and nonce, and
3070
         * just concatenates them. The pivot point between seed and nonce is
3071
         * byte 32, feed them into the health test separately. */
3072
0
        if (ret == 0) {
3073
0
            ret = wc_RNG_HealthTest_ex_internal(drbg, 0,
3074
0
                                       seedB + 32, sizeof(seedB_data) - 32,
3075
0
                                       seedB, 32,
3076
0
                                       NULL, 0,
3077
0
                                       check, RNG_HEALTH_TEST_CHECK_SIZE,
3078
0
                                       heap, devId);
3079
0
            if (ret == 0) {
3080
0
                if (ConstantCompare(check, outputB, sizeof(outputB_data)) != 0)
3081
0
                    ret = -1;
3082
0
            }
3083
0
        }
3084
3085
#ifdef WOLFSSL_USE_FLASHMEM
3086
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
3087
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
3088
        }
3089
#endif
3090
0
    }
3091
3092
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
3093
0
    WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
3094
0
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_TMP_BUFFER);
3095
0
#endif
3096
0
    } /* SHA-256 path */
3097
0
#endif /* !NO_SHA256 */
3098
3099
0
    return ret;
3100
0
}
3101
3102
/* ====================================================================== */
3103
/* SHA-512 Health Test API                                                 */
3104
/* ====================================================================== */
3105
#ifdef WOLFSSL_DRBG_SHA512
3106
3107
static int wc_RNG_HealthTest_SHA512_ex_internal(DRBG_SHA512_internal* drbg,
3108
                                  int reseed, const byte* nonce, word32 nonceSz,
3109
                                  const byte* perso, word32 persoSz,
3110
                                  const byte* seedA, word32 seedASz,
3111
                                  const byte* seedB, word32 seedBSz,
3112
                                  const byte* additionalA, word32 additionalASz,
3113
                                  const byte* additionalB, word32 additionalBSz,
3114
                                  byte* output, word32 outputSz,
3115
                                  void* heap, int devId)
3116
119k
{
3117
119k
    int ret = -1;
3118
3119
119k
    if (seedA == NULL || output == NULL) {
3120
0
        return BAD_FUNC_ARG;
3121
0
    }
3122
3123
119k
    if (reseed != 0 && seedB == NULL) {
3124
0
        return BAD_FUNC_ARG;
3125
0
    }
3126
3127
119k
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) {
3128
0
        return ret;
3129
0
    }
3130
3131
#ifdef WOLFSSL_SMALL_STACK_CACHE
3132
    (void)heap;
3133
    (void)devId;
3134
3135
    if (Hash512_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz,
3136
                          perso, persoSz) != 0) {
3137
        goto exit_rng_ht512;
3138
    }
3139
#else
3140
119k
    if (Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
3141
119k
                              perso, persoSz, heap, devId) != 0) {
3142
244
        goto exit_rng_ht512;
3143
244
    }
3144
119k
#endif
3145
3146
119k
    if (reseed) {
3147
0
        if (Hash512_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0) != 0) {
3148
0
            goto exit_rng_ht512;
3149
0
        }
3150
0
    }
3151
3152
    /* First generate: output discarded per NIST DRBGVS procedure */
3153
119k
    if (Hash512_DRBG_Generate(drbg, output, outputSz,
3154
119k
                              additionalA, additionalASz) != 0) {
3155
189
        goto exit_rng_ht512;
3156
189
    }
3157
3158
    /* Second generate: this is the actual test output */
3159
119k
    if (Hash512_DRBG_Generate(drbg, output, outputSz,
3160
119k
                              additionalB, additionalBSz) != 0) {
3161
170
        goto exit_rng_ht512;
3162
170
    }
3163
3164
119k
    ret = 0;
3165
3166
119k
exit_rng_ht512:
3167
3168
119k
#ifndef WOLFSSL_SMALL_STACK_CACHE
3169
119k
    if (Hash512_DRBG_Uninstantiate(drbg) != 0) {
3170
0
        ret = -1;
3171
0
    }
3172
119k
#endif
3173
3174
119k
    return ret;
3175
119k
}
3176
3177
3178
/* Extended API with personalization string and additional input
3179
 * for ACVP testing */
3180
int wc_RNG_HealthTest_SHA512_ex(int reseed,
3181
                                const byte* nonce, word32 nonceSz,
3182
                                const byte* persoString, word32 persoStringSz,
3183
                                const byte* seedA, word32 seedASz,
3184
                                const byte* seedB, word32 seedBSz,
3185
                                const byte* additionalA, word32 additionalASz,
3186
                                const byte* additionalB, word32 additionalBSz,
3187
                                byte* output, word32 outputSz,
3188
                                void* heap, int devId)
3189
0
{
3190
0
    int ret = -1;
3191
0
    DRBG_SHA512_internal* drbg;
3192
#ifndef WOLFSSL_SMALL_STACK
3193
    DRBG_SHA512_internal  drbg_var;
3194
#endif
3195
3196
0
    if (seedA == NULL || output == NULL) {
3197
0
        return BAD_FUNC_ARG;
3198
0
    }
3199
3200
0
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) {
3201
0
        return ret;
3202
0
    }
3203
3204
0
#ifdef WOLFSSL_SMALL_STACK
3205
0
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), heap,
3206
0
        DYNAMIC_TYPE_RNG);
3207
0
    if (drbg == NULL) {
3208
0
        return MEMORY_E;
3209
0
    }
3210
#else
3211
    drbg = &drbg_var;
3212
#endif
3213
3214
    /* SP 800-90A Sec 10.1.1.2: personalization string is concatenated
3215
     * with entropy during instantiation via Hash_df. */
3216
0
    ret = Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
3217
0
                                   persoString, persoStringSz, heap, devId);
3218
0
    if (ret != 0) {
3219
0
        goto exit_sha512_ex;
3220
0
    }
3221
3222
0
    if (reseed) {
3223
0
        if (seedB != NULL && seedBSz > 0) {
3224
0
            ret = Hash512_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0);
3225
0
            if (ret != 0) goto exit_sha512_ex;
3226
0
        }
3227
0
    }
3228
3229
    /* First generate (output discarded per NIST procedure) */
3230
0
    ret = Hash512_DRBG_Generate(drbg, output, outputSz,
3231
0
                                additionalA, additionalASz);
3232
0
    if (ret != 0) goto exit_sha512_ex;
3233
3234
    /* Second generate (this is the actual output) */
3235
0
    ret = Hash512_DRBG_Generate(drbg, output, outputSz,
3236
0
                                additionalB, additionalBSz);
3237
3238
0
exit_sha512_ex:
3239
0
    (void)Hash512_DRBG_Uninstantiate(drbg);
3240
3241
0
#ifdef WOLFSSL_SMALL_STACK
3242
0
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
3243
0
#endif
3244
3245
0
    return (ret == DRBG_SUCCESS) ? 0 : -1;
3246
0
}
3247
3248
3249
/* Simple API matching wc_RNG_HealthTest() pattern - entropy+nonce only */
3250
int wc_RNG_HealthTest_SHA512(int reseed,
3251
                             const byte* seedA, word32 seedASz,
3252
                             const byte* seedB, word32 seedBSz,
3253
                             byte* output, word32 outputSz)
3254
0
{
3255
0
    int ret = -1;
3256
0
    DRBG_SHA512_internal* drbg;
3257
#ifndef WOLFSSL_SMALL_STACK
3258
    DRBG_SHA512_internal  drbg_var;
3259
#endif
3260
3261
0
#ifdef WOLFSSL_SMALL_STACK
3262
0
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), NULL,
3263
0
        DYNAMIC_TYPE_RNG);
3264
0
    if (drbg == NULL) {
3265
0
        return MEMORY_E;
3266
0
    }
3267
#else
3268
    drbg = &drbg_var;
3269
#endif
3270
3271
#ifdef WOLFSSL_SMALL_STACK_CACHE
3272
    ret = Hash512_DRBG_Instantiate(drbg,
3273
                    NULL /* seed */, 0, NULL /* nonce */, 0,
3274
                    NULL, 0, NULL, INVALID_DEVID);
3275
    if (ret == 0)
3276
#endif
3277
0
    {
3278
0
        ret = wc_RNG_HealthTest_SHA512_ex_internal(
3279
0
                drbg, reseed, NULL, 0, NULL, 0,
3280
0
                seedA, seedASz, seedB, seedBSz,
3281
0
                NULL, 0, NULL, 0,
3282
0
                output, outputSz, NULL, INVALID_DEVID);
3283
#ifdef WOLFSSL_SMALL_STACK_CACHE
3284
        Hash512_DRBG_Uninstantiate(drbg);
3285
#endif
3286
0
    }
3287
0
    WC_FREE_VAR_EX(drbg, NULL, DYNAMIC_TYPE_RNG);
3288
3289
0
    return ret;
3290
0
}
3291
3292
#endif /* WOLFSSL_DRBG_SHA512 */
3293
3294
#if !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \
3295
    (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
3296
/* Extended SHA-256 Hash_DRBG health test per SP 800-90A.
3297
 * Supports flexible output sizes, prediction resistance, personalization
3298
 * strings, and additional input.
3299
 *
3300
 * predResistance=0: Instantiate(entropyA, nonce, perso) ->
3301
 *                   Reseed(entropyB, additionalReseed) ->
3302
 *                   Gen1(additionalA, discard) -> Gen2(additionalB, keep)
3303
 * predResistance=1: Instantiate(entropyA, nonce, perso) ->
3304
 *                   Reseed(entropyB, additionalA)+Gen1(NULL, discard) ->
3305
 *                   Reseed(entropyC, additionalB)+Gen2(NULL, keep)
3306
 */
3307
int wc_RNG_HealthTest_SHA256_ex(
3308
    int predResistance,
3309
    const byte* nonce, word32 nonceSz,
3310
    const byte* persoString, word32 persoStringSz,
3311
    const byte* entropyA, word32 entropyASz,
3312
    const byte* entropyB, word32 entropyBSz,
3313
    const byte* entropyC, word32 entropyCsz,
3314
    const byte* additionalA, word32 additionalASz,
3315
    const byte* additionalB, word32 additionalBSz,
3316
    const byte* additionalReseed, word32 additionalReseedSz,
3317
    byte* output, word32 outputSz,
3318
    void* heap, int devId)
3319
0
{
3320
0
    int ret;
3321
0
    DRBG_internal* drbg;
3322
#ifndef WOLFSSL_SMALL_STACK
3323
    DRBG_internal  drbg_var;
3324
#endif
3325
3326
0
    if (entropyA == NULL || output == NULL || outputSz == 0) {
3327
0
        return BAD_FUNC_ARG;
3328
0
    }
3329
3330
0
#ifdef WOLFSSL_SMALL_STACK
3331
0
    drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap,
3332
0
        DYNAMIC_TYPE_RNG);
3333
0
    if (drbg == NULL) {
3334
0
        return MEMORY_E;
3335
0
    }
3336
#else
3337
    drbg = &drbg_var;
3338
#endif
3339
3340
    /* Instantiate with entropy, nonce, personalization string */
3341
0
    ret = Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
3342
0
                                persoString, persoStringSz, heap, devId);
3343
0
    if (ret != 0) goto exit_sha256_ex;
3344
3345
0
    if (predResistance) {
3346
        /* Prediction resistance mode per SP 800-90A 9.3.1:
3347
         * additional_input is passed to Reseed, Generate gets NULL */
3348
3349
        /* Reseed 1 with additionalA, then Generate 1 with NULL (discard) */
3350
0
        if (entropyB != NULL && entropyBSz > 0) {
3351
0
            ret = Hash_DRBG_Reseed(drbg, entropyB, entropyBSz,
3352
0
                                   additionalA, additionalASz);
3353
0
            if (ret != 0) goto exit_sha256_ex;
3354
0
        }
3355
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0);
3356
0
        if (ret != 0) goto exit_sha256_ex;
3357
3358
        /* Reseed 2 with additionalB, then Generate 2 with NULL (keep) */
3359
0
        if (entropyC != NULL && entropyCsz > 0) {
3360
0
            ret = Hash_DRBG_Reseed(drbg, entropyC, entropyCsz,
3361
0
                                   additionalB, additionalBSz);
3362
0
            if (ret != 0) goto exit_sha256_ex;
3363
0
        }
3364
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0);
3365
0
    }
3366
0
    else {
3367
        /* Standard mode: explicit reseed, then two generates */
3368
0
        if (entropyB != NULL && entropyBSz > 0) {
3369
0
            ret = Hash_DRBG_Reseed(drbg, entropyB, entropyBSz,
3370
0
                                   additionalReseed, additionalReseedSz);
3371
0
            if (ret != 0) goto exit_sha256_ex;
3372
0
        }
3373
3374
        /* Generate 1 (output discarded per NIST DRBGVS procedure) */
3375
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz,
3376
0
                                 additionalA, additionalASz);
3377
0
        if (ret != 0) goto exit_sha256_ex;
3378
3379
        /* Generate 2 (this is the actual test output) */
3380
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz,
3381
0
                                 additionalB, additionalBSz);
3382
0
    }
3383
3384
0
exit_sha256_ex:
3385
0
    (void)Hash_DRBG_Uninstantiate(drbg);
3386
3387
0
#ifdef WOLFSSL_SMALL_STACK
3388
0
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
3389
0
#endif
3390
3391
0
    return ret;
3392
0
}
3393
#endif /* !NO_SHA256 && !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
3394
3395
3396
#ifdef WOLFSSL_DRBG_SHA512
3397
/* Extended SHA-512 Hash_DRBG health test per SP 800-90A.
3398
 * Supports flexible output sizes and prediction resistance mode.
3399
 *
3400
 * Per SP 800-90A Section 9.3.1, when prediction resistance is requested,
3401
 * the additional_input is consumed by the Reseed step and the subsequent
3402
 * Generate uses NULL additional_input.
3403
 *
3404
 * predResistance=0: Instantiate ->
3405
 *                   Reseed(entropyB, additionalReseed) ->
3406
 *                   Gen1(additionalA, discard) -> Gen2(additionalB, keep)
3407
 * predResistance=1: Instantiate ->
3408
 *                   Reseed(entropyB, additionalA)+Gen1(NULL, discard) ->
3409
 *                   Reseed(entropyC, additionalB)+Gen2(NULL, keep)
3410
 */
3411
int wc_RNG_HealthTest_SHA512_ex2(
3412
    int predResistance,
3413
    const byte* nonce, word32 nonceSz,
3414
    const byte* persoString, word32 persoStringSz,
3415
    const byte* entropyA, word32 entropyASz,
3416
    const byte* entropyB, word32 entropyBSz,
3417
    const byte* entropyC, word32 entropyCsz,
3418
    const byte* additionalA, word32 additionalASz,
3419
    const byte* additionalB, word32 additionalBSz,
3420
    const byte* additionalReseed, word32 additionalReseedSz,
3421
    byte* output, word32 outputSz,
3422
    void* heap, int devId)
3423
0
{
3424
0
    int ret;
3425
0
    DRBG_SHA512_internal* drbg;
3426
#ifndef WOLFSSL_SMALL_STACK
3427
    DRBG_SHA512_internal  drbg_var;
3428
#endif
3429
3430
0
    if (entropyA == NULL || output == NULL || outputSz == 0) {
3431
0
        return BAD_FUNC_ARG;
3432
0
    }
3433
3434
0
#ifdef WOLFSSL_SMALL_STACK
3435
0
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), heap,
3436
0
        DYNAMIC_TYPE_RNG);
3437
0
    if (drbg == NULL) {
3438
0
        return MEMORY_E;
3439
0
    }
3440
#else
3441
    drbg = &drbg_var;
3442
#endif
3443
3444
    /* Instantiate with entropy, nonce, personalization string */
3445
0
    ret = Hash512_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
3446
0
                                   persoString, persoStringSz, heap, devId);
3447
0
    if (ret != 0) goto exit_sha512_ex2;
3448
3449
0
    if (predResistance) {
3450
        /* Prediction resistance mode per SP 800-90A 9.3.1:
3451
         * additional_input is passed to Reseed, Generate gets NULL */
3452
3453
        /* Reseed 1 with additionalA, then Generate 1 with NULL (discard) */
3454
0
        if (entropyB != NULL && entropyBSz > 0) {
3455
0
            ret = Hash512_DRBG_Reseed(drbg, entropyB, entropyBSz,
3456
0
                                      additionalA, additionalASz);
3457
0
            if (ret != 0) goto exit_sha512_ex2;
3458
0
        }
3459
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz, NULL, 0);
3460
0
        if (ret != 0) goto exit_sha512_ex2;
3461
3462
        /* Reseed 2 with additionalB, then Generate 2 with NULL (keep) */
3463
0
        if (entropyC != NULL && entropyCsz > 0) {
3464
0
            ret = Hash512_DRBG_Reseed(drbg, entropyC, entropyCsz,
3465
0
                                      additionalB, additionalBSz);
3466
0
            if (ret != 0) goto exit_sha512_ex2;
3467
0
        }
3468
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz, NULL, 0);
3469
0
    }
3470
0
    else {
3471
        /* Standard mode: explicit reseed, then two generates */
3472
0
        if (entropyB != NULL && entropyBSz > 0) {
3473
0
            ret = Hash512_DRBG_Reseed(drbg, entropyB, entropyBSz,
3474
0
                                      additionalReseed, additionalReseedSz);
3475
0
            if (ret != 0) goto exit_sha512_ex2;
3476
0
        }
3477
3478
        /* Generate 1 (output discarded per NIST DRBGVS procedure) */
3479
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz,
3480
0
                                    additionalA, additionalASz);
3481
0
        if (ret != 0) goto exit_sha512_ex2;
3482
3483
        /* Generate 2 (this is the actual test output) */
3484
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz,
3485
0
                                    additionalB, additionalBSz);
3486
0
    }
3487
3488
0
exit_sha512_ex2:
3489
0
    (void)Hash512_DRBG_Uninstantiate(drbg);
3490
3491
0
#ifdef WOLFSSL_SMALL_STACK
3492
0
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
3493
0
#endif
3494
3495
0
    return (ret == DRBG_SUCCESS) ? 0 : -1;
3496
0
}
3497
3498
#endif /* WOLFSSL_DRBG_SHA512 */
3499
3500
#endif /* HAVE_HASHDRBG */
3501
3502
3503
#ifdef HAVE_WNR
3504
3505
/*
3506
 * Init global Whitewood netRandom context
3507
 * Returns 0 on success, negative on error
3508
 */
3509
int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
3510
{
3511
    int ret;
3512
3513
    if (configFile == NULL || timeout < 0)
3514
        return BAD_FUNC_ARG;
3515
3516
#ifndef WOLFSSL_MUTEX_INITIALIZER
3517
    if (wnr_mutex_inited > 0) {
3518
        WOLFSSL_MSG("netRandom context already created, skipping");
3519
        return 0;
3520
    }
3521
3522
    if (wc_InitMutex(&wnr_mutex) != 0) {
3523
        WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
3524
        return BAD_MUTEX_E;
3525
    }
3526
3527
    wnr_mutex_inited = 1;
3528
#endif
3529
3530
    if (wnr_inited > 0) {
3531
        WOLFSSL_MSG("netRandom context already created, skipping");
3532
        return 0;
3533
    }
3534
3535
    if (wc_LockMutex(&wnr_mutex) != 0) {
3536
        WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
3537
        return BAD_MUTEX_E;
3538
    }
3539
3540
    /* store entropy timeout */
3541
    wnr_timeout = timeout;
3542
3543
    /* create global wnr_context struct */
3544
    if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
3545
        WOLFSSL_MSG("Error creating global netRandom context");
3546
        ret = RNG_FAILURE_E;
3547
        goto out;
3548
    }
3549
3550
    /* load config file */
3551
    if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
3552
        WOLFSSL_MSG("Error loading config file into netRandom context");
3553
        wnr_destroy(wnr_ctx);
3554
        wnr_ctx = NULL;
3555
        ret = RNG_FAILURE_E;
3556
        goto out;
3557
    }
3558
3559
    /* create/init polling mechanism */
3560
    if (wnr_poll_create() != WNR_ERROR_NONE) {
3561
        WOLFSSL_MSG("Error initializing netRandom polling mechanism");
3562
        wnr_destroy(wnr_ctx);
3563
        wnr_ctx = NULL;
3564
        ret = RNG_FAILURE_E;
3565
        goto out;
3566
    }
3567
3568
    /* validate config, set HMAC callback (optional) */
3569
    if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
3570
        WOLFSSL_MSG("Error setting up netRandom context");
3571
        wnr_destroy(wnr_ctx);
3572
        wnr_ctx = NULL;
3573
        wnr_poll_destroy();
3574
        ret = RNG_FAILURE_E;
3575
        goto out;
3576
    }
3577
3578
    wnr_inited = 1;
3579
3580
out:
3581
3582
    wc_UnLockMutex(&wnr_mutex);
3583
3584
    return ret;
3585
}
3586
3587
/*
3588
 * Free global Whitewood netRandom context
3589
 * Returns 0 on success, negative on error
3590
 */
3591
int wc_FreeNetRandom(void)
3592
{
3593
    if (wnr_inited > 0) {
3594
3595
        if (wc_LockMutex(&wnr_mutex) != 0) {
3596
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
3597
            return BAD_MUTEX_E;
3598
        }
3599
3600
        if (wnr_ctx != NULL) {
3601
            wnr_destroy(wnr_ctx);
3602
            wnr_ctx = NULL;
3603
        }
3604
        wnr_poll_destroy();
3605
3606
        wc_UnLockMutex(&wnr_mutex);
3607
3608
#ifndef WOLFSSL_MUTEX_INITIALIZER
3609
        wc_FreeMutex(&wnr_mutex);
3610
        wnr_mutex_inited = 0;
3611
#endif
3612
3613
        wnr_inited = 0;
3614
    }
3615
3616
    return 0;
3617
}
3618
3619
#endif /* HAVE_WNR */
3620
3621
3622
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
3623
    defined(HAVE_AMD_RDSEED)
3624
3625
#ifdef WOLFSSL_ASYNC_CRYPT
3626
    /* need more retries if multiple cores */
3627
    #define INTELRD_RETRY (32 * 8)
3628
#else
3629
    #define INTELRD_RETRY 32
3630
#endif
3631
3632
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
3633
3634
#ifndef USE_INTEL_INTRINSICS
3635
3636
    /* return 0 on success */
3637
    static WC_INLINE int IntelRDseed64(word64* seed)
3638
    {
3639
        unsigned char ok;
3640
3641
        __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
3642
        return (ok) ? 0 : -1;
3643
    }
3644
3645
#else /* USE_INTEL_INTRINSICS */
3646
    /* The compiler Visual Studio uses does not allow inline assembly.
3647
     * It does allow for Intel intrinsic functions. */
3648
3649
    /* return 0 on success */
3650
# ifdef __GNUC__
3651
    __attribute__((target("rdseed")))
3652
# endif
3653
    static WC_INLINE int IntelRDseed64(word64* seed)
3654
    {
3655
        int ok;
3656
3657
        ok = _rdseed64_step((unsigned long long*) seed);
3658
        return (ok) ? 0 : -1;
3659
    }
3660
3661
#endif /* USE_INTEL_INTRINSICS */
3662
3663
/* return 0 on success */
3664
static WC_INLINE int IntelRDseed64_r(word64* rnd)
3665
{
3666
    int i;
3667
    for (i = 0; i < INTELRD_RETRY; i++) {
3668
        if (IntelRDseed64(rnd) == 0)
3669
            return 0;
3670
    }
3671
    return -1;
3672
}
3673
3674
/* return 0 on success */
3675
static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
3676
{
3677
    int ret;
3678
    word64 rndTmp;
3679
    static int rdseed_sanity_status = 0;
3680
3681
    (void)os;
3682
3683
    if (!IS_INTEL_RDSEED(intel_flags))
3684
        return -1;
3685
3686
    /* Note, access to rdseed_sanity_status is benignly racey on multithreaded
3687
     * targets.
3688
     */
3689
    if (rdseed_sanity_status == 0) {
3690
        word64 sanity_word1 = 0, sanity_word2 = 0;
3691
3692
        ret = IntelRDseed64_r(&sanity_word1);
3693
        if (ret != 0)
3694
            return ret;
3695
3696
        ret = IntelRDseed64_r(&sanity_word2);
3697
        if (ret != 0)
3698
            return ret;
3699
3700
        if (sanity_word1 == sanity_word2) {
3701
            ret = IntelRDseed64_r(&sanity_word1);
3702
            if (ret != 0)
3703
                return ret;
3704
3705
            if (sanity_word1 == sanity_word2) {
3706
#ifdef WC_VERBOSE_RNG
3707
                WOLFSSL_DEBUG_PRINTF(
3708
                    "WARNING: disabling RDSEED due to repeating word 0x%lx -- "
3709
                    "check CPU microcode version.", sanity_word2);
3710
#endif
3711
                rdseed_sanity_status = -1;
3712
                return -1;
3713
            }
3714
        }
3715
3716
        rdseed_sanity_status = 1;
3717
    }
3718
    else if (rdseed_sanity_status < 0) {
3719
        return -1;
3720
    }
3721
3722
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
3723
                                                    output += sizeof(word64)) {
3724
        ret = IntelRDseed64_r((word64*)output);
3725
        if (ret != 0)
3726
            return ret;
3727
    }
3728
    if (sz == 0)
3729
        return 0;
3730
3731
    /* handle unaligned remainder */
3732
    ret = IntelRDseed64_r(&rndTmp);
3733
    if (ret != 0)
3734
        return ret;
3735
3736
    XMEMCPY(output, &rndTmp, sz);
3737
    ForceZero(&rndTmp, sizeof(rndTmp));
3738
3739
    return 0;
3740
}
3741
3742
#endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3743
3744
#ifdef HAVE_INTEL_RDRAND
3745
3746
#ifndef USE_INTEL_INTRINSICS
3747
3748
/* return 0 on success */
3749
static WC_INLINE int IntelRDrand64(word64 *rnd)
3750
{
3751
    unsigned char ok;
3752
3753
    __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
3754
3755
    return (ok) ? 0 : -1;
3756
}
3757
3758
#else /* USE_INTEL_INTRINSICS */
3759
    /* The compiler Visual Studio uses does not allow inline assembly.
3760
     * It does allow for Intel intrinsic functions. */
3761
3762
/* return 0 on success */
3763
# ifdef __GNUC__
3764
__attribute__((target("rdrnd")))
3765
# endif
3766
static WC_INLINE int IntelRDrand64(word64 *rnd)
3767
{
3768
    int ok;
3769
3770
    ok = _rdrand64_step((unsigned long long*) rnd);
3771
3772
    return (ok) ? 0 : -1;
3773
}
3774
3775
#endif /* USE_INTEL_INTRINSICS */
3776
3777
/* return 0 on success */
3778
static WC_INLINE int IntelRDrand64_r(word64 *rnd)
3779
{
3780
    int i;
3781
    for (i = 0; i < INTELRD_RETRY; i++) {
3782
        if (IntelRDrand64(rnd) == 0)
3783
            return 0;
3784
    }
3785
    return -1;
3786
}
3787
3788
/* return 0 on success */
3789
static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
3790
{
3791
    int ret;
3792
    word64 rndTmp;
3793
3794
    (void)os;
3795
3796
    if (!IS_INTEL_RDRAND(intel_flags))
3797
        return -1;
3798
3799
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
3800
                                                    output += sizeof(word64)) {
3801
        ret = IntelRDrand64_r((word64 *)output);
3802
        if (ret != 0)
3803
            return ret;
3804
    }
3805
    if (sz == 0)
3806
        return 0;
3807
3808
    /* handle unaligned remainder */
3809
    ret = IntelRDrand64_r(&rndTmp);
3810
    if (ret != 0)
3811
        return ret;
3812
3813
    XMEMCPY(output, &rndTmp, sz);
3814
3815
    return 0;
3816
}
3817
3818
#endif /* HAVE_INTEL_RDRAND */
3819
#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3820
3821
3822
/* Begin wc_GenerateSeed Implementations */
3823
#if defined(CUSTOM_RAND_GENERATE_SEED)
3824
3825
    /* Implement your own random generation function
3826
     * Return 0 to indicate success
3827
     * int rand_gen_seed(byte* output, word32 sz);
3828
     * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
3829
3830
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3831
    {
3832
        (void)os; /* Suppress unused arg warning */
3833
        return CUSTOM_RAND_GENERATE_SEED(output, sz);
3834
    }
3835
3836
#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
3837
3838
    /* Implement your own random generation function,
3839
     *  which includes OS_Seed.
3840
     * Return 0 to indicate success
3841
     * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
3842
     * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
3843
3844
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3845
    {
3846
        return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
3847
    }
3848
3849
#elif defined(CUSTOM_RAND_GENERATE)
3850
3851
   /* Implement your own random generation function
3852
    * word32 rand_gen(void);
3853
    * #define CUSTOM_RAND_GENERATE  rand_gen  */
3854
3855
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3856
    {
3857
        word32 i = 0;
3858
3859
        (void)os;
3860
3861
        while (i < sz)
3862
        {
3863
            /* If not aligned or there is odd/remainder */
3864
            if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
3865
                ((wc_ptr_t)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
3866
            ) {
3867
                /* Single byte at a time */
3868
                output[i++] = (byte)CUSTOM_RAND_GENERATE();
3869
            }
3870
            else {
3871
                /* Use native 8, 16, 32 or 64 copy instruction */
3872
                *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
3873
                i += sizeof(CUSTOM_RAND_TYPE);
3874
            }
3875
        }
3876
3877
        return 0;
3878
    }
3879
3880
#elif defined(WOLFSSL_SGX)
3881
3882
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3883
{
3884
    int ret = !SGX_SUCCESS;
3885
    int i, read_max = 10;
3886
3887
    for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
3888
        ret = sgx_read_rand(output, sz);
3889
    }
3890
3891
    (void)os;
3892
    return (ret == SGX_SUCCESS) ? 0 : 1;
3893
}
3894
3895
#elif defined(USE_WINDOWS_API)
3896
3897
#ifdef WIN_REUSE_CRYPT_HANDLE
3898
/* shared crypt handle for RNG use */
3899
static ProviderHandle gHandle = 0;
3900
3901
int wc_WinCryptHandleInit(void)
3902
{
3903
    int ret = 0;
3904
    if (gHandle == 0) {
3905
        if(!CryptAcquireContext(&gHandle, 0, 0, PROV_RSA_FULL,
3906
                                        CRYPT_VERIFYCONTEXT)) {
3907
            DWORD dw = GetLastError();
3908
            WOLFSSL_MSG("CryptAcquireContext failed!");
3909
            WOLFSSL_ERROR((int)dw);
3910
            ret = WINCRYPT_E;
3911
        }
3912
    }
3913
    return ret;
3914
}
3915
3916
void wc_WinCryptHandleCleanup(void)
3917
{
3918
    if (gHandle != 0) {
3919
        CryptReleaseContext(gHandle, 0);
3920
        gHandle = 0;
3921
    }
3922
}
3923
#endif /* WIN_REUSE_CRYPT_HANDLE */
3924
3925
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3926
{
3927
#ifdef WOLF_CRYPTO_CB
3928
    int ret;
3929
3930
    if (os != NULL
3931
    #ifndef WOLF_CRYPTO_CB_FIND
3932
        && os->devId != INVALID_DEVID)
3933
    #endif
3934
    {
3935
        ret = wc_CryptoCb_RandomSeed(os, output, sz);
3936
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
3937
            return ret;
3938
        /* fall-through when unavailable */
3939
    }
3940
#endif
3941
3942
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
3943
        if (IS_INTEL_RDSEED(intel_flags)) {
3944
             if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
3945
                 /* success, we're done */
3946
                 return 0;
3947
             }
3948
        #ifdef FORCE_FAILURE_RDSEED
3949
             /* don't fall back to CryptoAPI */
3950
             return READ_RAN_E;
3951
        #endif
3952
        }
3953
    #ifdef FORCE_FAILURE_RDSEED
3954
        else {
3955
            /* Don't fall back to system randomness */
3956
            return MISSING_RNG_E;
3957
        }
3958
    #endif
3959
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3960
3961
#ifdef WIN_REUSE_CRYPT_HANDLE
3962
    /* Check that handle was initialized.
3963
     * Note: initialization should be done through:
3964
     * wolfSSL_Init -> wolfCrypt_Init -> wc_WinCryptHandleInit
3965
     */
3966
    if (wc_WinCryptHandleInit() != 0) {
3967
        return WINCRYPT_E;
3968
    }
3969
    if (!CryptGenRandom(gHandle, sz, output))
3970
        return CRYPTGEN_E;
3971
#else
3972
    if (!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
3973
                            CRYPT_VERIFYCONTEXT)) {
3974
        return WINCRYPT_E;
3975
    }
3976
    if (!CryptGenRandom(os->handle, sz, output)) {
3977
        return CRYPTGEN_E;
3978
    }
3979
    CryptReleaseContext(os->handle, 0);
3980
    os->handle = 0;
3981
#endif
3982
3983
    return 0;
3984
}
3985
3986
3987
#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
3988
3989
#include "rtprand.h"   /* rtp_rand () */
3990
3991
#if (defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)))
3992
#include "rtptime.h"   /* rtp_get_system_msec() */
3993
3994
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3995
{
3996
    word32 i;
3997
3998
    rtp_srand(rtp_get_system_msec());
3999
    for (i = 0; i < sz; i++ ) {
4000
        output[i] = rtp_rand() % 256;
4001
    }
4002
4003
    return 0;
4004
}
4005
#else
4006
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4007
{
4008
    word32 i;
4009
    KS_SEED(ks_get_ticks());
4010
4011
    for (i = 0; i < sz; i++ ) {
4012
        output[i] = KS_RANDOM() % 256;
4013
    }
4014
4015
    return 0;
4016
}
4017
#endif /* defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)) */
4018
4019
#elif (defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC_RNG)) && \
4020
      !defined(WOLFSSL_PIC32MZ_RNG)
4021
    /* enable ATECC RNG unless using PIC32MZ one instead */
4022
    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
4023
4024
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4025
    {
4026
        int ret = 0;
4027
4028
        (void)os;
4029
        if (output == NULL) {
4030
            return BUFFER_E;
4031
        }
4032
4033
        ret = atmel_get_random_number(sz, output);
4034
4035
        return ret;
4036
    }
4037
4038
#elif defined(MICROCHIP_PIC32) || defined(MICROCHIP_MPLAB_HARMONY)
4039
4040
    #ifdef MICROCHIP_MPLAB_HARMONY
4041
        #ifdef MICROCHIP_MPLAB_HARMONY_3
4042
            #include "system/time/sys_time.h"
4043
            #define PIC32_SEED_COUNT SYS_TIME_CounterGet
4044
        #else
4045
            #define PIC32_SEED_COUNT _CP0_GET_COUNT
4046
        #endif
4047
    #else
4048
        #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
4049
            #include <peripheral/timer.h>
4050
        #endif
4051
        extern word32 ReadCoreTimer(void);
4052
        #define PIC32_SEED_COUNT ReadCoreTimer
4053
    #endif
4054
4055
    #ifdef WOLFSSL_PIC32MZ_RNG
4056
        #include "xc.h"
4057
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4058
        {
4059
            int i;
4060
            byte rnd[8];
4061
            word32 *rnd32 = (word32 *)rnd;
4062
            word32 size = sz;
4063
            byte* op = output;
4064
4065
#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
4066
            RNGNUMGEN1 = _CP0_GET_COUNT();
4067
            RNGPOLY1 = _CP0_GET_COUNT();
4068
            RNGPOLY2 = _CP0_GET_COUNT();
4069
            RNGNUMGEN2 = _CP0_GET_COUNT();
4070
#else
4071
            /* All others can be seeded from the TRNG */
4072
            RNGCONbits.TRNGMODE = 1;
4073
            RNGCONbits.TRNGEN = 1;
4074
            while (RNGCNT < 64);
4075
            RNGCONbits.LOAD = 1;
4076
            while (RNGCONbits.LOAD == 1);
4077
            while (RNGCNT < 64);
4078
            RNGPOLY2 = RNGSEED2;
4079
            RNGPOLY1 = RNGSEED1;
4080
#endif
4081
4082
            RNGCONbits.PLEN = 0x40;
4083
            RNGCONbits.PRNGEN = 1;
4084
            for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
4085
                volatile int x, y;
4086
                x = RNGNUMGEN1;
4087
                y = RNGNUMGEN2;
4088
                (void)x;
4089
                (void)y;
4090
            }
4091
            do {
4092
                rnd32[0] = RNGNUMGEN1;
4093
                rnd32[1] = RNGNUMGEN2;
4094
4095
                for(i=0; i<8; i++, op++) {
4096
                    *op = rnd[i];
4097
                    size --;
4098
                    if(size==0)break;
4099
                }
4100
            } while(size);
4101
            return 0;
4102
        }
4103
    #else  /* WOLFSSL_PIC32MZ_RNG */
4104
        /* uses the core timer, in nanoseconds to seed srand */
4105
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4106
        {
4107
            int i;
4108
            srand(PIC32_SEED_COUNT() * 25);
4109
4110
            for (i = 0; i < sz; i++ ) {
4111
                output[i] = rand() % 256;
4112
                if ( (i % 8) == 7)
4113
                    srand(PIC32_SEED_COUNT() * 25);
4114
            }
4115
            return 0;
4116
        }
4117
    #endif /* WOLFSSL_PIC32MZ_RNG */
4118
4119
#elif defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
4120
    /*
4121
     * wc_Generates a RNG seed using the Random Number Generator Accelerator
4122
     * on the Kinetis K70. Documentation located in Chapter 37 of
4123
     * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
4124
     */
4125
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4126
    {
4127
        word32 i;
4128
4129
        /* turn on RNGA module */
4130
        #if defined(SIM_SCGC3_RNGA_MASK)
4131
            SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
4132
        #endif
4133
        #if defined(SIM_SCGC6_RNGA_MASK)
4134
            /* additionally needed for at least K64F */
4135
            SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
4136
        #endif
4137
4138
        /* set SLP bit to 0 - "RNGA is not in sleep mode" */
4139
        RNG_CR &= ~RNG_CR_SLP_MASK;
4140
4141
        /* set HA bit to 1 - "security violations masked" */
4142
        RNG_CR |= RNG_CR_HA_MASK;
4143
4144
        /* set GO bit to 1 - "output register loaded with data" */
4145
        RNG_CR |= RNG_CR_GO_MASK;
4146
4147
        for (i = 0; i < sz; i++) {
4148
4149
            /* wait for RNG FIFO to be full */
4150
            while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
4151
4152
            /* get value */
4153
            output[i] = RNG_OR;
4154
        }
4155
4156
        return 0;
4157
    }
4158
4159
#elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
4160
    /*
4161
     * wc_Generates a RNG seed using the Random Number Generator (RNGB)
4162
     * on the Kinetis K53. Documentation located in Chapter 33 of
4163
     * K53 Sub-Family Reference Manual (see note in the README for link).
4164
     */
4165
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4166
    {
4167
        int i;
4168
4169
        /* turn on RNGB module */
4170
        SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
4171
4172
        /* reset RNGB */
4173
        RNG_CMD |= RNG_CMD_SR_MASK;
4174
4175
        /* FIFO generate interrupt, return all zeros on underflow,
4176
         * set auto reseed */
4177
        RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
4178
4179
        /* gen seed, clear interrupts, clear errors */
4180
        RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
4181
4182
        /* wait for seeding to complete */
4183
        while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
4184
4185
        for (i = 0; i < sz; i++) {
4186
4187
            /* wait for a word to be available from FIFO */
4188
            while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
4189
4190
            /* get value */
4191
            output[i] = RNG_OUT;
4192
        }
4193
4194
        return 0;
4195
    }
4196
4197
#elif defined(FREESCALE_KSDK_2_0_TRNG)
4198
    #ifndef TRNG0
4199
    #define TRNG0 TRNG
4200
    #endif
4201
4202
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4203
    {
4204
        status_t status;
4205
        status = TRNG_GetRandomData(TRNG0, output, sz);
4206
        (void)os;
4207
        if (status == kStatus_Success)
4208
        {
4209
            return(0);
4210
        }
4211
        return RAN_BLOCK_E;
4212
    }
4213
4214
#elif defined(FREESCALE_KSDK_2_0_RNGA)
4215
4216
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4217
    {
4218
        status_t status;
4219
        status = RNGA_GetRandomData(RNG, output, sz);
4220
        (void)os;
4221
        if (status == kStatus_Success)
4222
        {
4223
            return(0);
4224
        }
4225
        return RAN_BLOCK_E;
4226
    }
4227
4228
4229
#elif defined(FREESCALE_RNGA)
4230
4231
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4232
    {
4233
        status_t status;
4234
        status = RNGA_GetRandomData(RNG, output, sz);
4235
        (void)os;
4236
        if (status == kStatus_Success)
4237
        {
4238
            return(0);
4239
        }
4240
        return RAN_BLOCK_E;
4241
    }
4242
#elif !defined(WOLFSSL_CAAM) && \
4243
    (defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
4244
     defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS))
4245
    /*
4246
     * Fallback to USE_TEST_GENSEED if a FREESCALE platform did not match any
4247
     * of the TRNG/RNGA/RNGB support
4248
     */
4249
    #define USE_TEST_GENSEED
4250
4251
#elif defined(WOLFSSL_SILABS_SE_ACCEL)
4252
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4253
    {
4254
        (void)os;
4255
        return silabs_GenerateRand(output, sz);
4256
    }
4257
4258
#elif defined(STM32_RNG)
4259
     /* Generate a RNG seed using the hardware random number generator
4260
      * on the STM32F2/F4/F7/L4. */
4261
    #include <wolfssl/wolfcrypt/port/st/stm32.h>
4262
        /* Pulls in WC_STM32_RNG_CLK_ENABLE for WOLFSSL_STM32_BARE builds */
4263
    #ifdef WC_STM32_RNG_DIAG
4264
        /* The WC_STM32_RNG_DIAG paths below use printf(); pull in stdio.h so the
4265
         * file compiles on strict C99+ toolchains when diagnostics are enabled. */
4266
        #include <stdio.h>
4267
    #endif
4268
4269
4270
    #ifdef WOLFSSL_STM32_CUBEMX
4271
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4272
    {
4273
        int ret;
4274
        RNG_HandleTypeDef hrng;
4275
        word32 i = 0;
4276
        (void)os;
4277
4278
        ret = wolfSSL_CryptHwMutexLock();
4279
        if (ret != 0) {
4280
            return ret;
4281
        }
4282
4283
        /* enable RNG clock source */
4284
        __HAL_RCC_RNG_CLK_ENABLE();
4285
4286
        /* enable RNG peripheral */
4287
        XMEMSET(&hrng, 0, sizeof(hrng));
4288
        hrng.Instance = RNG;
4289
        HAL_RNG_Init(&hrng);
4290
4291
        while (i < sz) {
4292
            /* If not aligned or there is odd/remainder */
4293
            if( (i + sizeof(word32)) > sz ||
4294
                ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
4295
            ) {
4296
                /* Single byte at a time */
4297
                uint32_t tmpRng = 0;
4298
                if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) {
4299
                    wolfSSL_CryptHwMutexUnLock();
4300
                    return RAN_BLOCK_E;
4301
                }
4302
                output[i++] = (byte)tmpRng;
4303
            }
4304
            else {
4305
                /* Use native 32 instruction */
4306
                if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) {
4307
                    wolfSSL_CryptHwMutexUnLock();
4308
                    return RAN_BLOCK_E;
4309
                }
4310
                i += sizeof(word32);
4311
            }
4312
        }
4313
4314
        HAL_RNG_DeInit(&hrng);
4315
4316
        wolfSSL_CryptHwMutexUnLock();
4317
4318
        return 0;
4319
    }
4320
    #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB) \
4321
        || defined(STM32_NUTTX_RNG)
4322
4323
    #ifdef STM32_NUTTX_RNG
4324
        #include "hardware/stm32_rng.h"
4325
        /* Set CONFIG_STM32U5_RNG in NuttX to enable the RCC */
4326
        #define WC_RNG_CR *((volatile uint32_t*)(STM32_RNG_CR))
4327
        #define WC_RNG_SR *((volatile uint32_t*)(STM32_RNG_SR))
4328
        #define WC_RNG_DR *((volatile uint32_t*)(STM32_RNG_DR))
4329
    #else
4330
        /* Comes from "stm32xxxx_hal.h" */
4331
        #define WC_RNG_CR RNG->CR
4332
        #define WC_RNG_SR RNG->SR
4333
        #define WC_RNG_DR RNG->DR
4334
    #endif
4335
4336
4337
    /* Bounded poll for DRDY, plus recovery from SECS / CECS. The
4338
     * unbounded `while (DRDY == 0)` loop in the original code spins
4339
     * forever on chips where the RNG kernel clock is unstable
4340
     * (e.g. WL55 with RNGSEL = MSI under sustained ECDSA-key-gen
4341
     * load), because once the IP latches a Seed-error or Clock-
4342
     * error condition it stops asserting DRDY. Per the STM32 RM
4343
     * recovery sequence: clear SEIS/CEIS, toggle RNGEN, discard the
4344
     * stale words sitting in the RNG output, then retry. */
4345
    #ifndef STM32_BARE_RNG_BYTE_TIMEOUT
4346
        #define STM32_BARE_RNG_BYTE_TIMEOUT 0x40000
4347
    #endif
4348
    #ifndef STM32_BARE_RNG_MAX_RETRIES
4349
        #define STM32_BARE_RNG_MAX_RETRIES 8
4350
    #endif
4351
4352
    /* Bring the direct-register RNG to a producing state: clock enable, the
4353
     * new-gen (C5) NIST conditioning under CONDRST on the first call, and
4354
     * RNGEN. Mutex-free -- the caller must already hold the crypto HW mutex.
4355
     * Shared by wc_GenerateSeed (below) and the SAES self-init path
4356
     * (Stm32SaesEnsureRng), so a cold DHUK/SAES operation no longer requires a
4357
     * prior wc_InitRng. Returns 0, or RNG_FAILURE_E if the conditioning
4358
     * soft-reset never clears. */
4359
    WOLFSSL_LOCAL int wc_stm32_rng_ensure_ready(void)
4360
    {
4361
        word32 t = 0;
4362
        (void)t;
4363
4364
    #ifndef STM32_NUTTX_RNG
4365
        /* enable RNG peripheral clock */
4366
        #ifdef WC_STM32_RNG_CLK_ENABLE
4367
            WC_STM32_RNG_CLK_ENABLE();
4368
        #else
4369
            /* Default for F4/F7/L4/L5/U5/H5/H7 -- RNG on AHB2 */
4370
            RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
4371
        #endif
4372
    #endif
4373
4374
        /* On the new-gen STM32C5 RNG IP the CR register is locked at
4375
         * reset (CONFIGLOCK clear, but the IP refuses to produce data
4376
         * until a NIST-compliant CONFIG1/2/3 + NSCR + HTCR sequence
4377
         * has been written under CONDRST). The HAL ships canonical
4378
         * candidate values in the device header (RNG_CAND_NIST_*).
4379
         * Detect the family by presence of that symbol -- on chips
4380
         * without it (F4/F7/L4/U5/H7/H5/WL/etc.) skip. Do this only
4381
         * on the first call (RNGEN clear) so subsequent calls don't
4382
         * disturb a running peripheral. */
4383
    #if defined(RNG_CAND_NIST_CR_VALUE) && defined(RNG_CR_CONDRST) && \
4384
        !defined(WC_STM32_RNG_NO_NIST_INIT)
4385
        if ((WC_RNG_CR & RNG_CR_RNGEN) == 0U) {
4386
        #ifdef RNG_SR_BUSY
4387
            /* HAL flow: drain BUSY before writing CR. */
4388
            t = 0;
4389
            while ((WC_RNG_SR & RNG_SR_BUSY) != 0U) {
4390
                if (++t >= STM32_BARE_RNG_BYTE_TIMEOUT) {
4391
                    break;
4392
                }
4393
            }
4394
        #endif
4395
            WC_RNG_CR = (uint32_t)RNG_CAND_NIST_CR_VALUE |
4396
                        (uint32_t)RNG_CR_CONDRST;
4397
        #ifdef RNG_CAND_NIST_NSCR_VALUE
4398
            RNG->NSCR = (uint32_t)RNG_CAND_NIST_NSCR_VALUE;
4399
        #endif
4400
        #ifdef RNG_CAND_NIST_HTCR_VALUE
4401
            RNG->HTCR[0] = (uint32_t)RNG_CAND_NIST_HTCR_VALUE;
4402
        #endif
4403
            /* Clear CONDRST and wait for the IP to mirror it back. The
4404
             * STM32 HAL polls RNG_CR.CONDRST (not SR.BUSY) for completion
4405
             * of the conditioning soft-reset; SR.BUSY drops earlier in
4406
             * the seed-pull pipeline on at least the C5 IP and reading
4407
             * it as "conditioning done" trips a SECS=1 a few microseconds
4408
             * later when RNGEN goes high. Bounded so a misconfigured
4409
             * kernel clock returns a clean error instead of hanging. */
4410
            WC_RNG_CR &= ~(uint32_t)RNG_CR_CONDRST;
4411
            t = 0;
4412
            while ((WC_RNG_CR & RNG_CR_CONDRST) != 0U) {
4413
                if (++t >= STM32_BARE_RNG_BYTE_TIMEOUT) {
4414
#ifdef WC_STM32_RNG_DIAG
4415
                    printf("[RNG] CONDRST stuck CR=%08lx SR=%08lx\n",
4416
                           (unsigned long)WC_RNG_CR,
4417
                           (unsigned long)WC_RNG_SR);
4418
#endif
4419
                    return RNG_FAILURE_E;
4420
                }
4421
            }
4422
#ifdef WC_STM32_RNG_DIAG
4423
            printf("[RNG] post-NIST CR=%08lx SR=%08lx t=%lu\n",
4424
                   (unsigned long)WC_RNG_CR,
4425
                   (unsigned long)WC_RNG_SR,
4426
                   (unsigned long)t);
4427
#endif
4428
        }
4429
    #endif
4430
4431
        /* enable RNG interrupt, set IE bit in RNG->CR register */
4432
        WC_RNG_CR |= RNG_CR_IE;
4433
4434
        /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
4435
         * RNG_LFSR, and error detector. WC_STM32_RNG_CED_DISABLE
4436
         * additionally sets CR.CED=1 to suppress the clock-error
4437
         * detection -- the Linux STM32 RNG driver does this and on
4438
         * the C5 silicon the CED detector trips on a (perfectly fine)
4439
         * 48 MHz kernel clock for reasons unclear in the RM. */
4440
#ifdef WC_STM32_RNG_CED_DISABLE
4441
        WC_RNG_CR |= RNG_CR_RNGEN | RNG_CR_CED;
4442
#else
4443
        WC_RNG_CR |= RNG_CR_RNGEN;
4444
#endif
4445
4446
        return 0;
4447
    }
4448
4449
    /* Generate a RNG seed using the hardware RNG on the STM32F427
4450
     * directly, following steps outlined in STM32F4 Reference
4451
     * Manual (Chapter 24) for STM32F4xx family. */
4452
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4453
    {
4454
        int ret;
4455
        word32 i;
4456
        word32 t;
4457
        word32 guard;
4458
        word32 retries;
4459
        word32 sr;
4460
        (void)os;
4461
4462
        ret = wolfSSL_CryptHwMutexLock();
4463
        if (ret != 0) {
4464
            return ret;
4465
        }
4466
4467
        /* Clock enable + (C5) NIST conditioning + RNGEN, shared with the SAES
4468
         * self-init path. Mutex-free helper; we hold the mutex. */
4469
        ret = wc_stm32_rng_ensure_ready();
4470
        if (ret != 0) {
4471
            wolfSSL_CryptHwMutexUnLock();
4472
            return ret;
4473
        }
4474
4475
        /* (No early SECS/CECS bail here.) The HAL doesn't check error
4476
         * status immediately after RNGEN -- the IP needs a few cycles
4477
         * after enable for the first seed pull, and a transient SEIS/SECS
4478
         * can latch and resolve itself through the auto-reset that the
4479
         * retry loop below already handles. Bailing here returned
4480
         * RNG_FAILURE_E (-199) on first-init on the STM32C5 silicon.
4481
         * NOTE: this branch serves all direct-register STM32 RNG users
4482
         * (WOLFSSL_STM32F427_RNG / WOLFSSL_STM32_RNG_NOLIB / STM32_NUTTX_RNG),
4483
         * not only the BARE/C5 port, so this bounded-retry + recovery applies
4484
         * to every NOLIB family. It is strictly more robust than the old early
4485
         * fast-fail: it still returns RNG_FAILURE_E after the retry budget. */
4486
4487
        for (i = 0; i < sz; i++) {
4488
            retries = 0;
4489
            for (;;) {
4490
                t = 0;
4491
                /* Sample SR once before the loop so the post-loop
4492
                 * happy-path / error checks have a defined value even
4493
                 * if STM32_BARE_RNG_BYTE_TIMEOUT is configured to 0. */
4494
                sr = WC_RNG_SR;
4495
                /* Bounded DRDY poll -- breaks on either DRDY or any
4496
                 * error indication (SECS/CECS). */
4497
                while (t < STM32_BARE_RNG_BYTE_TIMEOUT) {
4498
                    sr = WC_RNG_SR;
4499
                    if ((sr & (RNG_SR_DRDY | RNG_SR_SECS |
4500
                               RNG_SR_CECS)) != 0U) {
4501
                        break;
4502
                    }
4503
                    t++;
4504
                }
4505
4506
                /* Happy path: data ready and no error. */
4507
                if ((sr & RNG_SR_DRDY) != 0U &&
4508
                    (sr & (RNG_SR_SECS | RNG_SR_CECS)) == 0U) {
4509
                    output[i] = WC_RNG_DR;
4510
                    break;
4511
                }
4512
4513
                /* Either timed out or an error latched. Recover. */
4514
                if (++retries > STM32_BARE_RNG_MAX_RETRIES) {
4515
#ifdef WC_STM32_RNG_DIAG
4516
                    printf("[RNG] retry max byte=%lu sr=%08lx CR=%08lx\n",
4517
                           (unsigned long)i,
4518
                           (unsigned long)sr,
4519
                           (unsigned long)WC_RNG_CR);
4520
#endif
4521
                    wolfSSL_CryptHwMutexUnLock();
4522
                    return RNG_FAILURE_E;
4523
                }
4524
#ifdef WC_STM32_RNG_DIAG
4525
                printf("[RNG] retry byte=%lu retries=%lu sr=%08lx\n",
4526
                       (unsigned long)i,
4527
                       (unsigned long)retries,
4528
                       (unsigned long)sr);
4529
#endif
4530
4531
                /* Recovery sequence (per STM32 RM RNG chapter):
4532
                 *   1. Clear SEIS / CEIS interrupt status by writing 0
4533
                 *      to those bits. All other SR bits are read-only
4534
                 *      status indicators (DRDY / BUSY / SECS / CECS);
4535
                 *      writing 0 to them has no effect per the RM, so
4536
                 *      a plain 0 write is safe and avoids the
4537
                 *      read-modify-write hitting any reserved bits the
4538
                 *      IP revision may add later.
4539
                 *   2. Toggle RNGEN off then on to drop any stale
4540
                 *      LFSR state that may be tainted by the error.
4541
                 *   3. Discard four DR reads to flush the pipeline
4542
                 *      (only meaningful when DRDY is set; otherwise
4543
                 *      the reads are harmless and bounded). The 'guard'
4544
                 *      counter bounds the loop independently of 't' so a
4545
                 *      marginal kernel clock (DRDY stays 0, no error
4546
                 *      latched) cannot spin forever -- it falls through
4547
                 *      to the outer retry/backoff instead of hanging. */
4548
                WC_RNG_SR = 0;
4549
                WC_RNG_CR &= ~RNG_CR_RNGEN;
4550
                WC_RNG_CR |= RNG_CR_RNGEN;
4551
                t = 0;
4552
                guard = 0;
4553
                while (t < 4U && guard < STM32_BARE_RNG_BYTE_TIMEOUT) {
4554
                    guard++;
4555
                    if ((WC_RNG_SR & RNG_SR_DRDY) != 0U) {
4556
                        (void)WC_RNG_DR;
4557
                        t++;
4558
                    }
4559
                    else if ((WC_RNG_SR &
4560
                              (RNG_SR_SECS | RNG_SR_CECS)) != 0U) {
4561
                        /* Clock-error during recovery -- bail and
4562
                         * let the outer retry handle it. */
4563
                        break;
4564
                    }
4565
                }
4566
            }
4567
        }
4568
4569
        wolfSSL_CryptHwMutexUnLock();
4570
4571
        return 0;
4572
    }
4573
4574
    #else
4575
4576
    /* Generate a RNG seed using the STM32 Standard Peripheral Library */
4577
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4578
    {
4579
        int ret;
4580
        word32 i;
4581
        (void)os;
4582
4583
        ret = wolfSSL_CryptHwMutexLock();
4584
        if (ret != 0) {
4585
            return ret;
4586
        }
4587
4588
        /* enable RNG clock source */
4589
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
4590
4591
        /* reset RNG */
4592
        RNG_DeInit();
4593
4594
        /* enable RNG peripheral */
4595
        RNG_Cmd(ENABLE);
4596
4597
        /* verify no errors with RNG_CLK or Seed */
4598
        if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) {
4599
            wolfSSL_CryptHwMutexUnLock();
4600
            return RNG_FAILURE_E;
4601
        }
4602
4603
        for (i = 0; i < sz; i++) {
4604
            /* wait until RNG number is ready */
4605
            while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
4606
4607
            /* get value */
4608
            output[i] = RNG_GetRandomNumber();
4609
        }
4610
4611
        wolfSSL_CryptHwMutexUnLock();
4612
4613
        return 0;
4614
    }
4615
    #endif /* WOLFSSL_STM32_CUBEMX */
4616
4617
#elif defined(WOLFSSL_TIRTOS)
4618
    #warning "potential for not enough entropy, currently being used for testing"
4619
    #include <xdc/runtime/Timestamp.h>
4620
    #include <stdlib.h>
4621
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4622
    {
4623
        int i;
4624
        srand(xdc_runtime_Timestamp_get32());
4625
4626
        for (i = 0; i < sz; i++ ) {
4627
            output[i] = rand() % 256;
4628
            if ((i % 8) == 7) {
4629
                srand(xdc_runtime_Timestamp_get32());
4630
            }
4631
        }
4632
4633
        return 0;
4634
    }
4635
4636
#elif defined(WOLFSSL_PB)
4637
4638
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4639
    {
4640
        word32 i;
4641
        for (i = 0; i < sz; i++)
4642
            output[i] = UTL_Rand();
4643
4644
        (void)os;
4645
4646
        return 0;
4647
    }
4648
4649
#elif defined(WOLFSSL_NUCLEUS)
4650
#include "nucleus.h"
4651
#include "kernel/plus_common.h"
4652
4653
#warning "potential for not enough entropy, currently being used for testing"
4654
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4655
{
4656
    int i;
4657
    srand(NU_Get_Time_Stamp());
4658
4659
    for (i = 0; i < sz; i++ ) {
4660
        output[i] = rand() % 256;
4661
        if ((i % 8) == 7) {
4662
            srand(NU_Get_Time_Stamp());
4663
        }
4664
    }
4665
4666
    return 0;
4667
}
4668
#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE)
4669
    #include "stdlib.h"
4670
4671
    #warning "potential for not enough entropy, currently being used for testing Deos"
4672
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4673
    {
4674
        int i;
4675
        int seed = XTIME(0);
4676
        (void)os;
4677
4678
        for (i = 0; i < sz; i++ ) {
4679
            output[i] = rand_r(&seed) % 256;
4680
            if ((i % 8) == 7) {
4681
                seed = XTIME(0);
4682
                rand_r(&seed);
4683
            }
4684
        }
4685
4686
        return 0;
4687
    }
4688
#elif defined(WOLFSSL_VXWORKS)
4689
    #ifdef WOLFSSL_VXWORKS_6_x
4690
        #include "stdlib.h"
4691
        #warning "potential for not enough entropy, currently being used for testing"
4692
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4693
        {
4694
            int i;
4695
            unsigned int seed = (unsigned int)XTIME(0);
4696
            (void)os;
4697
4698
            for (i = 0; i < sz; i++ ) {
4699
                output[i] = rand_r(&seed) % 256;
4700
                if ((i % 8) == 7) {
4701
                    seed = (unsigned int)XTIME(0);
4702
                    rand_r(&seed);
4703
                }
4704
            }
4705
4706
            return 0;
4707
        }
4708
    #else
4709
        #include <randomNumGen.h>
4710
        #include <tickLib.h>
4711
4712
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
4713
            STATUS                status   = ERROR;
4714
            RANDOM_NUM_GEN_STATUS r_status = RANDOM_NUM_GEN_ERROR;
4715
            _Vx_ticks_t           seed = 0;
4716
4717
            #ifdef VXWORKS_SIM
4718
                /* cannot generate true entropy with VxWorks simulator */
4719
                #warning "not enough entropy, simulator for testing only"
4720
                int i = 0;
4721
4722
                for (i = 0; i < 1000; i++) {
4723
                    randomAddTimeStamp();
4724
                }
4725
            #endif
4726
4727
            /*
4728
              wolfSSL can request 52 Bytes of random bytes. We need to add
4729
              buffer to the entropy pool to ensure we can get more than 32 Bytes.
4730
              Because VxWorks has entropy limits (ENTROPY_MIN and ENTROPY_MAX)
4731
              defined as 256 and 1024 bits, see randomSWNumGenLib.c.
4732
4733
              randStatus() can return the following status:
4734
              RANDOM_NUM_GEN_NO_ENTROPY when entropy is 0
4735
              RANDOM_NUM_GEN_ERROR, entropy is not initialized
4736
              RANDOM_NUM_GEN_NOT_ENOUGH_ENTROPY if entropy < 32 Bytes
4737
              RANDOM_NUM_GEN_ENOUGH_ENTROPY if entropy is between 32 and 128 Bytes
4738
              RANDOM_NUM_GEN_MAX_ENTROPY if entropy is greater than 128 Bytes
4739
            */
4740
4741
            do {
4742
                seed = tickGet();
4743
                status = randAdd(&seed, sizeof(_Vx_ticks_t), 2);
4744
                if (status == OK)
4745
                    r_status = randStatus();
4746
4747
            } while (r_status != RANDOM_NUM_GEN_MAX_ENTROPY &&
4748
                     r_status != RANDOM_NUM_GEN_ERROR && status == OK);
4749
4750
            if (r_status == RANDOM_NUM_GEN_ERROR)
4751
                return RNG_FAILURE_E;
4752
4753
            status = randBytes (output, sz);
4754
4755
            if (status == ERROR) {
4756
                return RNG_FAILURE_E;
4757
            }
4758
4759
            return 0;
4760
        }
4761
    #endif
4762
#elif defined(WOLFSSL_NRF51) || defined(WOLFSSL_NRF5x)
4763
    #include "app_error.h"
4764
    #include "nrf_drv_rng.h"
4765
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4766
    {
4767
        int remaining = sz, pos = 0;
4768
        word32 err_code;
4769
        byte available;
4770
        static byte initialized = 0;
4771
4772
        (void)os;
4773
4774
        /* Make sure RNG is running */
4775
        if (!initialized) {
4776
            err_code = nrf_drv_rng_init(NULL);
4777
            if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE
4778
            #ifdef NRF_ERROR_MODULE_ALREADY_INITIALIZED
4779
                && err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED
4780
            #endif
4781
            ) {
4782
                return -1;
4783
            }
4784
            initialized = 1;
4785
        }
4786
4787
        while (remaining > 0) {
4788
            int length;
4789
            available = 0;
4790
            nrf_drv_rng_bytes_available(&available); /* void func */
4791
            length = (remaining < available) ? remaining : available;
4792
            if (length > 0) {
4793
                err_code = nrf_drv_rng_rand(&output[pos], length);
4794
                if (err_code != NRF_SUCCESS) {
4795
                    break;
4796
                }
4797
                remaining -= length;
4798
                pos += length;
4799
            }
4800
        }
4801
4802
        return (err_code == NRF_SUCCESS) ? 0 : -1;
4803
    }
4804
4805
#elif defined(HAVE_WNR)
4806
4807
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4808
    {
4809
        if (os == NULL || output == NULL || wnr_ctx == NULL ||
4810
                wnr_timeout < 0) {
4811
            return BAD_FUNC_ARG;
4812
        }
4813
4814
        if (wnr_mutex_init == 0) {
4815
            WOLFSSL_MSG("netRandom context must be created before use");
4816
            return RNG_FAILURE_E;
4817
        }
4818
4819
        if (wc_LockMutex(&wnr_mutex) != 0) {
4820
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
4821
            return BAD_MUTEX_E;
4822
        }
4823
4824
        if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
4825
                WNR_ERROR_NONE)
4826
            return RNG_FAILURE_E;
4827
4828
        wc_UnLockMutex(&wnr_mutex);
4829
4830
        return 0;
4831
    }
4832
4833
#elif defined(INTIME_RTOS)
4834
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4835
    {
4836
        uint32_t randval;
4837
        word32 len;
4838
4839
        if (output == NULL) {
4840
            return BUFFER_E;
4841
        }
4842
4843
    #ifdef INTIMEVER
4844
        /* If INTIMEVER exists then it is INTIME RTOS v6 or later */
4845
        #define INTIME_RAND_FUNC arc4random
4846
        len = 4;
4847
    #else
4848
        /* v5 and older */
4849
        #define INTIME_RAND_FUNC rand
4850
        srand(time(0));
4851
        len = 2; /* don't use all 31 returned bits */
4852
    #endif
4853
4854
        while (sz > 0) {
4855
            if (sz < len)
4856
                len = sz;
4857
            randval = INTIME_RAND_FUNC();
4858
            XMEMCPY(output, &randval, len);
4859
            output += len;
4860
            sz -= len;
4861
        }
4862
        (void)os;
4863
4864
        return 0;
4865
    }
4866
4867
#elif defined(WOLFSSL_WICED)
4868
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4869
    {
4870
        int ret;
4871
        (void)os;
4872
4873
        if (output == NULL || UINT16_MAX < sz) {
4874
            return BUFFER_E;
4875
        }
4876
4877
        if ((ret = wiced_crypto_get_random((void*) output, sz) )
4878
                         != WICED_SUCCESS) {
4879
            return ret;
4880
        }
4881
4882
        return ret;
4883
    }
4884
4885
#elif defined(WOLFSSL_NETBURNER)
4886
    #warning using NetBurner pseudo random GetRandomByte for seed
4887
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4888
    {
4889
        word32 i;
4890
        (void)os;
4891
4892
        if (output == NULL) {
4893
            return BUFFER_E;
4894
        }
4895
4896
        for (i = 0; i < sz; i++) {
4897
            output[i] = GetRandomByte();
4898
4899
            /* check if was a valid random number */
4900
            if (!RandomValid())
4901
                return RNG_FAILURE_E;
4902
        }
4903
4904
        return 0;
4905
    }
4906
#elif defined(IDIRECT_DEV_RANDOM)
4907
4908
    extern int getRandom( int sz, unsigned char *output );
4909
4910
    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4911
    {
4912
        int num_bytes_returned = 0;
4913
4914
        num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
4915
4916
        return 0;
4917
    }
4918
4919
#elif defined(WOLFSSL_CAAM)
4920
4921
    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
4922
4923
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4924
    {
4925
        unsigned int args[4] = {0};
4926
        CAAM_BUFFER buf[1];
4927
        int ret    = 0;
4928
        int times  = 1000, i; /* 1000 is an arbitrary number chosen */
4929
        word32 idx = 0;
4930
4931
        (void)os;
4932
4933
        if (output == NULL) {
4934
            return BUFFER_E;
4935
        }
4936
4937
        /* Check Waiting to make sure entropy is ready */
4938
        for (i = 0; i < times; i++) {
4939
            buf[0].BufferType = DataBuffer | LastBuffer;
4940
            buf[0].TheAddress = (CAAM_ADDRESS)(output + idx);
4941
            buf[0].Length     = ((sz - idx) < WC_CAAM_MAX_ENTROPY)?
4942
                                sz - idx : WC_CAAM_MAX_ENTROPY;
4943
4944
            args[0] = buf[0].Length;
4945
            ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY);
4946
            if (ret == 0) {
4947
                idx += buf[0].Length;
4948
                if (idx == sz)
4949
                    break;
4950
            }
4951
4952
            /* driver could be waiting for entropy */
4953
            if (ret != WC_NO_ERR_TRACE(RAN_BLOCK_E) && ret != 0) {
4954
                return ret;
4955
            }
4956
#ifndef WOLFSSL_IMXRT1170_CAAM
4957
            usleep(100);
4958
#endif
4959
        }
4960
4961
        if (i == times && ret != 0) {
4962
             return RNG_FAILURE_E;
4963
        }
4964
        else { /* Success case */
4965
            ret = 0;
4966
        }
4967
4968
        return ret;
4969
    }
4970
4971
#elif defined(WOLFSSL_APACHE_MYNEWT)
4972
4973
    #include <stdlib.h>
4974
    #include "os/os_time.h"
4975
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4976
    {
4977
        int i;
4978
        srand(os_time_get());
4979
4980
        for (i = 0; i < sz; i++ ) {
4981
            output[i] = rand() % 256;
4982
            if ((i % 8) == 7) {
4983
                srand(os_time_get());
4984
            }
4985
        }
4986
4987
        return 0;
4988
    }
4989
4990
#elif defined(ARDUINO)
4991
4992
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
4993
    {
4994
        int ret = 0;
4995
        word32 rand;
4996
        while (sz > 0) {
4997
            word32 len = sizeof(rand);
4998
            if (sz < len)
4999
                len = sz;
5000
        /* Get an Arduino framework random number */
5001
        #if defined(ARDUINO_SAMD_NANO_33_IOT) || \
5002
            defined(ARDUINO_ARCH_RP2040)
5003
            /* Known, tested boards working with random() */
5004
            rand = random();
5005
        #elif defined(ARDUINO_SAM_DUE)
5006
            /* See: https://github.com/avrxml/asf/tree/master/sam/utils/cmsis/sam3x/include */
5007
            #if defined(__SAM3A4C__)
5008
                #ifndef TRNG
5009
                    #define TRNG (0x400BC000U)
5010
                #endif
5011
            #elif defined(__SAM3A8C__)
5012
                #ifndef TRNG
5013
                    #define TRNG (0x400BC000U)
5014
                #endif
5015
            #elif defined(__SAM3X4C__)
5016
                #ifndef TRNG
5017
                    #define TRNG (0x400BC000U)
5018
                #endif
5019
            #elif defined(__SAM3X4E__)
5020
                #ifndef TRNG
5021
                    #define TRNG (0x400BC000U)
5022
                #endif
5023
            #elif defined(__SAM3X8C__)
5024
                #ifndef TRNG
5025
                    #define TRNG (0x400BC000U)
5026
                #endif
5027
            #elif defined(__SAM3X8E__)
5028
                /* This is the Arduino Due */
5029
                #ifndef TRNG
5030
                    #define TRNG (0x400BC000U)
5031
                #endif
5032
            #elif  defined(__SAM3A8H__)
5033
                #ifndef TRNG
5034
                    #define TRNG (0x400BC000U)
5035
                #endif
5036
            #else
5037
                #ifndef TRNG
5038
                    #error "Unknown TRNG for this device"
5039
                #endif
5040
            #endif
5041
5042
            srand(analogRead(0));
5043
            rand = trng_read_output_data(TRNG);
5044
        #elif defined(__STM32__)
5045
            /* TODO: confirm this is proper random number on Arduino STM32 */
5046
            #warning "Not yet tested on STM32 targets"
5047
            rand = random();
5048
        #else
5049
            /* TODO: Pull requests appreciated for new targets.
5050
             * Do *all* other Arduino boards support random()?
5051
             * Probably not 100%, but most will likely work: */
5052
            rand = random();
5053
        #endif
5054
5055
            XMEMCPY(output, &rand, len);
5056
            output += len;
5057
            sz -= len;
5058
        }
5059
5060
        return ret;
5061
    }
5062
5063
#elif defined(WOLFSSL_ESPIDF)
5064
5065
    /* Espressif */
5066
    #if defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE)
5067
5068
        /* Espressif ESP32 */
5069
        #include <esp_system.h>
5070
        #if defined(CONFIG_IDF_TARGET_ESP32S2) || \
5071
            defined(CONFIG_IDF_TARGET_ESP32S3)
5072
            #include <esp_random.h>
5073
        #endif
5074
5075
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5076
        {
5077
            word32 rand;
5078
            while (sz > 0) {
5079
                word32 len = sizeof(rand);
5080
                if (sz < len)
5081
                    len = sz;
5082
                /* Get one random 32-bit word from hw RNG */
5083
                rand = esp_random( );
5084
                XMEMCPY(output, &rand, len);
5085
                output += len;
5086
                sz -= len;
5087
            }
5088
5089
            return 0;
5090
        }
5091
5092
    #elif defined(WOLFSSL_ESP8266)
5093
5094
        /* Espressif ESP8266 */
5095
        #include <esp_system.h>
5096
5097
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5098
        {
5099
    #if defined(DEBUG_WOLFSSL)
5100
            WOLFSSL_ENTER("ESP8266 Random");
5101
    #endif
5102
            word32 rand;
5103
            while (sz > 0) {
5104
                word32 len = sizeof(rand);
5105
                if (sz < len)
5106
                    len = sz;
5107
                /* Get one random 32-bit word from hw RNG */
5108
                rand = esp_random( );
5109
                XMEMCPY(output, &rand, len);
5110
                output += len;
5111
                sz -= len;
5112
            }
5113
5114
            return 0;
5115
        }
5116
    #endif /* end WOLFSSL_ESPIDF */
5117
5118
#elif defined(WOLFSSL_LINUXKM)
5119
5120
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5121
    {
5122
        (void)os;
5123
        int ret = WC_NO_ERR_TRACE(RNG_FAILURE_E);
5124
5125
    #ifdef HAVE_ENTROPY_MEMUSE
5126
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
5127
        if (ret == 0)
5128
            return 0;
5129
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
5130
        return ret;
5131
        #endif
5132
    #endif
5133
5134
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
5135
        if (IS_INTEL_RDSEED(intel_flags)) {
5136
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
5137
            if (ret == 0)
5138
                return 0;
5139
            #ifdef FORCE_FAILURE_RDSEED
5140
            return ret;
5141
            #endif
5142
        }
5143
    #ifdef FORCE_FAILURE_RDSEED
5144
        else {
5145
            /* Don't fall back to get_random_bytes() */
5146
            return MISSING_RNG_E;
5147
        }
5148
    #endif
5149
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
5150
5151
    #ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
5152
        #if !defined(HAVE_ENTROPY_MEMUSE) && \
5153
            !defined(HAVE_INTEL_RDSEED) && \
5154
            !defined(HAVE_AMD_RDSEED)
5155
            #error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires an intrinsic entropy source.
5156
        #else
5157
            return ret;
5158
        #endif
5159
    #else
5160
        (void)ret;
5161
5162
        get_random_bytes(output, sz);
5163
        return 0;
5164
    #endif
5165
    }
5166
5167
#elif defined(WOLFSSL_BSDKM)
5168
    #include <sys/random.h>
5169
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5170
    {
5171
        (void)os;
5172
        int ret = WC_NO_ERR_TRACE(RNG_FAILURE_E);
5173
5174
    #ifdef HAVE_ENTROPY_MEMUSE
5175
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
5176
        if (ret == 0) {
5177
            return 0;
5178
        }
5179
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
5180
        /* Don't fallback to /dev/urandom. */
5181
        return ret;
5182
        #endif
5183
    #endif
5184
5185
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
5186
        if (IS_INTEL_RDSEED(intel_flags)) {
5187
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
5188
        #ifndef FORCE_FAILURE_RDSEED
5189
            if (ret == 0)
5190
        #endif
5191
            {
5192
                return ret;
5193
            }
5194
        }
5195
    #ifdef FORCE_FAILURE_RDSEED
5196
        else {
5197
            /* Don't fall back to arc4random_buf() */
5198
            return MISSING_RNG_E;
5199
        }
5200
    #endif
5201
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
5202
5203
        (void)ret;
5204
5205
        arc4random_buf(output, sz);
5206
        return 0;
5207
    }
5208
#elif defined(WOLFSSL_RENESAS_TSIP)
5209
5210
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5211
    {
5212
        (void)os;
5213
        return wc_tsip_GenerateRandBlock(output, sz);
5214
    }
5215
5216
5217
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
5218
    #include "hal_data.h"
5219
5220
    #ifndef WOLFSSL_SCE_TRNG_HANDLE
5221
        #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng
5222
    #endif
5223
5224
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5225
    {
5226
        word32 ret;
5227
        word32 blocks;
5228
        word32 len = sz;
5229
5230
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
5231
                                                  WOLFSSL_SCE_TRNG_HANDLE.p_cfg);
5232
        if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) {
5233
            /* error opening TRNG driver */
5234
            return -1;
5235
        }
5236
5237
        blocks = sz / sizeof(word32);
5238
        if (blocks > 0) {
5239
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
5240
                                                       (word32*)output, blocks);
5241
            if (ret != SSP_SUCCESS) {
5242
                return -1;
5243
            }
5244
        }
5245
5246
        len = len - (blocks * sizeof(word32));
5247
        if (len > 0) {
5248
            word32 tmp;
5249
5250
            if (len > sizeof(word32)) {
5251
                return -1;
5252
            }
5253
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
5254
                                                      (word32*)&tmp, 1);
5255
            if (ret != SSP_SUCCESS) {
5256
                return -1;
5257
            }
5258
            XMEMCPY(output + (blocks * sizeof(word32)), (byte*)&tmp, len);
5259
        }
5260
5261
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl);
5262
        if (ret != SSP_SUCCESS) {
5263
            /* error opening TRNG driver */
5264
            return -1;
5265
        }
5266
        return 0;
5267
    }
5268
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
5269
    /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
5270
     * extern int myRngFunc(byte* output, word32 sz);
5271
     */
5272
5273
#elif defined(__MICROBLAZE__)
5274
    #warning weak source of entropy
5275
    #define LPD_SCNTR_BASE_ADDRESS 0xFF250000
5276
5277
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5278
    {
5279
        word32* cnt;
5280
        word32 i;
5281
5282
        /* using current time with srand */
5283
        cnt = (word32*)LPD_SCNTR_BASE_ADDRESS;
5284
        srand(*cnt | *(cnt+1));
5285
5286
        for (i = 0; i < sz; i++)
5287
            output[i] = rand();
5288
5289
        (void)os;
5290
        return 0;
5291
    }
5292
5293
#elif defined(WOLFSSL_ZEPHYR)
5294
5295
    #ifdef __has_include
5296
        #if __has_include(<zephyr/version.h>)
5297
            #include <zephyr/version.h>
5298
        #else
5299
            #include <version.h>
5300
        #endif
5301
    #else
5302
        #include <version.h>
5303
    #endif
5304
5305
    #include <sys/types.h>
5306
5307
    #if KERNEL_VERSION_NUMBER >= 0x30500
5308
        #include <zephyr/random/random.h>
5309
    #else
5310
        #if KERNEL_VERSION_NUMBER >= 0x30100
5311
            #include <zephyr/random/rand32.h>
5312
        #else
5313
            #include <random/rand32.h>
5314
        #endif
5315
    #endif
5316
5317
    #if KERNEL_VERSION_NUMBER >= 0x40300
5318
        #include <time.h>
5319
    #elif KERNEL_VERSION_NUMBER >= 0x30100
5320
        #include <zephyr/posix/time.h>
5321
    #else
5322
        #include <posix/time.h>
5323
    #endif
5324
5325
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5326
    {
5327
        sys_rand_get(output, sz);
5328
        return 0;
5329
    }
5330
5331
#elif defined(WOLFSSL_TELIT_M2MB)
5332
5333
        #include "stdlib.h"
5334
        static long get_timestamp(void) {
5335
            long myTime = 0;
5336
            INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
5337
            if (fd >= 0) {
5338
                M2MB_RTC_TIMEVAL_T timeval;
5339
                m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
5340
                myTime = timeval.msec;
5341
                m2mb_rtc_close(fd);
5342
            }
5343
            return myTime;
5344
        }
5345
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5346
        {
5347
            int i;
5348
            srand(get_timestamp());
5349
            for (i = 0; i < sz; i++ ) {
5350
                output[i] = rand() % 256;
5351
                if ((i % 8) == 7) {
5352
                    srand(get_timestamp());
5353
                }
5354
            }
5355
            return 0;
5356
        }
5357
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_TRNG)
5358
     #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
5359
5360
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz){
5361
        int ret = 0;
5362
5363
        (void)os;
5364
5365
        if (output == NULL) {
5366
            return BUFFER_E;
5367
        }
5368
        ret = wolfSSL_CryptHwMutexLock();
5369
        if (ret == 0) {
5370
            ret = se050_get_random_number(sz, output);
5371
            wolfSSL_CryptHwMutexUnLock();
5372
        }
5373
        return ret;
5374
    }
5375
5376
#elif defined(WOLFSSL_NXP_RNG_1)
5377
    #include "fsl_rng.h"
5378
5379
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
5380
        (void)os;
5381
5382
        if (output == NULL) {
5383
            return BUFFER_E;
5384
        }
5385
5386
        if (RNG_GetRandomData(RNG, output, sz) != kStatus_Success)
5387
            return RNG_FAILURE_E;
5388
5389
        return 0;
5390
    }
5391
5392
#elif defined(DOLPHIN_EMULATOR) || defined (WOLFSSL_NDS)
5393
5394
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5395
        {
5396
            word32 i;
5397
            (void)os;
5398
            srand(time(NULL));
5399
            for (i = 0; i < sz; i++)
5400
                output[i] = (byte)rand();
5401
            return 0;
5402
        }
5403
#elif defined(WOLFSSL_MAXQ108X) || defined(WOLFSSL_MAXQ1065)
5404
5405
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5406
    {
5407
        (void)os;
5408
5409
        return maxq10xx_random(output, sz);
5410
    }
5411
#elif defined(MAX3266X_RNG)
5412
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5413
    {
5414
        int status;
5415
        static int initDone = 0;
5416
        (void)os;
5417
        if (initDone == 0) {
5418
            status = wolfSSL_HwRngMutexLock();
5419
            if (status != 0) {
5420
                return status;
5421
            }
5422
            if(MXC_TRNG_HealthTest() != 0) {
5423
                #ifdef DEBUG_WOLFSSL
5424
                WOLFSSL_MSG("TRNG HW Health Test Failed");
5425
                #endif /* DEBUG_WOLFSSL */
5426
                wolfSSL_HwRngMutexUnLock();
5427
                return WC_HW_E;
5428
            }
5429
            wolfSSL_HwRngMutexUnLock();
5430
            initDone = 1;
5431
        }
5432
        return wc_MXC_TRNG_Random(output, sz);
5433
    }
5434
5435
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
5436
5437
    /* Infineon/Cypress HAL RNG implementation */
5438
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5439
    {
5440
        cyhal_trng_t obj;
5441
        cy_rslt_t result;
5442
        uint32_t val;
5443
        word32 i = 0;
5444
5445
        (void)os;
5446
5447
        result = cyhal_trng_init(&obj);
5448
        if (result == CY_RSLT_SUCCESS) {
5449
            while (i < sz) {
5450
                /* If not aligned or there is odd/remainder add single byte */
5451
                if( (i + sizeof(word32)) > sz ||
5452
                    ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
5453
                ) {
5454
                    val = cyhal_trng_generate(&obj);
5455
                    output[i++] = (byte)val;
5456
                }
5457
                else {
5458
                    /* Use native 32 instruction */
5459
                    val = cyhal_trng_generate(&obj);
5460
                    *((uint32_t*)&output[i]) = val;
5461
                    i += sizeof(word32);
5462
                }
5463
            }
5464
            cyhal_trng_free(&obj);
5465
        }
5466
        return 0;
5467
    }
5468
5469
#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
5470
      defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
5471
      defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
5472
      defined(WOLFSSL_LPC43xx)  || defined(NO_STM32_RNG) || \
5473
      defined(MBED)             || defined(WOLFSSL_EMBOS) || \
5474
      defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
5475
      defined(WOLFSSL_CONTIKI)  || defined(WOLFSSL_AZSPHERE)
5476
5477
    /* these platforms do not have a default random seed and
5478
       you'll need to implement your own wc_GenerateSeed or define via
5479
       CUSTOM_RAND_GENERATE_BLOCK */
5480
5481
    #define USE_TEST_GENSEED
5482
5483
#elif defined(NO_DEV_RANDOM)
5484
5485
    /* Allow bare-metal targets to use cryptoCb as seed provider */
5486
    #if defined(WOLF_CRYPTO_CB)
5487
5488
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5489
    {
5490
        int ret = WC_NO_ERR_TRACE(WC_HW_E);
5491
5492
        #ifndef WOLF_CRYPTO_CB_FIND
5493
        if (os->devId != INVALID_DEVID)
5494
        #endif
5495
        {
5496
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
5497
            if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
5498
                ret = WC_HW_E;
5499
            }
5500
        }
5501
5502
        return ret;
5503
    }
5504
5505
    #else /* defined(WOLF_CRYPTO_CB)*/
5506
5507
    #error "you need to write an os specific wc_GenerateSeed() here"
5508
5509
    /*
5510
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5511
    {
5512
        return 0;
5513
    }
5514
    */
5515
5516
   #endif  /* !defined(WOLF_CRYPTO_CB) */
5517
5518
#else
5519
5520
    /* may block */
5521
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5522
108k
    {
5523
108k
        int ret = 0;
5524
5525
        /* Validate output before any entropy backend dereferences it: some
5526
         * (e.g. glibc's vDSO getrandom()) fault on a NULL buffer rather than
5527
         * returning an error. Mirrors wc_RNG_GenerateBlock's NULL check. */
5528
108k
        if (os == NULL || output == NULL) {
5529
0
            return BAD_FUNC_ARG;
5530
0
        }
5531
5532
108k
    #ifdef WOLF_CRYPTO_CB
5533
108k
        #ifndef WOLF_CRYPTO_CB_FIND
5534
108k
        if (os->devId != INVALID_DEVID)
5535
8
        #endif
5536
8
        {
5537
8
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
5538
8
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
5539
8
                return ret;
5540
            /* fall-through when unavailable */
5541
0
            ret = 0; /* reset error code */
5542
0
        }
5543
108k
    #endif
5544
5545
    #ifdef HAVE_ENTROPY_MEMUSE
5546
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
5547
        if (ret == 0) {
5548
            /* success, we're done */
5549
            return ret;
5550
        }
5551
    #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
5552
        /* Don't fall back to /dev/urandom. */
5553
        return ret;
5554
    #else
5555
        /* Reset error and fall back to using /dev/urandom. */
5556
        ret = 0;
5557
    #endif
5558
    #endif
5559
5560
108k
    #if !defined(HAVE_ENTROPY_MEMUSE) || !defined(ENTROPY_MEMUSE_FORCE_FAILURE)
5561
5562
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
5563
        if (IS_INTEL_RDSEED(intel_flags)) {
5564
             ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
5565
             if (ret == 0) {
5566
                 /* success, we're done */
5567
                 return ret;
5568
             }
5569
        #ifdef FORCE_FAILURE_RDSEED
5570
             /* Don't fall back to /dev/urandom. */
5571
             return ret;
5572
        #else
5573
             /* Reset error and fall back to using /dev/urandom. */
5574
             ret = 0;
5575
        #endif
5576
        }
5577
    #ifdef FORCE_FAILURE_RDSEED
5578
        else {
5579
            /* Don't fall back to /dev/urandom */
5580
            return MISSING_RNG_E;
5581
        }
5582
    #endif
5583
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
5584
5585
108k
    #if (!defined(HAVE_INTEL_RDSEED) && !defined(HAVE_AMD_RDSEED)) || \
5586
108k
        !defined(FORCE_FAILURE_RDSEED)
5587
5588
108k
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
5589
108k
        {
5590
108k
            word32 grSz = sz;
5591
108k
            byte* grOutput = output;
5592
5593
216k
            while (grSz) {
5594
108k
                ssize_t len;
5595
5596
108k
                errno = 0;
5597
108k
                len = getrandom(grOutput, grSz, 0);
5598
108k
                if (len == -1) {
5599
0
                    if (errno == EINTR) {
5600
                        /* interrupted, call getrandom again */
5601
0
                        continue;
5602
0
                    }
5603
0
                    else {
5604
0
                        ret = READ_RAN_E;
5605
0
                    }
5606
0
                    break;
5607
0
                }
5608
5609
108k
                grSz     -= (word32)len;
5610
108k
                grOutput += len;
5611
108k
            }
5612
108k
            if (ret == 0)
5613
108k
                return ret;
5614
        #ifdef FORCE_FAILURE_GETRANDOM
5615
            /* don't fall back to /dev/urandom */
5616
            return ret;
5617
        #elif !defined(NO_FILESYSTEM)
5618
            /* reset error and fall back to using /dev/urandom if filesystem
5619
             * support is compiled in */
5620
0
            ret = 0;
5621
0
        #endif
5622
0
        }
5623
0
    #endif
5624
5625
0
#ifndef NO_FILESYSTEM
5626
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
5627
        if (!os->seedFdOpen)
5628
        {
5629
        #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
5630
            os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
5631
            #if defined(DEBUG_WOLFSSL)
5632
                WOLFSSL_MSG("opened /dev/urandom.");
5633
            #endif /* DEBUG_WOLFSSL */
5634
            if (os->fd == XBADFD)
5635
        #endif /* NO_DEV_URANDOM */
5636
            {
5637
                /* may still have /dev/random */
5638
                os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
5639
            #if defined(DEBUG_WOLFSSL)
5640
                WOLFSSL_MSG("opened /dev/random.");
5641
            #endif /* DEBUG_WOLFSSL */
5642
                if (os->fd == XBADFD)
5643
                    return OPEN_RAN_E;
5644
                else {
5645
                    os->keepSeedFdOpen = 0;
5646
                    os->seedFdOpen = 1;
5647
                }
5648
            }
5649
            else {
5650
                os->keepSeedFdOpen = 1;
5651
                os->seedFdOpen = 1;
5652
            }
5653
        }
5654
    #else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
5655
0
        #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
5656
0
        os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
5657
        #if defined(DEBUG_WOLFSSL)
5658
            WOLFSSL_MSG("opened /dev/urandom.");
5659
        #endif /* DEBUG_WOLFSSL */
5660
0
        if (os->fd == XBADFD)
5661
0
        #endif /* !NO_DEV_URANDOM */
5662
0
        {
5663
            /* may still have /dev/random */
5664
0
            os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
5665
        #if defined(DEBUG_WOLFSSL)
5666
            WOLFSSL_MSG("opened /dev/random.");
5667
        #endif /* DEBUG_WOLFSSL */
5668
0
            if (os->fd == XBADFD)
5669
0
                return OPEN_RAN_E;
5670
0
        }
5671
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
5672
    #if defined(DEBUG_WOLFSSL)
5673
        WOLFSSL_MSG("rnd read...");
5674
    #endif /* DEBUG_WOLFSSL */
5675
0
        while (sz) {
5676
0
            int len = (int)read(os->fd, output, sz);
5677
0
            if (len == -1) {
5678
0
                ret = READ_RAN_E;
5679
0
                break;
5680
0
            }
5681
5682
0
            sz     -= (word32)len;
5683
0
            output += len;
5684
5685
0
            if (sz) {
5686
    #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
5687
                sleep(0);             /* context switch */
5688
    #else
5689
0
                ret = RAN_BLOCK_E;
5690
0
                break;
5691
0
    #endif /* BLOCKING || WC_RNG_BLOCKING */
5692
0
            }
5693
0
        }
5694
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
5695
        if (!os->keepSeedFdOpen && os->seedFdOpen)
5696
        {
5697
            close(os->fd);
5698
            os->fd = -1;
5699
            os->seedFdOpen = 0;
5700
        }
5701
    #else
5702
0
        close(os->fd);
5703
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
5704
#else /* NO_FILESYSTEM */
5705
        (void)output;
5706
        (void)sz;
5707
        ret = NOT_COMPILED_IN;
5708
#endif /* NO_FILESYSTEM */
5709
5710
0
        return ret;
5711
5712
0
    #endif /* (!HAVE_INTEL_RDSEED && !HAVE_AMD_RDSEED) || !FORCE_FAILURE_RDSEED */
5713
5714
0
    #endif /*!HAVE_ENTROPY_MEMUSE || !ENTROPY_MEMUSE_FORCE_FAILURE */
5715
5716
0
    }
5717
5718
#endif
5719
5720
#ifdef USE_TEST_GENSEED
5721
    #if !defined(_MSC_VER) && !defined(__TASKING__)
5722
        #warning "write a real random seed!!!!, just for testing now"
5723
    #else
5724
        #pragma message("Warning: write a real random seed!!!!, just for testing now")
5725
    #endif
5726
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
5727
    {
5728
        word32 i;
5729
        for (i = 0; i < sz; i++ )
5730
            output[i] = (byte)i;
5731
5732
        (void)os;
5733
5734
        return 0;
5735
    }
5736
#endif
5737
/* End wc_GenerateSeed */
5738
5739
#if defined(CUSTOM_RAND_GENERATE_BLOCK) && defined(WOLFSSL_KCAPI)
5740
#include <fcntl.h>
5741
int wc_hwrng_generate_block(byte *output, word32 sz)
5742
{
5743
    int fd;
5744
    int ret = 0;
5745
    fd = wc_open_cloexec("/dev/hwrng", O_RDONLY);
5746
    if (fd == -1)
5747
        return OPEN_RAN_E;
5748
    while(sz)
5749
    {
5750
        int len = (int)read(fd, output, sz);
5751
        if (len == -1)
5752
        {
5753
            ret = READ_RAN_E;
5754
            break;
5755
        }
5756
        sz -= len;
5757
        output += len;
5758
    }
5759
    close(fd);
5760
    return ret;
5761
}
5762
#endif
5763
5764
#endif /* WC_NO_RNG */