Coverage Report

Created: 2026-09-27 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/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_HAVE_RNG_BANKREF:      Enable RNG bank indirect RNG         default: off
39
 *                            support
40
 * WC_RNG_NO_AUTO_LOCK:      Leave out the lock that lets threads default: off
41
 *                            share one WC_RNG (lock on unless set)
42
 * WC_RNG_WANT_AUTO_LOCK:    Keep that lock even where this build default: off
43
 *                            would otherwise skip it
44
 * WC_RNG_AUTOFORK:          pthread_atfork handlers so a forked  default: on
45
 *                            child can keep using its WC_RNG     where found
46
 * WOLFSSL_RNG_USE_FULL_SEED: Use full-length seed for DRBG       default: off
47
 * WOLFSSL_GENSEED_FORTEST:  Use deterministic seed for testing   default: off
48
 *                            WARNING: not for production use
49
 * WOLFSSL_KEEP_RNG_SEED_FD_OPEN: Keep /dev/random fd open        default: off
50
 *                            between seed operations
51
 *
52
 * Custom RNG Sources:
53
 * CUSTOM_RAND_GENERATE:     Custom random word generator func    default: off
54
 * CUSTOM_RAND_GENERATE_BLOCK: Custom block random generator      default: off
55
 * CUSTOM_RAND_GENERATE_SEED: Custom seed generator function      default: off
56
 * CUSTOM_RAND_GENERATE_SEED_OS: Custom OS-level seed generator   default: off
57
 *
58
 * Entropy Sources:
59
 * HAVE_ENTROPY_MEMUSE:      Enable memory-use based entropy      default: off
60
 *                            source for DRBG seeding
61
 * ENTROPY_MEMUSE_FORCE_FAILURE: Force entropy failure (testing)  default: off
62
 * HAVE_GETRANDOM:           Use Linux getrandom() syscall        default: auto
63
 * WOLFSSL_GETRANDOM:        Use getrandom() for seed source      default: auto
64
 * FORCE_FAILURE_GETRANDOM:  Force getrandom failure (testing)    default: off
65
 * NO_DEV_RANDOM:            Don't use /dev/random for seeding    default: off
66
 * NO_DEV_URANDOM:           Don't use /dev/urandom for seeding   default: off
67
 * WC_RNG_SEED_DEVICE:       Device tried before the usual seed   default: off
68
 *                            sources. Must be a quoted string,
69
 *                            e.g. -DWC_RNG_SEED_DEVICE='"/dev/hwrng"'
70
 * HAVE_INTEL_RDRAND:        Use Intel RDRAND instruction         default: off
71
 * HAVE_INTEL_RDSEED:        Use Intel RDSEED instruction         default: off
72
 * HAVE_AMD_RDSEED:          Use AMD RDSEED instruction           default: off
73
 * IDIRECT_DEV_RANDOM:       iDirect custom /dev/random path      default: off
74
 * WIN_REUSE_CRYPT_HANDLE:   Reuse Windows CryptContext handle    default: off
75
 *
76
 * Entropy Tuning (for HAVE_ENTROPY_MEMUSE):
77
 * ENTROPY_NUM_UPDATE:       Number of updates per sample         default: 18
78
 *                            More updates = better entropy but slower
79
 * ENTROPY_NUM_UPDATES_BITS: Bits to represent ENTROPY_NUM_UPDATE default: 5
80
 *                            = upper(log2(ENTROPY_NUM_UPDATE))
81
 * ENTROPY_NUM_WORDS_BITS:   State size as 2^N entries            default: 14
82
 *                            Range: 8-30. Base on cache sizes.
83
 *                            Larger = more cache misses = better entropy
84
 *                            but more static memory usage.
85
 *
86
 * DRBG Health Tests:
87
 * WC_RNG_SEED_APT_CUTOFF:  Adaptive proportion test cutoff      default: auto
88
 * WC_RNG_SEED_APT_WINDOW:  Adaptive proportion test window size  default: auto
89
 * WC_RNG_SEED_RCT_CUTOFF:  Repetition count test cutoff         default: auto
90
 *
91
 * Hardware RNG:
92
 * STM32_RNG:                STM32 hardware RNG                   default: off
93
 * STM32_NUTTX_RNG:          STM32 RNG via NuttX                  default: off
94
 * WOLFSSL_STM32F427_RNG:    STM32F427 hardware RNG               default: off
95
 * WOLFSSL_STM32_RNG_NOLIB:  STM32 RNG without HAL library        default: off
96
 * WOLFSSL_PIC32MZ_RNG:      PIC32MZ hardware RNG                 default: off
97
 * FREESCALE_RNGA:           Freescale RNGA                       default: off
98
 * FREESCALE_K70_RNGA:       Freescale K70 RNGA                   default: off
99
 * FREESCALE_RNGB:           Freescale RNGB                       default: off
100
 * FREESCALE_KSDK_2_0_RNGA:  Freescale KSDK 2.0 RNGA              default: off
101
 * FREESCALE_KSDK_2_0_TRNG:  Freescale KSDK 2.0 TRNG              default: off
102
 * MAX3266X_RNG:             MAX3266X hardware RNG                default: off
103
 * QAT_ENABLE_RNG:           Intel QAT hardware RNG               default: off
104
 * WOLFSSL_ATECC_RNG:        ATECC508/608 hardware RNG            default: off
105
 * WOLFSSL_SILABS_TRNG:      Silicon Labs TRNG                    default: off
106
 * WOLFSSL_SCE_NO_TRNG:      Disable Renesas SCE TRNG             default: off
107
 * WOLFSSL_SCE_TRNG_HANDLE:  Renesas SCE TRNG handle              default: off
108
 * WOLFSSL_SE050_NO_TRNG:    Disable SE050 TRNG                   default: off
109
 * WOLFSSL_PSA_NO_RNG:       Disable PSA RNG                      default: off
110
 * HAVE_IOTSAFE_HWRNG:       IoT-Safe hardware RNG                default: off
111
 * WOLFSSL_XILINX_CRYPT_VERSAL: Xilinx Versal crypto RNG          default: off
112
 * WOLFSSL_VA416X0_TRNG:     Vorago VA416x0 hardware TRNG         default: off
113
 *                           (seeds Hash-DRBG; needs the VA416xx
114
 *                           SDK header va416xx.h on the include
115
 *                           path). See the wc_GenerateSeed()
116
 *                           implementation below for SDK API and
117
 *                           tuning details.
118
 */
119
120
#define WC_FIPS_LL_CRYPTO
121
#define _WC_BUILDING_RANDOM_C
122
123
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
124
125
/* on HPUX 11 you may need to install /dev/random see
126
   http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
127
128
*/
129
#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
130
    #include <esp_random.h>
131
#endif
132
133
#if defined(HAVE_FIPS) && \
134
    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
135
136
    #ifdef USE_WINDOWS_API
137
        #pragma code_seg(".fipsA$i")
138
        #pragma const_seg(".fipsB$i")
139
    #endif
140
#endif
141
142
143
#include <wolfssl/wolfcrypt/random.h>
144
#ifdef WC_RNG_LOCK_ATFORK
145
    #include <errno.h>   /* for the fork handlers, whatever the seed source */
146
#endif
147
#ifdef WC_HAVE_RNG_BANKREF
148
    #if defined(HAVE_FIPS) && !defined(WOLFSSL_EXPERIMENTAL_SETTINGS) && \
149
        !defined(WOLFSSL_FIPS_DEV)
150
        #error WC_HAVE_RNG_BANKREF is unsupported in FIPS configurations.
151
    #endif
152
    #include <wolfssl/wolfcrypt/rng_bank.h>
153
#endif
154
#include <wolfssl/wolfcrypt/cpuid.h>
155
156
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
157
158
#ifndef NO_SHA256
159
    #include <wolfssl/wolfcrypt/sha256.h>
160
#endif
161
#ifdef WOLFSSL_DRBG_SHA512
162
    #include <wolfssl/wolfcrypt/sha512.h>
163
#endif
164
165
#ifdef WOLF_CRYPTO_CB
166
    #include <wolfssl/wolfcrypt/cryptocb.h>
167
#endif
168
169
#ifdef NO_INLINE
170
    #include <wolfssl/wolfcrypt/misc.h>
171
#else
172
    #define WOLFSSL_MISC_INCLUDED
173
    #include <wolfcrypt/src/misc.c>
174
#endif
175
176
#if defined(WOLFSSL_SGX)
177
    #include <sgx_trts.h>
178
#elif defined(USE_WINDOWS_API)
179
    #ifndef _WIN32_WINNT
180
        #define _WIN32_WINNT 0x0400
181
    #endif
182
    #define _WINSOCKAPI_ /* block inclusion of winsock.h header file */
183
    #include <windows.h>
184
    #include <wincrypt.h>
185
    #undef _WINSOCKAPI_ /* undefine it for MINGW winsock2.h header file */
186
#elif defined(HAVE_WNR)
187
    #include <wnr.h>
188
    wolfSSL_Mutex wnr_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wnr_mutex);    /* global netRandom mutex */
189
    int wnr_timeout     = 0;    /* entropy timeout, milliseconds */
190
    #ifndef WOLFSSL_MUTEX_INITIALIZER
191
    /* Elects a single initializer for wnr_mutex. */
192
    wc_MutexOnceFlag wnr_mutex_inited = WOLFSSL_ATOMIC_INITIALIZER(0);
193
    #endif
194
    int wnr_inited = 0;    /* flag for whether wc_InitNetRandom() has been called */
195
    wnr_context*  wnr_ctx;      /* global netRandom context */
196
#elif defined(FREESCALE_KSDK_2_0_TRNG)
197
    #include "fsl_trng.h"
198
#elif defined(FREESCALE_KSDK_2_0_RNGA)
199
    #include "fsl_rnga.h"
200
#elif defined(WOLFSSL_WICED)
201
    #include "wiced_crypto.h"
202
#elif defined(WOLFSSL_NETBURNER)
203
    #include <predef.h>
204
    #include <basictypes.h>
205
    #include <random.h>
206
#elif defined(WOLFSSL_XILINX_CRYPT_VERSAL)
207
    #include "wolfssl/wolfcrypt/port/xilinx/xil-versal-trng.h"
208
#elif defined(WOLFSSL_RPIPICO)
209
    #include "wolfssl/wolfcrypt/port/rpi_pico/pico.h"
210
#elif defined(WOLFSSL_C2000_ENTROPY)
211
    #include "wolfssl/wolfcrypt/port/ti/ti-c2000-entropy.h"
212
#elif defined(NO_DEV_RANDOM)
213
#elif defined(CUSTOM_RAND_GENERATE)
214
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
215
#elif defined(CUSTOM_RAND_GENERATE_SEED)
216
#elif defined(WOLFSSL_GENSEED_FORTEST)
217
#elif defined(WOLFSSL_MDK_ARM)
218
#elif defined(WOLFSSL_IAR_ARM)
219
#elif defined(WOLFSSL_ROWLEY_ARM)
220
#elif defined(WOLFSSL_EMBOS)
221
#elif defined(WOLFSSL_DEOS)
222
#elif defined(MICRIUM)
223
#elif defined(WOLFSSL_NUCLEUS)
224
#elif defined(WOLFSSL_PB)
225
#elif defined(WOLFSSL_ZEPHYR)
226
#elif defined(WOLFSSL_TELIT_M2MB)
227
#elif defined(WOLFSSL_RENESAS_TSIP)
228
    /* for wc_tsip_GenerateRandBlock */
229
    #include "wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h"
230
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
231
#elif defined(WOLFSSL_IMXRT1170_CAAM)
232
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
233
    #include "cyhal_trng.h" /* Infineon/Cypress HAL RNG implementation */
234
#elif defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
235
    #include "wolfssl/wolfcrypt/port/maxim/max3266x.h"
236
#else
237
    #include <errno.h>
238
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
239
        #include <sys/random.h>
240
    #endif
241
    /* include headers that may be needed to get good seed */
242
    #include <fcntl.h>
243
    #ifndef EBSNET
244
        #include <unistd.h>
245
    #endif
246
#endif
247
248
#if defined(WOLFSSL_SILABS_SE_ACCEL)
249
#include <wolfssl/wolfcrypt/port/silabs/silabs_random.h>
250
#endif
251
252
#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_IOTSAFE_HWRNG)
253
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
254
#endif
255
256
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_RNG)
257
#include <wolfssl/wolfcrypt/port/psa/psa.h>
258
#endif
259
260
#if FIPS_VERSION3_GE(6,0,0)
261
    const unsigned int wolfCrypt_FIPS_drbg_ro_sanity[2] =
262
                                                     { 0x1a2b3c4d, 0x00000011 };
263
    int wolfCrypt_FIPS_DRBG_sanity(void)
264
    {
265
        return 0;
266
    }
267
#endif
268
269
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
270
    defined(HAVE_AMD_RDSEED)
271
    static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER;
272
    static void wc_InitRng_IntelRD(void)
273
    {
274
        cpuid_get_flags_ex(&intel_flags);
275
    }
276
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
277
    static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
278
    #endif
279
    #ifdef HAVE_INTEL_RDRAND
280
    static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
281
    #endif
282
283
#ifdef USE_WINDOWS_API
284
    #define USE_INTEL_INTRINSICS
285
#elif !defined __GNUC__ || defined __clang__ || __GNUC__ > 4
286
    #define USE_INTEL_INTRINSICS
287
#else
288
    #undef USE_INTEL_INTRINSICS
289
#endif
290
291
#ifdef USE_INTEL_INTRINSICS
292
    #include <immintrin.h>
293
    /* Before clang 7 or GCC 9, immintrin.h did not define _rdseed64_step() */
294
    #ifndef HAVE_INTEL_RDSEED
295
    #elif defined __clang__ && __clang_major__ > 6
296
    #elif !defined __GNUC__
297
    #elif __GNUC__ > 8
298
    #else
299
        #ifndef __clang__
300
            #pragma GCC push_options
301
            #pragma GCC target("rdseed")
302
        #else
303
            #define __RDSEED__
304
        #endif
305
        #include <x86intrin.h>
306
        #ifndef __clang__
307
            #pragma GCC pop_options
308
        #endif
309
    #endif
310
#endif /* USE_WINDOWS_API */
311
#endif
312
313
/* RNG health states */
314
0
#define DRBG_NOT_INIT     WC_DRBG_NOT_INIT
315
0
#define DRBG_OK           WC_DRBG_OK
316
0
#define DRBG_FAILED       WC_DRBG_FAILED
317
0
#define DRBG_CONT_FAILED  WC_DRBG_CONT_FAILED
318
319
/* enforcement helper for WC_RNG_LOCK_REQUIRED and
320
 * WC_RNG_LOCK_ENTROPY_INVALIDATED: instance-consuming public APIs call this on
321
 * entry. */
322
static WC_MAYBE_UNUSED WC_INLINE int rng_lock_required_check(WC_RNG* rng)
323
0
{
324
0
    if (rng == NULL)
325
0
        return BAD_FUNC_ARG;
326
0
#ifndef WC_RNG_HAVE_LOCK
327
0
    return 0;
328
#else /* WC_RNG_HAVE_LOCK */
329
    else {
330
    #ifdef WOLFSSL_NO_ATOMICS
331
        WC_RNG_lock_t lock_state = rng->lock;
332
    #else
333
        WC_RNG_lock_arg_t lock_state = WOLFSSL_ATOMIC_LOAD(rng->lock);
334
    #endif
335
        if ((lock_state & WC_RNG_LOCK_REQUIRED) &&
336
            (! (lock_state & WC_RNG_LOCK_HELD)))
337
        {
338
            return OBJECT_NOT_LOCKED_E;
339
        }
340
        /* WC_RNG_LOCK_ENTROPY_INVALIDATED deliberately does not gate entry
341
         * here: on lock-required instances the lock API refuses new leases,
342
         * and on unlocked instances the saturated reseedCtr (see
343
         * wc_RNG_invalidate_entropy()) forces a credited reseed -- which
344
         * clears the flag -- before the next generate.  Refusing here would
345
         * brick unlocked instances, with no path to recovery. */
346
        return 0;
347
    }
348
#endif /* WC_RNG_HAVE_LOCK */
349
0
}
350
351
/* Read-only accessor for the RNG health status (enum wc_RngHealthState).
352
 * Returns the status, or BAD_FUNC_ARG for a NULL rng. */
353
int wc_RNG_GetStatus(const WC_RNG* rng)
354
0
{
355
0
    if (rng == NULL)
356
0
        return BAD_FUNC_ARG;
357
0
    return (int)rng->status;
358
0
}
359
360
/* Returns 1 if rng has an instantiated DRBG, else 0.  An in-service WC_RNG can
361
 * lack one: _InitRng() in HAVE_INTEL_RDRAND configurations bypasses DRBG
362
 * instantiation when the CPU has RDRAND (). */
363
int wc_RNG_DRBG_Present(const WC_RNG* rng)
364
0
{
365
0
    if (rng == NULL)
366
0
        return 0;
367
0
#if defined(HAVE_HASHDRBG) && !defined(NO_SHA256)
368
0
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL))
369
0
        return 1;
370
0
#endif
371
0
#if defined(HAVE_HASHDRBG) && defined(WOLFSSL_DRBG_SHA512)
372
0
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL))
373
0
        return 1;
374
0
#endif
375
0
    return 0;
376
0
}
377
378
#ifdef WC_RNG_HAVE_POOL
379
static WARN_UNUSED_RESULT int PoolPurge(WC_RNG* rng);
380
#endif
381
382
/* Start NIST DRBG code */
383
#ifdef HAVE_HASHDRBG
384
385
0
#define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
386
#define MAX_REQUEST_LEN   (0x10000)
387
388
#ifdef WC_RNG_SEED_CB
389
390
#ifndef HAVE_FIPS
391
static wc_RngSeed_Cb seedCb = wc_GenerateSeed;
392
#else
393
static wc_RngSeed_Cb seedCb = NULL;
394
#endif
395
396
int wc_SetSeed_Cb(wc_RngSeed_Cb cb)
397
{
398
    seedCb = cb;
399
    return 0;
400
}
401
402
#endif
403
404
405
/* Internal return codes */
406
enum {
407
    DRBG_SUCCESS = 0,
408
    DRBG_FAILURE = 1,
409
    DRBG_NEED_RESEED = 2,
410
    DRBG_CONT_FAILURE = 3,
411
    DRBG_NO_SEED_CB = 4
412
};
413
414
/* Numerous existing code points assume DRBG_SUCCESS is 0 -- for now, just
415
 * assert safety around that. */
416
wc_static_assert(DRBG_SUCCESS == 0);
417
418
#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES
419
    enum {
420
        CONST_NUM_ERR_DRBG_FAILURE = DRBG_FAILURE,
421
        CONST_NUM_ERR_DRBG_NEED_RESEED = DRBG_NEED_RESEED,
422
        CONST_NUM_ERR_DRBG_CONT_FAILURE = DRBG_CONT_FAILURE,
423
        CONST_NUM_ERR_DRBG_NO_SEED_CB = DRBG_NO_SEED_CB
424
    };
425
    /* DRBG_SUCCESS needs to be macroized to avoid "enumerated and
426
     * non-enumerated type in conditional expression" in C++. */
427
    #define DRBG_SUCCESS (byte)DRBG_SUCCESS
428
    #define DRBG_FAILURE (byte)WC_ERR_TRACE(DRBG_FAILURE)
429
    #define DRBG_NEED_RESEED (byte)WC_ERR_TRACE(DRBG_NEED_RESEED)
430
    #define DRBG_CONT_FAILURE (byte)WC_ERR_TRACE(DRBG_CONT_FAILURE)
431
    #define DRBG_NO_SEED_CB (byte)WC_ERR_TRACE(DRBG_NO_SEED_CB)
432
    #define WC_DRBG_FAILED (byte)WC_ERR_TRACE(WC_DRBG_FAILED)
433
    #define WC_DRBG_CONT_FAILED (byte)WC_ERR_TRACE(WC_DRBG_CONT_FAILED)
434
#endif
435
436
0
#define SEED_SZ           WC_DRBG_SEED_SZ
437
0
#define MAX_SEED_SZ       WC_DRBG_MAX_SEED_SZ
438
439
/* Verify max gen block len */
440
#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
441
    #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
442
#endif
443
444
/* the seed device is read through the filesystem API */
445
#if defined(WC_RNG_SEED_DEVICE) && defined(NO_FILESYSTEM)
446
    #error WC_RNG_SEED_DEVICE requires filesystem support
447
#endif
448
449
enum {
450
    drbgInitC     = 0,
451
    drbgReseed    = 1,
452
    drbgGenerateW = 2,
453
    drbgGenerateH = 3,
454
    drbgInitV     = 4
455
};
456
457
#ifndef NO_SHA256
458
typedef struct DRBG_internal DRBG_internal;
459
#endif
460
461
#ifdef WOLFSSL_DRBG_SHA512
462
typedef struct DRBG_SHA512_internal DRBG_SHA512_internal;
463
464
static WARN_UNUSED_RESULT int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg,
465
                               const byte* seed, word32 seedSz,
466
                               const byte* additional, word32 additionalSz);
467
static WARN_UNUSED_RESULT int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg,
468
                                 byte* out, word32 outSz,
469
                                 const byte* additional, word32 additionalSz);
470
static WARN_UNUSED_RESULT int Hash512_DRBG_Instantiate(
471
                                    DRBG_SHA512_internal* drbg,
472
                                    const byte* seed, word32 seedSz,
473
                                    const byte* nonce, word32 nonceSz,
474
                                    const byte* perso, word32 persoSz,
475
                                    void* heap, int devId);
476
static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg);
477
#endif
478
479
/* Runtime DRBG disable state.
480
 * These flags control which DRBG type is used for new WC_RNG instances and
481
 * may be toggled at runtime (e.g. NSA Suite 2.0 threads disable SHA-256).
482
 * A mutex protects the check-then-set in disable functions so concurrent
483
 * calls cannot bypass the mutual-exclusion guard and disable both DRBG types.
484
 * _InitRng also holds the mutex while reading the flags to get a consistent
485
 * snapshot, and returns BAD_STATE_E if both are somehow disabled. */
486
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
487
#ifndef NO_SHA256
488
#ifdef WOLFSSL_NO_SHA256_DRBG
489
static int sha256DrbgDisabled = 1;
490
#else
491
static int sha256DrbgDisabled = 0;
492
#endif /* WOLFSSL_NO_SHA256_DRBG */
493
#endif /* !NO_SHA256 */
494
#ifdef WOLFSSL_DRBG_SHA512
495
static int sha512DrbgDisabled = 0;
496
#endif /* WOLFSSL_DRBG_SHA512 */
497
498
499
#ifndef SINGLE_THREADED
500
static wolfSSL_Mutex drbgStateMutex
501
    WOLFSSL_MUTEX_INITIALIZER_CLAUSE(drbgStateMutex);
502
#ifndef WOLFSSL_MUTEX_INITIALIZER
503
enum {
504
    WC_DRBG_MUTEX_UNINITED,
505
    WC_DRBG_MUTEX_INITED
506
};
507
/* Ports with no static mutex initializer must create drbgStateMutex at run
508
 * time, so its readiness is tracked here.
509
 *
510
 * wc_DrbgState_MutexInit and wc_DrbgState_MutexFree are called only from
511
 * wolfCrypt_Init() and wolfCrypt_Cleanup(), inside the span serialized by the
512
 * init-state machine, so this flag is not otherwise synchronized. */
513
static int drbgStateMutex_inited = WC_DRBG_MUTEX_UNINITED;
514
#endif /* !defined(WOLFSSL_MUTEX_INITIALIZER) */
515
#endif /* !defined(SINGLE_THREADED) */
516
517
518
int wc_DrbgState_MutexInit(void)
519
0
{
520
0
#ifndef SINGLE_THREADED
521
#ifndef WOLFSSL_MUTEX_INITIALIZER
522
    if (drbgStateMutex_inited == WC_DRBG_MUTEX_UNINITED) {
523
        int ret = wc_InitMutex(&drbgStateMutex);
524
        if (ret != 0) {
525
            /* flag left unchanged because mutex was not inited */
526
            return ret;
527
        }
528
        drbgStateMutex_inited = WC_DRBG_MUTEX_INITED;
529
    }
530
531
#endif /* !defined(WOLFSSL_MUTEX_INITIALIZER) */
532
0
#endif /* !defined(SINGLE_THREADED) */
533
0
    return 0;
534
0
}
535
536
int wc_DrbgState_MutexFree(void)
537
0
{
538
0
#ifndef SINGLE_THREADED
539
#ifndef WOLFSSL_MUTEX_INITIALIZER
540
    if (drbgStateMutex_inited == WC_DRBG_MUTEX_INITED) {
541
        int ret = wc_FreeMutex(&drbgStateMutex);
542
        if (ret != 0) {
543
            /* flag left unchanged because mutex was not freed */
544
            return ret;
545
        }
546
        drbgStateMutex_inited = WC_DRBG_MUTEX_UNINITED;
547
    }
548
549
#endif /* !defined(WOLFSSL_MUTEX_INITIALIZER) */
550
0
#endif /* !defined(SINGLE_THREADED) */
551
0
    return 0;
552
0
}
553
554
static WARN_UNUSED_RESULT int LockDrbgState(void)
555
0
{
556
0
#ifndef SINGLE_THREADED
557
0
    return wc_LockMutex(&drbgStateMutex);
558
#else
559
    return 0;
560
#endif
561
0
}
562
563
static int UnlockDrbgState(void)
564
0
{
565
0
#ifndef SINGLE_THREADED
566
0
    return wc_UnLockMutex(&drbgStateMutex);
567
#else
568
    return 0;
569
#endif
570
0
}
571
572
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
573
574
#ifdef WC_RNG_LOCK_ATFORK
575
/* The lock and its fork handlers live in wc_port.c, outside the FIPS module
576
 * boundary.  Only the DRBG's reaction to a fork belongs in here. */
577
static int RngAutoLockInit(WC_RNG* rng)
578
0
{
579
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
580
    /* A full mutex instance is locked by its caller for the whole call, so
581
     * the automatic lock leaves that instance alone, as it does without the
582
     * fork handlers.  Such an instance is not fork covered either. */
583
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
584
        return 0;
585
#endif
586
0
    return wc_ForkLock_New(&rng->autoLock, rng->heap);
587
0
}
588
589
/* Safe on a zeroed WC_RNG that never got a lock. */
590
static void RngAutoLockFree(WC_RNG* rng)
591
0
{
592
0
    wc_ForkLock_Free(&rng->autoLock);
593
0
}
594
595
/* The child's stale DRBG state is dealt with by rng_pid_change_check() on
596
 * the generate path, which the fork handlers require. */
597
static int RngAutoLockEnter(WC_RNG* rng)
598
0
{
599
0
    return wc_ForkLock_Enter(rng->autoLock);
600
0
}
601
602
static void RngAutoLockExit(WC_RNG* rng)
603
0
{
604
0
    wc_ForkLock_Exit(rng->autoLock);
605
0
}
606
#elif defined(WC_RNG_HAVE_AUTO_LOCK)
607
/* Without fork handlers the lock lives in the WC_RNG itself: no heap. */
608
static int RngAutoLockInit(WC_RNG* rng)
609
{
610
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
611
    /* A full mutex instance is locked by its caller, which holds rng->mutex
612
     * for the whole call, so the automatic lock leaves that instance alone. */
613
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
614
        return 0;
615
#endif
616
    if (wc_InitMutex(&rng->mutex) != 0)
617
        return BAD_MUTEX_E;
618
    rng->autoLockInited = 1;
619
    return 0;
620
}
621
622
/* Safe on a zeroed WC_RNG that never got a lock. */
623
static void RngAutoLockFree(WC_RNG* rng)
624
{
625
    if (rng->autoLockInited) {
626
        (void)wc_FreeMutex(&rng->mutex);
627
        rng->autoLockInited = 0;
628
    }
629
}
630
631
/* Cancellation stays off while the lock is held: a reseed reads a device,
632
 * which is a cancellation point.  wc_port.c owns the platform side. */
633
static int RngAutoLockEnter(WC_RNG* rng)
634
{
635
    int old;
636
    if (!rng->autoLockInited)
637
        return 0;
638
    old = wc_CancelDisable();
639
    if (wc_LockMutex(&rng->mutex) != 0) {
640
        wc_CancelRestore(old);
641
        return BAD_MUTEX_E;
642
    }
643
    rng->autoLockCancel = old;
644
    return 0;
645
}
646
647
static void RngAutoLockExit(WC_RNG* rng)
648
{
649
    int old;
650
    if (!rng->autoLockInited)
651
        return;
652
    old = rng->autoLockCancel;   /* read before the unlock hands the slot on */
653
    (void)wc_UnLockMutex(&rng->mutex);
654
    wc_CancelRestore(old);
655
}
656
#else
657
#define RngAutoLockEnter(rng) 0
658
#define RngAutoLockExit(rng)  WC_DO_NOTHING
659
#endif /* WC_RNG_HAVE_AUTO_LOCK */
660
661
static WARN_UNUSED_RESULT int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed,
662
                                  void* heap, int devId);
663
664
#ifdef WOLFSSL_DRBG_SHA512
665
static WARN_UNUSED_RESULT int wc_RNG_HealthTest_SHA512_ex_internal(
666
                                  DRBG_SHA512_internal* drbg,
667
                                  int reseed, const byte* nonce, word32 nonceSz,
668
                                  const byte* perso, word32 persoSz,
669
                                  const byte* seedA, word32 seedASz,
670
                                  const byte* seedB, word32 seedBSz,
671
                                  const byte* additionalA, word32 additionalASz,
672
                                  const byte* additionalB, word32 additionalBSz,
673
                                  byte* output, word32 outputSz,
674
                                  void* heap, int devId);
675
#endif
676
677
/* The SHA-256 Hash_DRBG core (Hash_df, Hash_DRBG_*) operates on
678
 * DRBG_internal, which random.h defines only when SHA-256 is compiled in.
679
 * Wrap the whole block so a NO_SHA256 + WOLFSSL_DRBG_SHA512 build (the
680
 * SHA-512-only DRBG configuration) still compiles. The SHA-512 DRBG core
681
 * lives below in its own #ifdef WOLFSSL_DRBG_SHA512 section. */
682
#ifndef NO_SHA256
683
684
/* Hash Derivation Function */
685
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
686
static WARN_UNUSED_RESULT int Hash_df(DRBG_internal* drbg, byte* out,
687
                                                  word32 outSz, byte type,
688
                                                  const byte* inA, word32 inASz,
689
                                                  const byte* inB, word32 inBSz,
690
                                                  const byte* inC, word32 inCSz)
691
0
{
692
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
693
0
    byte ctr;
694
0
    word32 i;
695
0
    word32 len;
696
0
    word32 bits = (outSz * 8);
697
#ifdef WOLFSSL_WIDE_BYTE
698
    byte bitsBuf[4]; /* the 32-bit length as four big-endian octets */
699
#endif
700
#ifdef WOLFSSL_SMALL_STACK_CACHE
701
    wc_Sha256* sha = &drbg->sha256;
702
#else
703
0
    wc_Sha256 sha[1];
704
0
#endif
705
#if defined(WOLFSSL_SMALL_STACK_CACHE)
706
    byte* digest = drbg->digest_scratch;
707
#elif defined(WOLFSSL_SMALL_STACK)
708
    byte* digest;
709
#else
710
0
    byte digest[WC_SHA256_DIGEST_SIZE];
711
0
#endif
712
713
0
    if (drbg == NULL) {
714
0
        return DRBG_FAILURE;
715
0
    }
716
717
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
718
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
719
        DYNAMIC_TYPE_DIGEST);
720
    if (digest == NULL)
721
        return DRBG_FAILURE;
722
#endif
723
724
#ifdef WOLFSSL_CHECK_MEM_ZERO
725
    /* poison so a missed ForceZero on any path is caught by the check */
726
    XMEMSET(digest, 0xff, WC_SHA256_DIGEST_SIZE);
727
    wc_MemZero_Add("Hash_df digest", digest, WC_SHA256_DIGEST_SIZE);
728
#endif
729
730
#ifdef WOLFSSL_WIDE_BYTE
731
    /* A word32 cannot be aliased as an octet stream where a C byte is wider
732
     * than 8 bits; emit the length as four big-endian octets (shared helper). */
733
    BytesFromWordsBE32(bitsBuf, &bits, 4);
734
#elif defined(LITTLE_ENDIAN_ORDER)
735
0
    bits = ByteReverseWord32(bits);
736
0
#endif
737
0
    len = (outSz / OUTPUT_BLOCK_LEN)
738
0
        + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
739
740
0
    ctr = 1;
741
0
    for (i = 0; i < len; i++) {
742
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
743
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
744
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
745
    #else
746
0
        ret = wc_InitSha256(sha);
747
0
    #endif
748
0
        if (ret != 0)
749
0
            break;
750
0
#endif
751
0
        ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
752
0
        if (ret == 0) {
753
0
            ctr++;
754
#ifdef WOLFSSL_WIDE_BYTE
755
            ret = wc_Sha256Update(sha, bitsBuf, sizeof(bitsBuf));
756
#else
757
0
            ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
758
0
#endif
759
0
        }
760
761
0
        if (ret == 0) {
762
            /* churning V is the only string that doesn't have the type added */
763
0
            if (type != drbgInitV)
764
0
                ret = wc_Sha256Update(sha, &type, sizeof(type));
765
0
        }
766
0
        if (ret == 0)
767
0
            ret = wc_Sha256Update(sha, inA, inASz);
768
0
        if (ret == 0) {
769
0
            if (inB != NULL && inBSz > 0)
770
0
                ret = wc_Sha256Update(sha, inB, inBSz);
771
0
        }
772
0
        if (ret == 0) {
773
0
            if (inC != NULL && inCSz > 0)
774
0
                ret = wc_Sha256Update(sha, inC, inCSz);
775
0
        }
776
0
        if (ret == 0)
777
0
            ret = wc_Sha256Final(sha, digest);
778
779
#ifdef WOLFSSL_SMALL_STACK_CACHE
780
        if (ret != 0)
781
            (void)wc_Sha256Reset(sha);
782
#else
783
0
        wc_Sha256Free(sha);
784
0
#endif
785
0
        if (ret == 0) {
786
0
            if (outSz > OUTPUT_BLOCK_LEN) {
787
0
                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
788
0
                outSz -= OUTPUT_BLOCK_LEN;
789
0
                out += OUTPUT_BLOCK_LEN;
790
0
            }
791
0
            else {
792
0
                XMEMCPY(out, digest, outSz);
793
0
            }
794
0
        }
795
0
        else {
796
0
            break;
797
0
        }
798
0
    }
799
800
0
    ForceZero(digest, WC_SHA256_DIGEST_SIZE);
801
    /* Explicit check only where the buffer is NOT XFREEd (XFREE auto-checks):
802
     * the stack build and the small-stack-cache build (drbg member). */
803
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
804
    defined(WOLFSSL_CHECK_MEM_ZERO)
805
    wc_MemZero_Check(digest, WC_SHA256_DIGEST_SIZE);
806
#endif
807
808
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
809
    XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
810
#endif
811
812
#ifdef WC_VERBOSE_RNG
813
    if (ret != 0)
814
        WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __func__,
815
                             ret);
816
#endif
817
818
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
819
0
}
820
821
/* Returns: DRBG_SUCCESS or DRBG_FAILURE.  No state mutation on failure. */
822
static WARN_UNUSED_RESULT int Hash256_DRBG_Reseed(DRBG_internal* drbg,
823
                               const byte* seed,
824
                               word32 seedSz, const byte* additional,
825
                               word32 additionalSz)
826
0
{
827
0
    int ret;
828
0
    WC_DECLARE_VAR(newV_C, byte, DRBG_SEED_LEN * 2, 0);
829
0
    byte *newV, *newC;
830
831
0
    if (drbg == NULL) {
832
0
        return DRBG_FAILURE;
833
0
    }
834
835
#ifdef WOLFSSL_SMALL_STACK_CACHE
836
    newV_C = drbg->seed_scratch;
837
#else
838
0
    WC_ALLOC_VAR_EX(newV_C, byte, DRBG_SEED_LEN * 2, drbg->heap,
839
0
        DYNAMIC_TYPE_TMP_BUFFER, return DRBG_FAILURE);
840
0
#endif
841
0
    XMEMSET(newV_C, 0, DRBG_SEED_LEN * 2);
842
#ifdef WOLFSSL_CHECK_MEM_ZERO
843
    wc_MemZero_Add("Hash256_DRBG_Reseed newV_C", newV_C, DRBG_SEED_LEN * 2);
844
#endif
845
846
0
    newV = newV_C;
847
0
    newC = newV + DRBG_SEED_LEN;
848
849
0
    ret = Hash_df(drbg, newV, DRBG_SEED_LEN, drbgReseed,
850
0
                drbg->V, sizeof(drbg->V), seed, seedSz,
851
0
                additional, additionalSz);
852
0
    if (ret == DRBG_SUCCESS) {
853
0
        ret = Hash_df(drbg, newC, DRBG_SEED_LEN, drbgInitC, newV,
854
0
                                    DRBG_SEED_LEN, NULL, 0, NULL, 0);
855
0
    }
856
0
    if (ret == DRBG_SUCCESS) {
857
0
        XMEMCPY(drbg->V, newV, DRBG_SEED_LEN);
858
0
        XMEMCPY(drbg->C, newC, DRBG_SEED_LEN);
859
0
        drbg->reseedCtr = 1;
860
0
    }
861
862
0
    ForceZero(newV_C, DRBG_SEED_LEN * 2);
863
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
864
    defined(WOLFSSL_CHECK_MEM_ZERO)
865
    wc_MemZero_Check(newV_C, DRBG_SEED_LEN * 2);
866
#endif
867
868
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
869
0
    WC_FREE_VAR_EX(newV_C, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
870
0
#endif
871
872
0
    return ret;
873
0
}
874
875
#endif /* !NO_SHA256 */
876
877
#ifdef WC_RNG_HAVE_NEXT_SEED
878
/* Purge the credited next-seed aperture.  A plain store would race an in-flight
879
 * producer: the producer's publish must lose against a purge, never the
880
 * reverse, or material generated before a state-invalidation event could
881
 * surface READY after it -- exactly the resurrection the provenance guarantee
882
 * forbids.  A producer mid-fill (PRODUCING) owns the buffer, so the purge only
883
 * repaints the sentinel (PRODUCING -> PURGED); the producer's failed
884
 * publish-CAS observes the repaint and reopens the aperture EMPTY (see
885
 * NextSeedProducerRelease()) -- the sentinel alone suppresses the pre-event
886
 * material; abandoned seed-aperture buffers are zeroized as explained below.
887
 * All other states purge directly to EMPTY.  (The uncredited stir aperture
888
 * keeps its plain-store purge: stirs carry no claims, so resurrection there is
889
 * benign by the three-no-ops doctrine.)
890
 *
891
 * Zeroization doctrine for purges: abandonment here is event-driven (fork,
892
 * VM clone/resume, credited reseed), and the event that abandons bytes in
893
 * this lineage is the same event that created a sibling lineage that may
894
 * consume its identical copy of them.  Abandoned-here can be consumed-there,
895
 * so purged material is treated as CSP and wiped -- under ownership only:
896
 * READY or parked-fill words are claimed _CONSUMING first (the same CAS a
897
 * consumer uses; producers claim only non-negative words, so the claim
898
 * cannot collide), then wiped, then reopened EMPTY.  A _CONSUMING holder's
899
 * material is left to that consumer's own burn-before-release, and a
900
 * _PRODUCING holder's to its unwind (see NextSeedProducerRelease()).
901
 * Contrast the health-test burn arm, which stays sentinel-only: RCT/APT
902
 * are deterministic on the bytes, so every sibling rejects the same
903
 * material identically and no lineage can have consumed it.
904
 */
905
static WARN_UNUSED_RESULT int NextSeedPurge(wolfSSL_Atomic_Int *lenp,
906
                                            byte *seed_buf,
907
                                            word32 seed_buf_sz)
908
{
909
    int ret;
910
    WC_ATOMIC_INT_ARG cur_len, want_len;
911
912
    WC_CAS_WITH_RETRY_BEGIN_INIT_CUR(lenp, cur_len, ret) {
913
        if (cur_len == WC_DRBG_NEXT_SEED_PURGED)
914
            return ALREADY_E; /* already handed off to a producer's unwind. */
915
        if ((cur_len == WC_DRBG_NEXT_SEED_READY) || (cur_len > 0)) {
916
            /* Published or parked bytes with no owner: claim, wipe as
917
             * owner, reopen. */
918
            WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Int_CompareExchange,
919
                                          lenp, cur_len,
920
                                          WC_DRBG_NEXT_SEED_CONSUMING, ret);
921
            ForceZero(seed_buf, seed_buf_sz);
922
            WOLFSSL_ATOMIC_STORE(*lenp, WC_DRBG_NEXT_SEED_EMPTY);
923
        }
924
        else {
925
            want_len = (cur_len == WC_DRBG_NEXT_SEED_PRODUCING) ?
926
                WC_DRBG_NEXT_SEED_PURGED : WC_DRBG_NEXT_SEED_EMPTY;
927
            WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Int_CompareExchange,
928
                                          lenp, cur_len, want_len, ret);
929
        }
930
    } WC_CAS_WITH_RETRY_END;
931
932
    /* percolate the CAS result -- if the loop was aborted by user logic, the
933
     * caller needs to know that the purge failed. */
934
    return ret;
935
}
936
937
/* Release a producer claim (PRODUCING) on the credited aperture,
938
 * installing val (a fill offset, the full length, READY, or EMPTY).
939
 * Returns 0 on release, else BUSY_E: the release CAS can fail for
940
 * exactly one reason -- a concurrent NextSeedPurge() repainted the
941
 * claim PURGED (producers cannot claim a PRODUCING word, consumers
942
 * only exchange from READY, and the purge is the sole writer against
943
 * a claim).  The producer's material then predates the invalidation
944
 * event and must not surface: the aperture reopens EMPTY, which is
945
 * the whole suppression -- an EMPTY aperture is never consumed, and
946
 * the next fill overwrites from offset zero.  The bytes themselves are
947
 * wiped before the reopen, while this producer still owns the buffer:
948
 * the purge that repainted the claim marks an event that created a
949
 * sibling lineage, and the sibling's copy of a completed fill may be
950
 * consumed there (see the doctrine at NextSeedPurge()). */
951
static int NextSeedProducerRelease(wolfSSL_Atomic_Int *lenp,
952
                                   byte *seed_buf, word32 seed_buf_sz,
953
                                   WC_ATOMIC_INT_ARG val)
954
{
955
    WC_ATOMIC_INT_ARG expected = WC_DRBG_NEXT_SEED_PRODUCING;
956
    if (wolfSSL_Atomic_Int_CompareExchange(lenp, &expected, val))
957
        return 0;
958
    ForceZero(seed_buf, seed_buf_sz);
959
    WOLFSSL_ATOMIC_STORE(*lenp, WC_DRBG_NEXT_SEED_EMPTY);
960
    return BUSY_E;
961
}
962
#endif /* WC_RNG_HAVE_NEXT_SEED */
963
964
/* in_bracketed_consume: nonzero when the caller feeds this reseed from its own
965
 * _CONSUMING claim on the credited aperture (wc_RNG_DRBG_NextSeedNow_Nonce()).
966
 * The invalidated-entry purges below must then exempt that aperture: purging
967
 * it would steal the caller's claim and defeat its release CAS, converting
968
 * the caller's own recovery into a false epoch violation.  An external
969
 * (event) purge still repaints the claim, which is exactly what the
970
 * caller's release CAS exists to detect. */
971
static WARN_UNUSED_RESULT int Hash_DRBG_Reseed(WC_RNG* rng, const byte* seed,
972
                            word32 seedSz,
973
                            const byte* additional, word32 additionalSz,
974
                            int in_bracketed_consume)
975
0
{
976
0
    int ret;
977
#ifdef WC_RNG_HAVE_LOCK
978
    WC_RNG_lock_arg_t cur_lock;
979
#endif
980
981
0
    if (rng == NULL)
982
0
        return BAD_FUNC_ARG;
983
984
#ifdef WC_RNG_HAVE_LOCK
985
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
986
#endif
987
988
#ifdef WC_RNG_HAVE_LOCK
989
    /* Never allow an undersized seed to clear an invalidated state. */
990
    if ((cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) &&
991
        (seedSz < WC_DRBG_SEED_SZ))
992
    {
993
        /* Short-circuit return in case the _RECOVERING mutex below would have
994
         * failed. */
995
        return NEEDS_RECOVERY_E;
996
    }
997
998
    /* Iff _ENTROPY_INVALIDATED, assert the _ENTROPY_RECOVERING bit now -- if we
999
     * are re-invalidated in the meantime, it will have been cleared by the
1000
     * invalidation at exit time, signaling that we are still invalidated. */
1001
1002
    WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, ret) {
1003
        if (! (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)) {
1004
            /* Not invalidated -- no recovery mutex needed.  Explicit
1005
             * success: BEGIN initializes ret to a failure code. */
1006
            ret = 0;
1007
            break;
1008
        }
1009
        if (cur_lock & WC_RNG_LOCK_ENTROPY_RECOVERING) {
1010
            /* Must short-circuit return here, so that we don't improperly clear
1011
             * the _RECOVERING bit. */
1012
            return BUSY_E;
1013
        }
1014
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
1015
                                      &rng->lock, cur_lock,
1016
                                      cur_lock | WC_RNG_LOCK_ENTROPY_RECOVERING,
1017
                                      ret);
1018
        /* We now have the _RECOVERING mutex -- record that fact. */
1019
        cur_lock |= WC_RNG_LOCK_ENTROPY_RECOVERING;
1020
    } WC_CAS_WITH_RETRY_END;
1021
    if (ret != 0) {
1022
        /* Aborted acquire (a port's retry clause): the lock word is
1023
         * untouched and no state has moved -- bail before the purges,
1024
         * which must not run unserialized against a concurrent
1025
         * recovery. */
1026
        return ret;
1027
    }
1028
#endif /* WC_RNG_HAVE_LOCK */
1029
1030
#ifdef WC_RNG_HAVE_POOL
1031
    /* Purge the pool when recovering from invalidation, or if reseeding without
1032
     * locks (i.e. without an internal mechanism for tracking invalidation).
1033
     *
1034
     * The reseed counter tracks generates since the last reseed, and every
1035
     * pooled byte is itself a generate that incremented it. So the pool's
1036
     * contents are within the budget the counter enforces -- indeed they were
1037
     * authorized by the same accounting that later demanded the
1038
     * reseed. Discarding them treats output as retroactively over-budget when
1039
     * it was under-budget when produced.
1040
     */
1041
    #ifdef WC_RNG_HAVE_LOCK
1042
    if (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)
1043
    #endif
1044
    {
1045
        ret = PoolPurge(rng);
1046
        if ((ret != 0) &&
1047
            (ret != WC_NO_ERR_TRACE(ALREADY_E)))
1048
        {
1049
            goto out;
1050
        }
1051
    }
1052
#endif /* WC_RNG_HAVE_POOL */
1053
1054
0
#ifndef NO_SHA256
1055
0
    if (rng->drbgType == WC_DRBG_SHA256) {
1056
0
        DRBG_internal* drbg = (DRBG_internal *)rng->drbg;
1057
1058
0
        if (drbg == NULL) {
1059
        #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
1060
            if (IS_INTEL_RDRAND(intel_flags)) {
1061
                /* using RDRAND not DRBG, so return success */
1062
                ret = 0;
1063
                goto out;
1064
            }
1065
        #endif
1066
0
            ret = BAD_FUNC_ARG;
1067
0
            goto out;
1068
0
        }
1069
1070
#if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_HAVE_NEXT_SEED)
1071
        if ((cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) &&
1072
            (! in_bracketed_consume))
1073
        {
1074
            ret = NextSeedPurge(&drbg->nextSeedLen, drbg->nextSeed,
1075
                                (word32)sizeof(drbg->nextSeed));
1076
            if ((ret != 0) &&
1077
                (ret != WC_NO_ERR_TRACE(ALREADY_E)))
1078
            {
1079
                goto out;
1080
            }
1081
            /* the uncredited stir aperture is purged too, for provenance
1082
             * uniformity; best-effort (an in-flight depositor may
1083
             * resurrect a partial fill -- benign, stirs carry no
1084
             * divergence burden), and never zeroized (racy, and
1085
             * interleaved entropy of compatible provenance is harmless).
1086
             */
1087
            WOLFSSL_ATOMIC_STORE(rng->nextStirLen,
1088
                                 WC_DRBG_NEXT_SEED_EMPTY);
1089
        }
1090
#else
1091
0
        (void)in_bracketed_consume;
1092
0
#endif
1093
1094
0
        ret = Hash256_DRBG_Reseed(drbg, seed, seedSz, additional, additionalSz);
1095
#ifdef WC_RNG_DEBUG_STATS
1096
        if (ret == 0) {
1097
            ++rng->_stats_reseeds;
1098
        }
1099
#endif
1100
0
        goto out;
1101
0
    }
1102
0
#endif
1103
1104
0
#ifdef WOLFSSL_DRBG_SHA512
1105
0
    if (rng->drbgType == WC_DRBG_SHA512) {
1106
0
        DRBG_SHA512_internal* drbg512 =
1107
0
            (DRBG_SHA512_internal *)rng->drbg512;
1108
1109
0
        if (drbg512 == NULL) {
1110
        #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
1111
            if (IS_INTEL_RDRAND(intel_flags)) {
1112
                /* using RDRAND not DRBG, so return success */
1113
                ret = 0;
1114
                goto out;
1115
            }
1116
        #endif
1117
0
            ret = BAD_FUNC_ARG;
1118
0
            goto out;
1119
0
        }
1120
1121
#if defined(WC_RNG_HAVE_LOCK) && defined(WC_RNG_HAVE_NEXT_SEED)
1122
        if ((cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) &&
1123
            (! in_bracketed_consume))
1124
        {
1125
            ret = NextSeedPurge(&drbg512->nextSeedLen, drbg512->nextSeed,
1126
                                (word32)sizeof(drbg512->nextSeed));
1127
            if ((ret != 0) &&
1128
                (ret != WC_NO_ERR_TRACE(ALREADY_E)))
1129
            {
1130
                goto out;
1131
            }
1132
            /* see the SHA-256 arm re best-effort and no-zeroize. */
1133
            WOLFSSL_ATOMIC_STORE(rng->nextStirLen,
1134
                                 WC_DRBG_NEXT_SEED_EMPTY);
1135
        }
1136
#endif
1137
1138
0
        ret = Hash512_DRBG_Reseed(drbg512, seed, seedSz,
1139
0
                                  additional, additionalSz);
1140
#ifdef WC_RNG_DEBUG_STATS
1141
        if (ret == 0) {
1142
            ++rng->_stats_reseeds;
1143
        }
1144
#endif
1145
0
        goto out;
1146
0
    }
1147
0
#endif
1148
1149
    /* No DRBG type matched; if using RDRAND, that's OK */
1150
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
1151
    if (IS_INTEL_RDRAND(intel_flags)) {
1152
        /* using RDRAND not DRBG, so return success */
1153
        ret = 0;
1154
        goto out;
1155
    }
1156
    #endif
1157
1158
0
    ret = WRONG_TYPE_OBJECT_E;
1159
1160
0
    out:
1161
1162
#ifdef WC_RNG_HAVE_LOCK
1163
    /* The _RECOVERING bit functions as a mutex -- if it's set here, *we*
1164
     * set it, and must clear it.
1165
     *
1166
     * If we were invalidated on entry, and reseed succeeded, and provided we
1167
     * weren't re-invalidated in the meantime, clear the _INVALIDATED bit
1168
     * alongside the _RECOVERING bit.
1169
     *
1170
     * Otherwise, just clear the _RECOVERING bit (releasing the recovery mutex),
1171
     * and return with the success or failure code from above.
1172
     */
1173
    if ((ret == 0) && (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)) {
1174
        WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, ret) {
1175
            if (! (cur_lock & WC_RNG_LOCK_ENTROPY_RECOVERING)) {
1176
                ret = NEEDS_RECOVERY_E;
1177
                break;
1178
            }
1179
            WC_CAS_WITH_RETRY_LOOP_FOREVER(
1180
                wolfSSL_Atomic_Uint_CompareExchange, &rng->lock, cur_lock,
1181
                cur_lock & ~(WC_RNG_LOCK_ENTROPY_INVALIDATED |
1182
                             WC_RNG_LOCK_ENTROPY_RECOVERING),
1183
                ret);
1184
        } WC_CAS_WITH_RETRY_END;
1185
        if ((ret != 0) && (ret != WC_NO_ERR_TRACE(NEEDS_RECOVERY_E))) {
1186
            /* Aborted clear (a port's retry clause) strands _RECOVERING with no
1187
             * in-band path back: every future recovery would refuse BUSY_E.
1188
             * Condemn -- in kernel, DRBG_FAILED has an automated exit (the
1189
             * entropy daemon's recovery pass), and the owner can always reinit.
1190
             * A wedged mutex bit would have no visible indication that reinit
1191
             * is required.
1192
             */
1193
            rng->status = DRBG_FAILED;
1194
        }
1195
    }
1196
    else if (cur_lock & WC_RNG_LOCK_ENTROPY_RECOVERING) {
1197
        /* ret carries the reseed's status here and must survive, so the
1198
         * release gets its own result variable. */
1199
        int release_ret;
1200
        WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, release_ret) {
1201
            WC_CAS_WITH_RETRY_LOOP_FOREVER(
1202
                wolfSSL_Atomic_Uint_CompareExchange, &rng->lock, cur_lock,
1203
                cur_lock & ~WC_RNG_LOCK_ENTROPY_RECOVERING, release_ret);
1204
        } WC_CAS_WITH_RETRY_END;
1205
        if (release_ret != 0) {
1206
            /* Same stranded-_RECOVERING condemnation as the clear arm
1207
             * above; the reseed's own status still wins the return. */
1208
            rng->status = DRBG_FAILED;
1209
            if (ret == 0)
1210
                ret = release_ret;
1211
        }
1212
    }
1213
#endif /* WC_RNG_HAVE_LOCK */
1214
1215
0
    return ret;
1216
0
}
1217
1218
int wc_RNG_DRBG_Reseed_Nonce(WC_RNG* rng, const byte* seed, word32 seedSz,
1219
                             const byte *nonce, word32 nonceSz)
1220
0
{
1221
0
    int ret;
1222
1223
0
    if (rng == NULL || seed == NULL) {
1224
0
        return BAD_FUNC_ARG;
1225
0
    }
1226
1227
    /* Hash_df() skips a NULL input regardless of its stated length, so
1228
     * without this the caller's additional input would be dropped and
1229
     * success reported.  Matches _InitRng() and ReseedRBGC(). */
1230
0
    if ((nonce == NULL) && (nonceSz > 0))
1231
0
        return BAD_FUNC_ARG;
1232
1233
0
    ret = rng_lock_required_check(rng);
1234
0
    if (ret != 0)
1235
0
        return ret;
1236
1237
    /* These checks read state a generate writes under the lock, so the lock
1238
     * comes first.  The internal reseed paths already hold it. */
1239
0
    ret = RngAutoLockEnter(rng);
1240
0
    if (ret != 0)
1241
0
        return ret;
1242
1243
    /* A condemned instance does not accept a credited reseed: DRBG_FAILED's
1244
     * designed exit is wc_FreeRng()/wc_InitRng() (or the daemon's recovery
1245
     * pass), not in-place resurrection that would reset the counter, purge
1246
     * the pool, and clear quarantine on unvetted authority. */
1247
0
    if (rng->status != DRBG_OK) {
1248
0
        ret = RNG_FAILURE_E;
1249
0
        goto out;
1250
0
    }
1251
1252
#ifdef WC_RNG_HAVE_LOCK
1253
    /* Never allow an undersized seed to clear an invalidated state, and if
1254
     * invalidated, always assume potentially primary seed data -- test it with
1255
     * wc_RNG_TestSeed(). */
1256
    if (WOLFSSL_ATOMIC_LOAD(rng->lock) & WC_RNG_LOCK_ENTROPY_INVALIDATED) {
1257
        if (seedSz < WC_DRBG_SEED_SZ) {
1258
            ret = NEEDS_RECOVERY_E;
1259
            goto out;
1260
        }
1261
        ret = wc_RNG_TestSeed(seed, seedSz);
1262
        if (ret != 0)
1263
            goto out;
1264
    }
1265
#endif /* WC_RNG_HAVE_LOCK */
1266
1267
0
    ret = Hash_DRBG_Reseed(rng, seed, seedSz, nonce, nonceSz,
1268
0
                           0 /* in_bracketed_consume */);
1269
#ifdef WC_RNG_HAVE_RBGC
1270
    if (ret == 0) {
1271
        /* User-supplied entropy is of unknown provenance.  In RBGC builds,
1272
         * represent that fact using WC_RNG_RBGC_USER_SEED_STRATUM, preventing confusion with RNGs seeded by the ESV . */
1273
        rng->RBGCStratum = WC_RNG_RBGC_USER_SEED_STRATUM;
1274
    }
1275
#endif
1276
1277
0
    out:
1278
1279
0
    RngAutoLockExit(rng);
1280
0
    return ret;
1281
0
}
1282
1283
0
int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) {
1284
0
    return wc_RNG_DRBG_Reseed_Nonce(rng, seed, seedSz, NULL, 0);
1285
0
}
1286
1287
#ifdef WC_RNG_HAVE_RBGC
1288
1289
int wc_RNG_DRBG_GetRBGCStratum(const WC_RNG* rng)
1290
{
1291
    if (rng)
1292
        return rng->RBGCStratum;
1293
    else
1294
        return BAD_FUNC_ARG;
1295
}
1296
1297
#ifdef WC_RNG_HAVE_NEXT_SEED
1298
int wc_RNG_DRBG_GetNextSeedRBGCStratum(const WC_RNG* rng)
1299
{
1300
    if (rng == NULL)
1301
        return BAD_FUNC_ARG;
1302
1303
    /* Race-free via the NextSeed aperture protocol.  If called with rng locked,
1304
     * and ->nextSeedLen == WC_DRBG_NEXT_SEED_READY, then competing producers
1305
     * and consumers are all excluded, unambiguously marking
1306
     * ->nextSeedRBGCStratum as strictly reliable and stable.  nextSeedLen
1307
     * functions as the synchronizer -- the producer writes
1308
     * ->nextSeedRBGCStratum before publishing WC_DRBG_NEXT_SEED_READY to
1309
     * nextSeedLen with release semantics.
1310
     */
1311
1312
#ifndef NO_SHA256
1313
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
1314
        if (WOLFSSL_ATOMIC_LOAD(((const DRBG_internal*)rng->drbg)->nextSeedLen)
1315
            != WC_DRBG_NEXT_SEED_READY)
1316
        {
1317
            return NOT_READY_E;
1318
        }
1319
        else
1320
            return ((const DRBG_internal *)rng->drbg)->nextSeedRBGCStratum;
1321
    }
1322
#endif
1323
#ifdef WOLFSSL_DRBG_SHA512
1324
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
1325
        if (WOLFSSL_ATOMIC_LOAD(((const DRBG_SHA512_internal*)rng->drbg512)->nextSeedLen)
1326
            != WC_DRBG_NEXT_SEED_READY)
1327
        {
1328
            return NOT_READY_E;
1329
        }
1330
        else
1331
            return ((const DRBG_SHA512_internal *)rng->drbg512)->nextSeedRBGCStratum;
1332
    }
1333
#endif
1334
1335
    return BAD_FUNC_ARG;
1336
}
1337
#endif /* WC_RNG_HAVE_NEXT_SEED */
1338
1339
#endif /* WC_RNG_HAVE_RBGC */
1340
1341
/* Read-only accessor for the DRBG reseed counter.  When no DRBG is
1342
 * instantiated (see wc_RNG_DRBG_Present()) there is no counter; *reseedCtr
1343
 * is set to 0 -- never due for reseed -- and 0 is returned. */
1344
int wc_RNG_DRBG_GetReseedCtr(const WC_RNG* rng,
1345
                             wc_drbg_reseed_ctr_t* reseedCtr)
1346
0
{
1347
0
    if ((rng == NULL) || (reseedCtr == NULL))
1348
0
        return BAD_FUNC_ARG;
1349
0
    if (! wc_RNG_DRBG_Present(rng))
1350
0
        return WRONG_TYPE_OBJECT_E;
1351
0
    if (rng->status != DRBG_OK)
1352
0
        return BAD_STATE_E;
1353
0
#ifndef NO_SHA256
1354
0
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
1355
0
        *reseedCtr = ((const DRBG_internal *)rng->drbg)->reseedCtr;
1356
0
        return 0;
1357
0
    }
1358
0
#endif
1359
0
#ifdef WOLFSSL_DRBG_SHA512
1360
0
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
1361
0
        *reseedCtr = (wc_drbg_reseed_ctr_t)
1362
0
            ((const DRBG_SHA512_internal *)rng->drbg512)->reseedCtr;
1363
0
        return 0;
1364
0
    }
1365
0
#endif
1366
0
    return BAD_FUNC_ARG;
1367
0
}
1368
1369
#if defined(WC_RESEED_INTERVAL) && !defined(WORD64_AVAILABLE)
1370
    wc_static_assert((WC_RESEED_INTERVAL) <= 0xFFFFFFFFUL);
1371
#endif
1372
1373
/* Mark rng due for reseed: the next generate operation reseeds from the
1374
 * module's built-in or registered seed source before producing output (see also
1375
 * wc_RNG_DRBG_Reseed_Now()).  This can only shorten the current seed's
1376
 * remaining lifetime, never extend it.  When no DRBG is instantiated (RDRAND et
1377
 * al.) commanded reseed is not supported and the call returns
1378
 * WRONG_TYPE_OBJECT_E. */
1379
/* Every public entry below locks the instance, with a _local core for the
1380
 * generate path, which already holds the lock.
1381
 *
1382
 * Why they lock at all: they mutate the same DRBG state a generate does.
1383
 * Unlocked, a second thread reads and writes the reseed counter and the hash
1384
 * context mid-update, which ThreadSanitizer reports as a data race: 48 of them
1385
 * before this change, none after.  Nothing crashes and the output still looks
1386
 * random, which is what makes it easy to ship by mistake.
1387
 */
1388
static WARN_UNUSED_RESULT int wc_RNG_DRBG_ScheduleReseed_local(WC_RNG* rng)
1389
0
{
1390
0
    if (rng == NULL)
1391
0
        return BAD_FUNC_ARG;
1392
0
#ifndef NO_SHA256
1393
0
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
1394
0
        ((DRBG_internal *)rng->drbg)->reseedCtr =
1395
0
            (wc_drbg_reseed_ctr_t)WC_RESEED_INTERVAL;
1396
0
        return 0;
1397
0
    }
1398
0
#endif
1399
0
#ifdef WOLFSSL_DRBG_SHA512
1400
0
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
1401
0
        ((DRBG_SHA512_internal *)rng->drbg512)->reseedCtr =
1402
0
            (word64)WC_RESEED_INTERVAL;
1403
0
        return 0;
1404
0
    }
1405
0
#endif
1406
0
    return WRONG_TYPE_OBJECT_E;
1407
0
}
1408
1409
int wc_RNG_DRBG_ScheduleReseed(WC_RNG* rng)
1410
0
{
1411
0
    int ret;
1412
1413
0
    if (rng == NULL)
1414
0
        return BAD_FUNC_ARG;
1415
0
    ret = RngAutoLockEnter(rng);
1416
0
    if (ret != 0)
1417
0
        return ret;
1418
0
    ret = wc_RNG_DRBG_ScheduleReseed_local(rng);
1419
0
    RngAutoLockExit(rng);
1420
0
    return ret;
1421
0
}
1422
1423
/* Generic byte-array helper -- shared by both SHA-256 and SHA-512 DRBG
1424
 * cores. Lives outside the NO_SHA256 guard so SHA-512-only builds
1425
 * still build. */
1426
static WC_INLINE void array_add_one(byte* data, word32 dataSz)
1427
0
{
1428
0
    int i;
1429
0
    for (i = (int)dataSz - 1; i >= 0; i--) {
1430
0
        data[i] = WC_OCTET(data[i] + 1);
1431
0
        if (data[i] != 0) break;
1432
0
    }
1433
0
}
1434
1435
#ifndef NO_SHA256 /* re-open SHA-256 Hash_DRBG core */
1436
1437
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1438
static WARN_UNUSED_RESULT int Hash_gen(DRBG_internal* drbg, byte* out,
1439
                                       word32 outSz, const byte* V)
1440
0
{
1441
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
1442
0
    word32 i;
1443
0
    word32 len;
1444
#if defined(WOLFSSL_SMALL_STACK_CACHE)
1445
    wc_Sha256* sha = &drbg->sha256;
1446
    byte* data = drbg->seed_scratch; /* Note, top half of seed_scratch is used
1447
                                      * by Hash_DRBG_Generate(). */
1448
    byte* digest = drbg->digest_scratch;
1449
#elif defined(WOLFSSL_SMALL_STACK)
1450
    wc_Sha256 sha[1];
1451
    byte* data = NULL;
1452
    byte* digest = NULL;
1453
#else
1454
0
    wc_Sha256 sha[1];
1455
0
    byte data[DRBG_SEED_LEN];
1456
0
    byte digest[WC_SHA256_DIGEST_SIZE];
1457
0
#endif
1458
1459
0
    if (drbg == NULL) {
1460
0
        return DRBG_FAILURE;
1461
0
    }
1462
1463
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1464
    data = (byte*)XMALLOC(DRBG_SEED_LEN, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1465
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
1466
        DYNAMIC_TYPE_DIGEST);
1467
    if (data == NULL || digest == NULL) {
1468
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1469
        XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1470
        return DRBG_FAILURE;
1471
    }
1472
#endif
1473
1474
    /* Special case: outSz is 0 and out is NULL (Hash_DRBG_StirGenerate()): run
1475
     * a single Hashgen iteration with the block discarded, so the caller gets
1476
     * Generate's V-advance side effects without emitting output.  This
1477
     * preserves standard SP 800-90A sequencing, while presenting call semantics
1478
     * that are convenient for the stir. */
1479
0
    if (outSz == 0) {
1480
0
        outSz = 1;
1481
0
    }
1482
1483
0
    len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
1484
1485
0
    XMEMCPY(data, V, DRBG_SEED_LEN);
1486
#ifdef WOLFSSL_CHECK_MEM_ZERO
1487
    wc_MemZero_Add("Hash_gen data", data, DRBG_SEED_LEN);
1488
#endif
1489
0
    for (i = 0; i < len; i++) {
1490
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1491
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1492
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
1493
    #else
1494
0
        ret = wc_InitSha256(sha);
1495
0
    #endif
1496
0
        if (ret == 0)
1497
0
#endif
1498
0
            ret = wc_Sha256Update(sha, data, DRBG_SEED_LEN);
1499
0
        if (ret == 0)
1500
0
            ret = wc_Sha256Final(sha, digest);
1501
#ifdef WOLFSSL_SMALL_STACK_CACHE
1502
        if (ret != 0)
1503
            (void)wc_Sha256Reset(sha);
1504
#else
1505
0
        wc_Sha256Free(sha);
1506
0
#endif
1507
1508
0
        if (ret == 0) {
1509
0
            if (out != NULL && outSz != 0) {
1510
0
                if (outSz >= OUTPUT_BLOCK_LEN) {
1511
0
                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
1512
0
                    outSz -= OUTPUT_BLOCK_LEN;
1513
0
                    out += OUTPUT_BLOCK_LEN;
1514
0
                    array_add_one(data, DRBG_SEED_LEN);
1515
0
                }
1516
0
                else {
1517
0
                    XMEMCPY(out, digest, outSz);
1518
0
                    outSz = 0;
1519
0
                }
1520
0
            }
1521
0
        }
1522
0
        else {
1523
            /* wc_Sha256Update or wc_Sha256Final returned error */
1524
0
            break;
1525
0
        }
1526
0
    }
1527
0
    ForceZero(data, DRBG_SEED_LEN);
1528
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
1529
    defined(WOLFSSL_CHECK_MEM_ZERO)
1530
    wc_MemZero_Check(data, DRBG_SEED_LEN);
1531
#endif
1532
1533
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1534
0
    WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1535
0
    WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1536
0
#endif
1537
1538
    #ifdef WC_VERBOSE_RNG
1539
    if ((ret != DRBG_SUCCESS) && (ret != WC_NO_ERR_TRACE(DRBG_FAILURE))) {
1540
        /* Note, if we're just going to return DRBG_FAILURE to the caller, then
1541
         * there's no point printing it out here because (1) the lower-level
1542
         * code that was remapped to DRBG_FAILURE already got printed before the
1543
         * remapping, so a DRBG_FAILURE message would just be spamming the log,
1544
         * and (2) the caller will actually see the DRBG_FAILURE code, and is
1545
         * free to (and probably will) log it itself.
1546
         */
1547
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_gen failed with err %d.", ret);
1548
    }
1549
    #endif
1550
1551
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1552
0
}
1553
1554
#endif /* !NO_SHA256 - close to expose array_add to SHA-512 below */
1555
1556
/* Generic multi-byte add. Shared by SHA-256 and SHA-512 DRBG cores;
1557
 * lives outside the NO_SHA256 guard so SHA-512-only builds still link. */
1558
static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
1559
0
{
1560
0
    if (dLen > 0 && sLen > 0 && dLen >= sLen) {
1561
0
        int sIdx, dIdx;
1562
0
        word16 carry = 0;
1563
1564
0
        dIdx = (int)dLen - 1;
1565
0
        for (sIdx = (int)sLen - 1; sIdx >= 0; sIdx--) {
1566
0
            carry = (word16)(carry + d[dIdx] + s[sIdx]);
1567
0
            d[dIdx] = WC_OCTET(carry);
1568
0
            carry >>= 8;
1569
0
            dIdx--;
1570
0
        }
1571
1572
0
        for (; dIdx >= 0; dIdx--) {
1573
0
            carry = (word16)(carry + d[dIdx]);
1574
0
            d[dIdx] = WC_OCTET(carry);
1575
0
            carry >>= 8;
1576
0
        }
1577
0
    }
1578
0
}
1579
1580
#ifndef NO_SHA256 /* re-open SHA-256 Hash_DRBG core */
1581
1582
/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE.  DRBG state is
1583
 * always consistent upon return, whether success or failure. */
1584
static WARN_UNUSED_RESULT int Hash_DRBG_Generate(DRBG_internal* drbg,
1585
                              byte* out, word32 outSz,
1586
                              const byte* additional, word32 additionalSz)
1587
0
{
1588
0
    int ret;
1589
#ifdef WOLFSSL_SMALL_STACK_CACHE
1590
    wc_Sha256* sha = &drbg->sha256;
1591
#else
1592
0
    wc_Sha256 sha[1];
1593
0
#endif
1594
0
    byte type;
1595
0
#ifdef WORD64_AVAILABLE
1596
0
    word64 reseedCtr;
1597
#else
1598
    word32 reseedCtr;
1599
#endif
1600
#ifdef WOLFSSL_WIDE_BYTE
1601
    byte ctrBuf[8]; /* reseed counter as big-endian octets */
1602
#endif
1603
0
    byte *thisV = NULL;
1604
0
    WC_DECLARE_VAR(shadowV, byte, DRBG_SEED_LEN, 0);
1605
1606
0
    if (drbg == NULL) {
1607
0
        return DRBG_FAILURE;
1608
0
    }
1609
1610
0
    if (drbg->reseedCtr >= WC_RESEED_INTERVAL) {
1611
    #if (defined(DEBUG_WOLFSSL) || defined(DEBUG_DRBG_RESEEDS)) && \
1612
        defined(WOLFSSL_DEBUG_PRINTF)
1613
        WOLFSSL_DEBUG_PRINTF("DRBG reseed triggered, reseedCtr == %lu",
1614
                (unsigned long)drbg->reseedCtr);
1615
    #endif
1616
0
        return DRBG_NEED_RESEED;
1617
0
    }
1618
0
    else {
1619
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
1620
        byte* digest = drbg->digest_scratch;
1621
    #elif defined(WOLFSSL_SMALL_STACK)
1622
        byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
1623
            DYNAMIC_TYPE_DIGEST);
1624
        if (digest == NULL)
1625
            return DRBG_FAILURE;
1626
    #else
1627
0
        byte digest[WC_SHA256_DIGEST_SIZE];
1628
0
    #endif
1629
1630
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1631
        /* baseline 0 (not 0xff): a pre-write early exit on this path checks
1632
         * digest, so it must read zero.  Registered across the whole generate;
1633
         * every exit below force-zeros+checks (or XFREEs) it. */
1634
        XMEMSET(digest, 0, WC_SHA256_DIGEST_SIZE);
1635
        wc_MemZero_Add("Hash_DRBG_Generate digest", digest,
1636
            WC_SHA256_DIGEST_SIZE);
1637
    #endif
1638
1639
0
        type = drbgGenerateH;
1640
0
        reseedCtr = drbg->reseedCtr;
1641
1642
        /* SP 800-90A 10.1.1.4 step 2: if additional_input != Null,
1643
         * w = Hash(0x02 || V || additional_input), V = (V + w) mod 2^seedlen */
1644
0
        if (additional != NULL && additionalSz > 0) {
1645
0
            byte addType = drbgGenerateW;
1646
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1647
0
            ret = 0;
1648
0
            WC_ALLOC_VAR_EX(shadowV, byte, DRBG_SEED_LEN, drbg->heap,
1649
0
                            DYNAMIC_TYPE_TMP_BUFFER, ret = MEMORY_E);
1650
0
            if (ret == 0) {
1651
0
                thisV = shadowV;
1652
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1653
                ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
1654
        #else
1655
0
                ret = wc_InitSha256(sha);
1656
0
        #endif
1657
0
            }
1658
1659
0
            if (ret != 0) {
1660
0
                WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1661
                /* digest holds only the 0 baseline here (never written) */
1662
            #if (!defined(WOLFSSL_SMALL_STACK) || \
1663
                 defined(WOLFSSL_SMALL_STACK_CACHE)) && \
1664
                defined(WOLFSSL_CHECK_MEM_ZERO)
1665
                wc_MemZero_Check(digest, WC_SHA256_DIGEST_SIZE);
1666
            #endif
1667
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1668
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1669
            #endif
1670
0
                return DRBG_FAILURE;
1671
0
            }
1672
#else
1673
            (void)shadowV;
1674
            /* use the upper half of drbg->seed_scratch -- the lower half is
1675
             * used by Hash_gen() for its "data" work buffer. */
1676
            thisV = drbg->seed_scratch + DRBG_SEED_LEN;
1677
            ret = 0;
1678
#endif
1679
0
            if (ret == 0)
1680
0
                ret = wc_Sha256Update(sha, &addType, sizeof(addType));
1681
0
            if (ret == 0)
1682
0
                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
1683
0
            if (ret == 0)
1684
0
                ret = wc_Sha256Update(sha, additional, additionalSz);
1685
0
            if (ret == 0)
1686
0
                ret = wc_Sha256Final(sha, digest);
1687
#ifdef WOLFSSL_SMALL_STACK_CACHE
1688
            if (ret != 0)
1689
                (void)wc_Sha256Reset(sha);
1690
#else
1691
0
            wc_Sha256Free(sha);
1692
0
#endif
1693
0
            if (ret == 0) {
1694
0
                XMEMCPY(thisV, drbg->V, DRBG_SEED_LEN);
1695
0
                array_add(thisV, DRBG_SEED_LEN, digest,
1696
0
                          WC_SHA256_DIGEST_SIZE);
1697
0
            }
1698
0
            else {
1699
0
                WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1700
0
                ForceZero(digest, WC_SHA256_DIGEST_SIZE);
1701
            #if (!defined(WOLFSSL_SMALL_STACK) || \
1702
                 defined(WOLFSSL_SMALL_STACK_CACHE)) && \
1703
                defined(WOLFSSL_CHECK_MEM_ZERO)
1704
                wc_MemZero_Check(digest, WC_SHA256_DIGEST_SIZE);
1705
            #endif
1706
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1707
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1708
            #endif
1709
0
                return DRBG_FAILURE;
1710
0
            }
1711
0
        }
1712
0
        else {
1713
0
            thisV = drbg->V;
1714
0
        }
1715
1716
0
        ret = Hash_gen(drbg, out, outSz, thisV);
1717
0
        if (ret == DRBG_SUCCESS) {
1718
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1719
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1720
            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
1721
        #else
1722
0
            ret = wc_InitSha256(sha);
1723
0
        #endif
1724
0
            if (ret == 0)
1725
0
#endif
1726
0
                ret = wc_Sha256Update(sha, &type, sizeof(type));
1727
0
            if (ret == 0)
1728
0
                ret = wc_Sha256Update(sha, thisV, DRBG_SEED_LEN);
1729
0
            if (ret == 0)
1730
0
                ret = wc_Sha256Final(sha, digest);
1731
1732
#ifdef WOLFSSL_SMALL_STACK_CACHE
1733
            if (ret != 0)
1734
                (void)wc_Sha256Reset(sha);
1735
#else
1736
0
            wc_Sha256Free(sha);
1737
0
#endif
1738
1739
0
            if (ret == 0) {
1740
                /* No failure possible from here -- commit thisV if needed. */
1741
0
                if (thisV != drbg->V)
1742
0
                    XMEMCPY(drbg->V, thisV, DRBG_SEED_LEN);
1743
0
                array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
1744
0
                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
1745
#ifdef WOLFSSL_WIDE_BYTE
1746
                /* A word cannot be aliased as an octet stream where a C byte is
1747
                 * wider than 8 bits; add the counter as big-endian octets. */
1748
            #ifdef WORD64_AVAILABLE
1749
                BytesFromWordsBE64(ctrBuf, &reseedCtr, 8);
1750
                array_add(drbg->V, sizeof(drbg->V), ctrBuf, 8);
1751
            #else
1752
                BytesFromWordsBE32(ctrBuf, &reseedCtr, 4);
1753
                array_add(drbg->V, sizeof(drbg->V), ctrBuf, 4);
1754
            #endif
1755
#else
1756
0
            #ifdef LITTLE_ENDIAN_ORDER
1757
0
                #ifdef WORD64_AVAILABLE
1758
0
                reseedCtr = ByteReverseWord64(reseedCtr);
1759
                #else
1760
                reseedCtr = ByteReverseWord32(reseedCtr);
1761
                #endif
1762
0
            #endif
1763
0
                array_add(drbg->V, sizeof(drbg->V),
1764
0
                                          (byte*)&reseedCtr, sizeof(reseedCtr));
1765
0
#endif
1766
0
                ret = DRBG_SUCCESS;
1767
0
                drbg->reseedCtr++;
1768
0
            }
1769
            /* else no state mutation, hence no reseed counter increment. */
1770
0
        }
1771
0
        ForceZero(digest, WC_SHA256_DIGEST_SIZE);
1772
    #if (!defined(WOLFSSL_SMALL_STACK) || \
1773
         defined(WOLFSSL_SMALL_STACK_CACHE)) && \
1774
        defined(WOLFSSL_CHECK_MEM_ZERO)
1775
        wc_MemZero_Check(digest, WC_SHA256_DIGEST_SIZE);
1776
    #endif
1777
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1778
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
1779
    #endif
1780
0
    }
1781
1782
    #ifdef WC_VERBOSE_RNG
1783
    if ((ret != DRBG_SUCCESS) && (ret != WC_NO_ERR_TRACE(DRBG_FAILURE))) {
1784
        /* see note above regarding log spam reduction */
1785
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Generate failed with err %d.",
1786
                             ret);
1787
    }
1788
    #endif
1789
1790
0
    if ((thisV != drbg->V) && (thisV != NULL))
1791
0
        ForceZero(thisV, DRBG_SEED_LEN);
1792
0
    WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
1793
1794
0
    if (ret == 0)
1795
0
        return DRBG_SUCCESS;
1796
0
    else {
1797
        /* wipe the stranded output, which would otherwise be repeated
1798
         * on a subsequent successful call.
1799
         */
1800
0
        ForceZero(out, outSz);
1801
0
        return DRBG_FAILURE;
1802
0
    }
1803
0
}
1804
1805
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1806
static WARN_UNUSED_RESULT int Hash_DRBG_Init(DRBG_internal* drbg,
1807
                                             const byte* seed, word32 seedSz,
1808
                                             const byte* nonce, word32 nonceSz,
1809
                                             const byte* perso, word32 persoSz)
1810
0
{
1811
0
    if (seed == NULL)
1812
0
        return DRBG_FAILURE;
1813
1814
0
    if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
1815
0
                                              nonce, nonceSz,
1816
0
                                              perso, persoSz) == DRBG_SUCCESS &&
1817
0
        Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
1818
0
                                    sizeof(drbg->V), NULL, 0,
1819
0
                                    NULL, 0) == DRBG_SUCCESS) {
1820
1821
0
        drbg->reseedCtr = 1;
1822
0
        return DRBG_SUCCESS;
1823
0
    }
1824
0
    else {
1825
0
        return DRBG_FAILURE;
1826
0
    }
1827
0
}
1828
1829
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1830
static WARN_UNUSED_RESULT int Hash_DRBG_Instantiate(DRBG_internal* drbg,
1831
                                 const byte* seed, word32 seedSz,
1832
                                 const byte* nonce, word32 nonceSz,
1833
                                 const byte* perso, word32 persoSz,
1834
                                 void* heap, int devId)
1835
0
{
1836
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
1837
1838
0
    XMEMSET(drbg, 0, sizeof(DRBG_internal));
1839
#ifdef WC_RNG_HAVE_NEXT_SEED
1840
    wolfSSL_Atomic_Int_Init(&drbg->nextSeedLen, WC_DRBG_NEXT_SEED_EMPTY);
1841
#endif
1842
0
    drbg->heap = heap;
1843
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1844
    drbg->devId = devId;
1845
#else
1846
0
    (void)devId;
1847
0
#endif
1848
1849
#ifdef WOLFSSL_SMALL_STACK_CACHE
1850
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1851
        ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
1852
    #else
1853
        ret = wc_InitSha256(&drbg->sha256);
1854
    #endif
1855
    if (ret != 0)
1856
        return ret;
1857
#endif
1858
1859
0
    if (seed != NULL)
1860
0
        ret = Hash_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz,
1861
0
                             perso, persoSz);
1862
0
    return ret;
1863
0
}
1864
1865
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1866
static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg)
1867
0
{
1868
0
    word32 i;
1869
0
    int    compareSum = 0;
1870
0
    byte*  compareDrbg = (byte*)drbg;
1871
1872
#ifdef WOLFSSL_SMALL_STACK_CACHE
1873
    wc_Sha256Free(&drbg->sha256);
1874
#endif
1875
1876
0
    ForceZero(drbg, sizeof(DRBG_internal));
1877
1878
0
    for (i = 0; i < sizeof(DRBG_internal); i++) {
1879
0
        compareSum |= compareDrbg[i] ^ 0;
1880
0
    }
1881
1882
0
    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
1883
0
}
1884
1885
#endif /* !NO_SHA256 - SHA-256 Hash_DRBG core block */
1886
1887
/* ====================================================================== */
1888
/* SHA-512 Hash_DRBG (SP 800-90A Rev 1, Table 2)                          */
1889
/*                                                                        */
1890
/* Internal state (V, C): seedlen = 888 bits = 111 bytes each             */
1891
/* Output block length:   512 bits = 64 bytes (WC_SHA512_DIGEST_SIZE)     */
1892
/* Security strength:     256 bits                                        */
1893
/*                                                                        */
1894
/* NOTE: The raw entropy seed gathered at instantiation / reseed is       */
1895
/* WC_DRBG_SEED_SZ (1024 bits in FIPS builds), NOT seedlen.  We overseed  */
1896
/* to tolerate weak entropy sources.  Hash_df then compresses the seed    */
1897
/* material down to the 888-bit V and derives C from V.  See random.h.    */
1898
/* ====================================================================== */
1899
#ifdef WOLFSSL_DRBG_SHA512
1900
1901
0
#define OUTPUT_BLOCK_LEN_SHA512  (WC_SHA512_DIGEST_SIZE)  /* 64 bytes */
1902
1903
/* Hash Derivation Function using SHA-512 */
1904
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
1905
static WARN_UNUSED_RESULT int Hash512_df(DRBG_SHA512_internal* drbg, byte* out,
1906
                                         word32 outSz,
1907
                      byte type,
1908
                      const byte* inA, word32 inASz,
1909
                      const byte* inB, word32 inBSz,
1910
                      const byte* inC, word32 inCSz)
1911
0
{
1912
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
1913
0
    byte ctr;
1914
0
    word32 i;
1915
0
    word32 len;
1916
0
    word32 bits = (outSz * 8);
1917
#ifdef WOLFSSL_WIDE_BYTE
1918
    byte bitsBuf[4]; /* the 32-bit length as four big-endian octets */
1919
#endif
1920
#ifdef WOLFSSL_SMALL_STACK_CACHE
1921
    wc_Sha512* sha = &drbg->sha512;
1922
#else
1923
0
    wc_Sha512 sha[1];
1924
0
#endif
1925
#if defined(WOLFSSL_SMALL_STACK_CACHE)
1926
    byte* digest = drbg->digest_scratch;
1927
#elif defined(WOLFSSL_SMALL_STACK)
1928
    byte* digest;
1929
#else
1930
#if defined(__GNUC__) && !defined(__clang__) && defined(__AVX512F__)
1931
    /* Use a jumbo alignment to work around a gcc compiler/optimizer bug that
1932
     * assumes AVX512 alignment in an object sized correctly for AVX512 passed
1933
     * to builtin memcpy(), which promptly crashes if not thus aligned.
1934
     */
1935
    byte digest[WC_SHA512_DIGEST_SIZE] WOLFSSL_ALIGN(WC_SHA512_DIGEST_SIZE);
1936
#else
1937
0
    byte digest[WC_SHA512_DIGEST_SIZE];
1938
0
#endif
1939
0
#endif
1940
1941
0
    if (drbg == NULL) {
1942
0
        return DRBG_FAILURE;
1943
0
    }
1944
1945
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1946
    digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
1947
        DYNAMIC_TYPE_DIGEST);
1948
    if (digest == NULL)
1949
        return DRBG_FAILURE;
1950
#endif
1951
1952
#ifdef WOLFSSL_CHECK_MEM_ZERO
1953
    /* poison so a missed ForceZero on any path is caught by the check */
1954
    XMEMSET(digest, 0xff, WC_SHA512_DIGEST_SIZE);
1955
    wc_MemZero_Add("Hash512_df digest", digest, WC_SHA512_DIGEST_SIZE);
1956
#endif
1957
1958
#ifdef WOLFSSL_WIDE_BYTE
1959
    BytesFromWordsBE32(bitsBuf, &bits, 4);   /* see Hash_df */
1960
#elif defined(LITTLE_ENDIAN_ORDER)
1961
0
    bits = ByteReverseWord32(bits);
1962
0
#endif
1963
0
    len = (outSz / OUTPUT_BLOCK_LEN_SHA512)
1964
0
        + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0);
1965
1966
0
    ctr = 1;
1967
0
    for (i = 0; i < len; i++) {
1968
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
1969
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1970
        ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
1971
    #else
1972
0
        ret = wc_InitSha512(sha);
1973
0
    #endif
1974
0
        if (ret != 0)
1975
0
            break;
1976
0
#endif
1977
0
        ret = wc_Sha512Update(sha, &ctr, sizeof(ctr));
1978
0
        if (ret == 0) {
1979
0
            ctr++;
1980
#ifdef WOLFSSL_WIDE_BYTE
1981
            ret = wc_Sha512Update(sha, bitsBuf, sizeof(bitsBuf));
1982
#else
1983
0
            ret = wc_Sha512Update(sha, (byte*)&bits, sizeof(bits));
1984
0
#endif
1985
0
        }
1986
1987
0
        if (ret == 0) {
1988
            /* churning V is the only string that doesn't have the type added */
1989
0
            if (type != drbgInitV)
1990
0
                ret = wc_Sha512Update(sha, &type, sizeof(type));
1991
0
        }
1992
0
        if (ret == 0)
1993
0
            ret = wc_Sha512Update(sha, inA, inASz);
1994
0
        if (ret == 0) {
1995
0
            if (inB != NULL && inBSz > 0)
1996
0
                ret = wc_Sha512Update(sha, inB, inBSz);
1997
0
        }
1998
0
        if (ret == 0) {
1999
0
            if (inC != NULL && inCSz > 0)
2000
0
                ret = wc_Sha512Update(sha, inC, inCSz);
2001
0
        }
2002
0
        if (ret == 0)
2003
0
            ret = wc_Sha512Final(sha, digest);
2004
#ifdef WOLFSSL_SMALL_STACK_CACHE
2005
        if (ret != 0)
2006
            (void)wc_Sha512Reset(sha);
2007
#else
2008
0
        wc_Sha512Free(sha);
2009
0
#endif
2010
0
        if (ret == 0) {
2011
0
            if (outSz > OUTPUT_BLOCK_LEN_SHA512) {
2012
0
                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512);
2013
0
                outSz -= OUTPUT_BLOCK_LEN_SHA512;
2014
0
                out += OUTPUT_BLOCK_LEN_SHA512;
2015
0
            }
2016
0
            else {
2017
0
                XMEMCPY(out, digest, outSz);
2018
0
            }
2019
0
        }
2020
0
        else {
2021
0
            break;
2022
0
        }
2023
0
    }
2024
2025
0
    ForceZero(digest, WC_SHA512_DIGEST_SIZE);
2026
    /* Explicit check only where the buffer is NOT XFREEd (XFREE auto-checks):
2027
     * the stack build and the small-stack-cache build (drbg member). */
2028
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2029
    defined(WOLFSSL_CHECK_MEM_ZERO)
2030
    wc_MemZero_Check(digest, WC_SHA512_DIGEST_SIZE);
2031
#endif
2032
2033
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2034
    XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2035
#endif
2036
2037
#ifdef WC_VERBOSE_RNG
2038
    if (ret != 0)
2039
        WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __func__,
2040
                             ret);
2041
#endif
2042
2043
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
2044
0
}
2045
2046
/* Returns: DRBG_SUCCESS or DRBG_FAILURE.  No state mutation on failure. */
2047
static WARN_UNUSED_RESULT int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg,
2048
                               const byte* seed, word32 seedSz,
2049
                               const byte* additional, word32 additionalSz)
2050
0
{
2051
0
    int ret;
2052
0
    WC_DECLARE_VAR(newV_C, byte, DRBG_SHA512_SEED_LEN * 2, 0);
2053
0
    byte *newV, *newC;
2054
2055
0
    if (drbg == NULL) {
2056
0
        return DRBG_FAILURE;
2057
0
    }
2058
2059
#ifdef WOLFSSL_SMALL_STACK_CACHE
2060
    newV_C = drbg->seed_scratch;
2061
#else
2062
0
    WC_ALLOC_VAR_EX(newV_C, byte, DRBG_SHA512_SEED_LEN * 2, drbg->heap,
2063
0
        DYNAMIC_TYPE_TMP_BUFFER, return DRBG_FAILURE);
2064
0
#endif
2065
0
    XMEMSET(newV_C, 0, DRBG_SHA512_SEED_LEN * 2);
2066
#ifdef WOLFSSL_CHECK_MEM_ZERO
2067
    wc_MemZero_Add("Hash512_DRBG_Reseed newV_C", newV_C,
2068
                   DRBG_SHA512_SEED_LEN * 2);
2069
#endif
2070
2071
0
    newV = newV_C;
2072
0
    newC = newV + DRBG_SHA512_SEED_LEN;
2073
2074
0
    ret = Hash512_df(drbg, newV, DRBG_SHA512_SEED_LEN, drbgReseed,
2075
0
                drbg->V, sizeof(drbg->V), seed, seedSz,
2076
0
                additional, additionalSz);
2077
0
    if (ret == DRBG_SUCCESS) {
2078
0
        ret = Hash512_df(drbg, newC, DRBG_SHA512_SEED_LEN, drbgInitC, newV,
2079
0
                                    DRBG_SHA512_SEED_LEN, NULL, 0,
2080
0
                                    NULL, 0);
2081
0
    }
2082
0
    if (ret == DRBG_SUCCESS) {
2083
0
        XMEMCPY(drbg->V, newV, DRBG_SHA512_SEED_LEN);
2084
0
        XMEMCPY(drbg->C, newC, DRBG_SHA512_SEED_LEN);
2085
0
        drbg->reseedCtr = 1;
2086
0
    }
2087
2088
0
    ForceZero(newV_C, DRBG_SHA512_SEED_LEN * 2);
2089
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2090
    defined(WOLFSSL_CHECK_MEM_ZERO)
2091
    wc_MemZero_Check(newV_C, DRBG_SHA512_SEED_LEN * 2);
2092
#endif
2093
2094
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2095
0
    WC_FREE_VAR_EX(newV_C, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2096
0
#endif
2097
2098
0
    return ret;
2099
0
}
2100
2101
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
2102
static WARN_UNUSED_RESULT int Hash512_gen(DRBG_SHA512_internal* drbg,
2103
                                          byte* out, word32 outSz,
2104
                                          const byte* V)
2105
0
{
2106
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
2107
0
    word32 i;
2108
0
    word32 len;
2109
#if defined(WOLFSSL_SMALL_STACK_CACHE)
2110
    wc_Sha512* sha = &drbg->sha512;
2111
    byte* data = drbg->seed_scratch; /* Note, top half of seed_scratch is used
2112
                                      * by Hash_DRBG_Generate(). */
2113
    byte* digest = drbg->digest_scratch;
2114
#elif defined(WOLFSSL_SMALL_STACK)
2115
    wc_Sha512 sha[1];
2116
    byte* data = NULL;
2117
    byte* digest = NULL;
2118
#else
2119
0
    wc_Sha512 sha[1];
2120
0
    byte data[DRBG_SHA512_SEED_LEN];
2121
0
    byte digest[WC_SHA512_DIGEST_SIZE];
2122
0
#endif
2123
2124
0
    if (drbg == NULL) {
2125
0
        return DRBG_FAILURE;
2126
0
    }
2127
2128
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2129
    data = (byte*)XMALLOC(DRBG_SHA512_SEED_LEN, drbg->heap,
2130
        DYNAMIC_TYPE_TMP_BUFFER);
2131
    digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
2132
        DYNAMIC_TYPE_DIGEST);
2133
    if (data == NULL || digest == NULL) {
2134
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2135
        XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2136
        return DRBG_FAILURE;
2137
    }
2138
#endif
2139
2140
    /* Special case: outSz is 0 and out is NULL (Hash_DRBG_StirGenerate()): run
2141
     * a single Hashgen iteration with the block discarded, so the caller gets
2142
     * Generate's V-advance side effects without emitting output.  This
2143
     * preserves standard SP 800-90A sequencing, while presenting call semantics
2144
     * that are convenient for the stir. */
2145
0
    if (outSz == 0) {
2146
0
        outSz = 1;
2147
0
    }
2148
2149
0
    len = (outSz / OUTPUT_BLOCK_LEN_SHA512)
2150
0
        + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0);
2151
2152
0
    XMEMCPY(data, V, DRBG_SHA512_SEED_LEN);
2153
#ifdef WOLFSSL_CHECK_MEM_ZERO
2154
    wc_MemZero_Add("Hash512_gen data", data, DRBG_SHA512_SEED_LEN);
2155
#endif
2156
0
    for (i = 0; i < len; i++) {
2157
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2158
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2159
        ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
2160
    #else
2161
0
        ret = wc_InitSha512(sha);
2162
0
    #endif
2163
0
        if (ret == 0)
2164
0
#endif
2165
0
            ret = wc_Sha512Update(sha, data, DRBG_SHA512_SEED_LEN);
2166
0
        if (ret == 0)
2167
0
            ret = wc_Sha512Final(sha, digest);
2168
#ifdef WOLFSSL_SMALL_STACK_CACHE
2169
        if (ret != 0)
2170
            (void)wc_Sha512Reset(sha);
2171
#else
2172
0
        wc_Sha512Free(sha);
2173
0
#endif
2174
2175
0
        if (ret == 0) {
2176
0
            if (out != NULL && outSz != 0) {
2177
0
                if (outSz >= OUTPUT_BLOCK_LEN_SHA512) {
2178
0
                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512);
2179
0
                    outSz -= OUTPUT_BLOCK_LEN_SHA512;
2180
0
                    out += OUTPUT_BLOCK_LEN_SHA512;
2181
0
                    array_add_one(data, DRBG_SHA512_SEED_LEN);
2182
0
                }
2183
0
                else {
2184
0
                    XMEMCPY(out, digest, outSz);
2185
0
                    outSz = 0;
2186
0
                }
2187
0
            }
2188
0
        }
2189
0
        else {
2190
0
            break;
2191
0
        }
2192
0
    }
2193
0
    ForceZero(data, DRBG_SHA512_SEED_LEN);
2194
#if (!defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2195
    defined(WOLFSSL_CHECK_MEM_ZERO)
2196
    wc_MemZero_Check(data, DRBG_SHA512_SEED_LEN);
2197
#endif
2198
2199
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2200
0
    WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2201
0
    WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2202
0
#endif
2203
2204
0
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
2205
0
}
2206
2207
/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE.  DRBG state is
2208
 * always consistent upon return, whether success or failure. */
2209
static WARN_UNUSED_RESULT int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg,
2210
                                 byte* out, word32 outSz,
2211
                                 const byte* additional, word32 additionalSz)
2212
0
{
2213
0
    int ret;
2214
#ifdef WOLFSSL_SMALL_STACK_CACHE
2215
    wc_Sha512* sha = &drbg->sha512;
2216
#else
2217
0
    wc_Sha512 sha[1];
2218
0
#endif
2219
0
    byte type;
2220
0
    word64 reseedCtr;
2221
#ifdef WOLFSSL_WIDE_BYTE
2222
    byte ctrBuf[8]; /* reseed counter as big-endian octets */
2223
#endif
2224
0
    byte *thisV = NULL;
2225
0
    WC_DECLARE_VAR(shadowV, byte, DRBG_SHA512_SEED_LEN, 0);
2226
2227
0
    if (drbg == NULL) {
2228
0
        return DRBG_FAILURE;
2229
0
    }
2230
2231
0
    if (drbg->reseedCtr >= WC_RESEED_INTERVAL) {
2232
0
        return DRBG_NEED_RESEED;
2233
0
    }
2234
0
    else {
2235
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
2236
        byte* digest = drbg->digest_scratch;
2237
    #elif defined(WOLFSSL_SMALL_STACK)
2238
        byte* digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap,
2239
            DYNAMIC_TYPE_DIGEST);
2240
        if (digest == NULL)
2241
            return DRBG_FAILURE;
2242
    #else
2243
0
        byte digest[WC_SHA512_DIGEST_SIZE];
2244
0
    #endif
2245
2246
    #ifdef WOLFSSL_CHECK_MEM_ZERO
2247
        /* baseline 0; registered across the whole generate, force-zeroed and
2248
         * checked at the single exit below (all paths funnel there). */
2249
        XMEMSET(digest, 0, WC_SHA512_DIGEST_SIZE);
2250
        wc_MemZero_Add("Hash512_DRBG_Generate digest", digest,
2251
            WC_SHA512_DIGEST_SIZE);
2252
    #endif
2253
2254
0
        type = drbgGenerateH;
2255
0
        reseedCtr = drbg->reseedCtr;
2256
2257
        /* SP 800-90A Section 10.1.1.4 step 2:
2258
         * If additional_input != Null, w = Hash(0x02 || V || additional_input),
2259
         * V = (V + w) mod 2^seedlen */
2260
0
        ret = DRBG_SUCCESS;
2261
0
        if (additional != NULL && additionalSz > 0) {
2262
0
            byte addType = drbgGenerateW; /* 0x02 */
2263
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2264
0
            ret = 0;
2265
0
            WC_ALLOC_VAR_EX(shadowV, byte, DRBG_SHA512_SEED_LEN, drbg->heap,
2266
0
                            DYNAMIC_TYPE_TMP_BUFFER, ret = MEMORY_E);
2267
0
            if (ret == 0) {
2268
0
                thisV = shadowV;
2269
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2270
                ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
2271
        #else
2272
0
                ret = wc_InitSha512(sha);
2273
0
        #endif
2274
0
            }
2275
2276
0
            if (ret != 0) {
2277
0
                WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2278
                /* digest holds only the 0 baseline here (never written) */
2279
            #if (!defined(WOLFSSL_SMALL_STACK) || \
2280
                 defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2281
                defined(WOLFSSL_CHECK_MEM_ZERO)
2282
                wc_MemZero_Check(digest, WC_SHA512_DIGEST_SIZE);
2283
            #endif
2284
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2285
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2286
            #endif
2287
0
                return DRBG_FAILURE;
2288
0
            }
2289
#else
2290
            (void)shadowV;
2291
            /* use the upper half of drbg->seed_scratch -- the lower half is
2292
             * used by Hash512_gen() for its "data" work buffer. */
2293
            thisV = drbg->seed_scratch + DRBG_SHA512_SEED_LEN;
2294
            ret = 0;
2295
#endif
2296
0
            if (ret == 0)
2297
0
                ret = wc_Sha512Update(sha, &addType, sizeof(addType));
2298
0
            if (ret == 0)
2299
0
                ret = wc_Sha512Update(sha, drbg->V, sizeof(drbg->V));
2300
0
            if (ret == 0)
2301
0
                ret = wc_Sha512Update(sha, additional, additionalSz);
2302
0
            if (ret == 0)
2303
0
                ret = wc_Sha512Final(sha, digest);
2304
#ifdef WOLFSSL_SMALL_STACK_CACHE
2305
            if (ret != 0)
2306
                (void)wc_Sha512Reset(sha);
2307
#else
2308
0
            wc_Sha512Free(sha);
2309
0
#endif
2310
0
            if (ret == 0) {
2311
0
                XMEMCPY(thisV, drbg->V, DRBG_SHA512_SEED_LEN);
2312
0
                array_add(thisV, DRBG_SHA512_SEED_LEN, digest,
2313
0
                          WC_SHA512_DIGEST_SIZE);
2314
0
            }
2315
0
            else {
2316
0
                WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2317
0
                ForceZero(digest, WC_SHA512_DIGEST_SIZE);
2318
            #if (!defined(WOLFSSL_SMALL_STACK) || \
2319
                 defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2320
                defined(WOLFSSL_CHECK_MEM_ZERO)
2321
                wc_MemZero_Check(digest, WC_SHA512_DIGEST_SIZE);
2322
            #endif
2323
            #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2324
                XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2325
            #endif
2326
0
                return DRBG_FAILURE;
2327
0
            }
2328
0
        }
2329
0
        else {
2330
0
            thisV = drbg->V;
2331
0
        }
2332
2333
0
        if (ret == 0)
2334
0
            ret = Hash512_gen(drbg, out, outSz, thisV);
2335
0
        if (ret == DRBG_SUCCESS) {
2336
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
2337
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2338
            ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId);
2339
        #else
2340
0
            ret = wc_InitSha512(sha);
2341
0
        #endif
2342
0
            if (ret == 0)
2343
0
#endif
2344
0
                ret = wc_Sha512Update(sha, &type, sizeof(type));
2345
0
            if (ret == 0)
2346
0
                ret = wc_Sha512Update(sha, thisV, DRBG_SHA512_SEED_LEN);
2347
0
            if (ret == 0)
2348
0
                ret = wc_Sha512Final(sha, digest);
2349
#ifdef WOLFSSL_SMALL_STACK_CACHE
2350
            if (ret != 0)
2351
                (void)wc_Sha512Reset(sha);
2352
#else
2353
0
            wc_Sha512Free(sha);
2354
0
#endif
2355
2356
0
            if (ret == 0) {
2357
                /* No failure possible from here -- commit thisV if needed. */
2358
0
                if (thisV != drbg->V)
2359
0
                    XMEMCPY(drbg->V, thisV, DRBG_SHA512_SEED_LEN);
2360
0
                array_add(drbg->V, sizeof(drbg->V), digest,
2361
0
                          WC_SHA512_DIGEST_SIZE);
2362
0
                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
2363
#ifdef WOLFSSL_WIDE_BYTE
2364
                /* See Hash_DRBG_Generate. */
2365
                BytesFromWordsBE64(ctrBuf, &reseedCtr, 8);
2366
                array_add(drbg->V, sizeof(drbg->V), ctrBuf, 8);
2367
#else
2368
0
            #ifdef LITTLE_ENDIAN_ORDER
2369
0
                reseedCtr = ByteReverseWord64(reseedCtr);
2370
0
            #endif
2371
0
                array_add(drbg->V, sizeof(drbg->V),
2372
0
                                          (byte*)&reseedCtr, sizeof(reseedCtr));
2373
0
#endif
2374
0
                ret = DRBG_SUCCESS;
2375
0
                drbg->reseedCtr++;
2376
0
            }
2377
            /* else no state mutation, hence no reseed counter increment. */
2378
0
        }
2379
0
        ForceZero(digest, WC_SHA512_DIGEST_SIZE);
2380
    #if (!defined(WOLFSSL_SMALL_STACK) || \
2381
         defined(WOLFSSL_SMALL_STACK_CACHE)) && \
2382
        defined(WOLFSSL_CHECK_MEM_ZERO)
2383
        wc_MemZero_Check(digest, WC_SHA512_DIGEST_SIZE);
2384
    #endif
2385
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2386
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
2387
    #endif
2388
0
    }
2389
2390
0
    if ((thisV != drbg->V) && (thisV != NULL))
2391
0
        ForceZero(thisV, DRBG_SHA512_SEED_LEN);
2392
0
    WC_FREE_VAR_EX(shadowV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
2393
2394
0
    if (ret == 0)
2395
0
        return DRBG_SUCCESS;
2396
0
    else {
2397
        /* wipe the stranded output, which would otherwise be repeated
2398
         * on a subsequent successful call.
2399
         */
2400
0
        ForceZero(out, outSz);
2401
0
        return DRBG_FAILURE;
2402
0
    }
2403
0
}
2404
2405
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
2406
static WARN_UNUSED_RESULT int Hash512_DRBG_Init(DRBG_SHA512_internal* drbg,
2407
                             const byte* seed, word32 seedSz,
2408
                             const byte* nonce, word32 nonceSz,
2409
                             const byte* perso, word32 persoSz)
2410
0
{
2411
0
    if (seed == NULL)
2412
0
        return DRBG_FAILURE;
2413
2414
0
    if (Hash512_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
2415
0
                                              nonce, nonceSz,
2416
0
                                              perso, persoSz) == DRBG_SUCCESS &&
2417
0
        Hash512_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
2418
0
                                    sizeof(drbg->V), NULL, 0,
2419
0
                                    NULL, 0) == DRBG_SUCCESS) {
2420
2421
0
        drbg->reseedCtr = 1;
2422
0
        return DRBG_SUCCESS;
2423
0
    }
2424
0
    else {
2425
0
        return DRBG_FAILURE;
2426
0
    }
2427
0
}
2428
2429
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
2430
static WARN_UNUSED_RESULT int Hash512_DRBG_Instantiate(
2431
                                    DRBG_SHA512_internal* drbg,
2432
                                    const byte* seed, word32 seedSz,
2433
                                    const byte* nonce, word32 nonceSz,
2434
                                    const byte* perso, word32 persoSz,
2435
                                    void* heap, int devId)
2436
0
{
2437
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
2438
2439
0
    XMEMSET(drbg, 0, sizeof(DRBG_SHA512_internal));
2440
#ifdef WC_RNG_HAVE_NEXT_SEED
2441
    wolfSSL_Atomic_Int_Init(&drbg->nextSeedLen, WC_DRBG_NEXT_SEED_EMPTY);
2442
#endif
2443
0
    drbg->heap = heap;
2444
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2445
    drbg->devId = devId;
2446
#else
2447
0
    (void)devId;
2448
0
#endif
2449
2450
#ifdef WOLFSSL_SMALL_STACK_CACHE
2451
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2452
        ret = wc_InitSha512_ex(&drbg->sha512, drbg->heap, drbg->devId);
2453
    #else
2454
        ret = wc_InitSha512(&drbg->sha512);
2455
    #endif
2456
    if (ret != 0)
2457
        return ret;
2458
#endif
2459
2460
0
    if (seed != NULL)
2461
0
        ret = Hash512_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz,
2462
0
                                perso, persoSz);
2463
0
    return ret;
2464
0
}
2465
2466
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
2467
static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg)
2468
0
{
2469
0
    word32 i;
2470
0
    int    compareSum = 0;
2471
0
    byte*  compareDrbg = (byte*)drbg;
2472
2473
#ifdef WOLFSSL_SMALL_STACK_CACHE
2474
    wc_Sha512Free(&drbg->sha512);
2475
#endif
2476
2477
0
    ForceZero(drbg, sizeof(DRBG_SHA512_internal));
2478
2479
0
    for (i = 0; i < sizeof(DRBG_SHA512_internal); i++) {
2480
0
        compareSum |= compareDrbg[i] ^ 0;
2481
0
    }
2482
2483
0
    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
2484
0
}
2485
2486
#endif /* WOLFSSL_DRBG_SHA512 */
2487
2488
/* Uncredited stirring, per SP 800-90A 10.1.1.4 generate with additional_input
2489
 * (step 2: V += Hash(0x02 || V || additional_input)).  The generate is
2490
 * zero-length: Hash_gen()'s (and Hash512_gen()'s) outSz==0 mode banks the
2491
 * generated block for the continuous-test hook (its consumer is
2492
 * configuration-dependent; no comparison state lives in this file), and
2493
 * out is never dereferenced.  The reseed counter is incremented as for any
2494
 * generate, and quarantine/stratum are untouched, so the no-claims doctrine
2495
 * holds as a theorem of the standard rather than a property of a custom
2496
 * transition.  Refused with NOT_READY_E when the instance is quarantined or due
2497
 * for a credited reseed: a generate must not run past the reseed interval. */
2498
2499
static WARN_UNUSED_RESULT int Hash_DRBG_StirGenerate(WC_RNG* rng,
2500
                                                     const byte* add,
2501
                                                     word32 addSz)
2502
0
{
2503
0
    wc_drbg_reseed_ctr_t ctr = 0;
2504
0
    int ret;
2505
2506
#ifdef WC_RNG_HAVE_LOCK
2507
    /* The lock word is the atomic source of truth for quarantine: the
2508
     * invalidator's counter saturation can be lost to a racing
2509
     * lease-holder's plain reseedCtr++, but the latch cannot.  Checked
2510
     * before the counter for exactly that reason. */
2511
    if (WOLFSSL_ATOMIC_LOAD(rng->lock) & WC_RNG_LOCK_ENTROPY_INVALIDATED)
2512
        return NOT_READY_E;
2513
#endif
2514
0
    ret = wc_RNG_DRBG_GetReseedCtr(rng, &ctr);
2515
0
    if (ret != 0)
2516
0
        return ret;
2517
0
    if (ctr >= WC_RESEED_INTERVAL)
2518
0
        return NOT_READY_E;
2519
2520
0
    ret = RNG_FAILURE_E;
2521
0
#ifndef NO_SHA256
2522
0
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
2523
0
        ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, NULL, 0,
2524
0
                                 add, addSz);
2525
0
    }
2526
0
#endif
2527
0
#ifdef WOLFSSL_DRBG_SHA512
2528
0
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
2529
0
        ret = Hash512_DRBG_Generate((DRBG_SHA512_internal *)rng->drbg512,
2530
0
                                    NULL, 0, add, addSz);
2531
0
    }
2532
0
#endif
2533
#ifdef WC_RNG_DEBUG_STATS
2534
    if (ret == 0)
2535
        ++rng->_stats_stirs; /* counts uncredited stir-generates. */
2536
#endif
2537
2538
0
    if (ret == DRBG_NEED_RESEED)
2539
0
        return NOT_READY_E;
2540
0
    else if (ret > 0)
2541
0
        return RNG_FAILURE_E;
2542
0
    else
2543
0
        return ret;
2544
0
}
2545
2546
static WARN_UNUSED_RESULT int wc_RNG_DRBG_Stir_Nonce_local(WC_RNG* rng,
2547
                                        const byte* seed, word32 seedSz,
2548
                                        const byte *nonce, word32 nonceSz)
2549
0
{
2550
0
    if (rng == NULL || seed == NULL)
2551
0
        return BAD_FUNC_ARG;
2552
0
    if ((nonce == NULL) && (nonceSz != 0))
2553
0
        return BAD_FUNC_ARG;
2554
2555
0
    if (rng->status != WC_DRBG_OK)
2556
0
        return RNG_FAILURE_E;
2557
2558
0
    {
2559
0
        int lock_ret = rng_lock_required_check(rng);
2560
0
        if (lock_ret != 0)
2561
0
            return lock_ret;
2562
0
    }
2563
2564
0
    {
2565
0
        int ret = Hash_DRBG_StirGenerate(rng, seed, seedSz);
2566
0
        if ((ret == 0) && (nonce != NULL) && (nonceSz > 0)) {
2567
            /* Second chunk as its own specified generate: additional
2568
             * input is per-call, and chunking beats concatenation
2569
             * scratch. */
2570
0
            ret = Hash_DRBG_StirGenerate(rng, nonce, nonceSz);
2571
0
        }
2572
0
        return ret;
2573
0
    }
2574
0
}
2575
2576
int wc_RNG_DRBG_Stir_Nonce(WC_RNG* rng, const byte* seed, word32 seedSz,
2577
                           const byte *nonce, word32 nonceSz)
2578
0
{
2579
0
    int ret;
2580
2581
0
    if (rng == NULL)
2582
0
        return BAD_FUNC_ARG;
2583
0
    ret = RngAutoLockEnter(rng);
2584
0
    if (ret != 0)
2585
0
        return ret;
2586
0
    ret = wc_RNG_DRBG_Stir_Nonce_local(rng, seed, seedSz, nonce, nonceSz);
2587
0
    RngAutoLockExit(rng);
2588
0
    return ret;
2589
0
}
2590
2591
int wc_RNG_DRBG_Stir(WC_RNG* rng, const byte* seed, word32 seedSz)
2592
0
{
2593
0
    return wc_RNG_DRBG_Stir_Nonce(rng, seed, seedSz, NULL, 0);
2594
0
}
2595
2596
/* FIPS 140-3 IG 10.3.A / SP800-90B Health Tests for Seed Data
2597
 *
2598
 * These tests replace the older FIPS 140-2 Continuous Random Number Generator
2599
 * Test (CRNGT) with more mathematically robust statistical tests per
2600
 * ISO 19790 / SP800-90B requirements.
2601
 *
2602
 * When HAVE_ENTROPY_MEMUSE is defined, the wolfentropy.c jitter-based TRNG
2603
 * performs another set of these health tests, but those are on the noise not
2604
 * the conditioned output so we still need to retest here even in that case
2605
 * to evaluate the conditioned output for the same behavior. These tests ensure
2606
 * the seed data meets basic entropy requirements regardless of the source.
2607
 */
2608
2609
/* SP800-90B 4.4.1 - Repetition Count Test
2610
 * Detects if the noise source becomes "stuck" producing repeated output.
2611
 *
2612
 * C = 1 + ceil(-log2(alpha) / H)
2613
 * For alpha = 2^-30 (false positive probability) and H = 1 (min entropy):
2614
 * C = 1 + ceil(30 / 1) = 31
2615
 */
2616
#ifndef WC_RNG_SEED_RCT_CUTOFF
2617
0
    #define WC_RNG_SEED_RCT_CUTOFF 31
2618
#endif
2619
2620
/* SP800-90B 4.4.2 - Adaptive Proportion Test
2621
 * Monitors if a particular sample value appears too frequently within a
2622
 * window of samples, indicating loss of entropy.
2623
 *
2624
 * Window size W = 512 for non-binary alphabet (byte values 0-255)
2625
 * C = 1 + CRITBINOM(W, 2^(-H), 1-alpha)
2626
 * For alpha = 2^-30 and H = 1, W = 512:
2627
 * C = 1 + CRITBINOM(512, 0.5, 1-2^-30) = 325
2628
 */
2629
#ifndef WC_RNG_SEED_APT_WINDOW
2630
0
    #define WC_RNG_SEED_APT_WINDOW 512
2631
#endif
2632
#ifndef WC_RNG_SEED_APT_CUTOFF
2633
0
    #define WC_RNG_SEED_APT_CUTOFF 325
2634
#endif
2635
2636
int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
2637
0
{
2638
0
    int ret = 0;
2639
2640
0
    word32 i;
2641
0
    int rctFailed = 0;
2642
0
    int aptFailed = 0;
2643
2644
0
    if (seed == NULL || seedSz < SEED_BLOCK_SZ) {
2645
0
        return BAD_FUNC_ARG;
2646
0
    }
2647
2648
    /* SP800-90B 4.4.1 - Repetition Count Test (RCT)
2649
     * Check for consecutive identical bytes that would indicate a stuck
2650
     * entropy source. Fail if we see WC_RNG_SEED_RCT_CUTOFF or more
2651
     * consecutive identical values.
2652
     *
2653
     * Constant-time implementation: always process full seed, accumulate
2654
     * failure status without early exit to prevent timing side-channels.
2655
     */
2656
0
    {
2657
0
        int repCount = 1;
2658
0
        byte prevByte = seed[0];
2659
2660
0
        for (i = 1; i < seedSz; i++) {
2661
            /* Constant-time: always evaluate both branches effects */
2662
0
            int match = (seed[i] == prevByte);
2663
            /* If match, increment count, if not, reset to 1 */
2664
0
            repCount = (match * (repCount + 1)) + (!match * 1);
2665
            /* Update prevByte only when not matching (new value) */
2666
0
            prevByte = (byte) ((match * prevByte) + (!match * seed[i]));
2667
            /* Accumulate failure flag - once set, stays set */
2668
0
            rctFailed |= (repCount >= WC_RNG_SEED_RCT_CUTOFF);
2669
0
        }
2670
0
    }
2671
2672
    /* SP800-90B 4.4.2 - Adaptive Proportion Test (APT)
2673
     * Check that no single byte value appears too frequently within
2674
     * a sliding window. This detects bias in the entropy source.
2675
     *
2676
     * For seeds smaller than the window size, we test the entire seed.
2677
     * For larger seeds, we use a sliding window approach.
2678
     *
2679
     * Constant-time implementation: always process full seed and check
2680
     * all counts to prevent timing side-channels.
2681
     */
2682
0
    {
2683
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2684
        word16* byteCounts = NULL;
2685
    #else
2686
0
        word16 byteCounts[MAX_ENTROPY_BITS];
2687
0
    #endif
2688
0
        word32 windowSize = min(seedSz, (word32)WC_RNG_SEED_APT_WINDOW);
2689
0
        word32 windowStart = 0;
2690
0
        word32 newIdx;
2691
2692
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2693
        byteCounts = (word16*)XMALLOC(MAX_ENTROPY_BITS * sizeof(word16), NULL,
2694
                                      DYNAMIC_TYPE_TMP_BUFFER);
2695
        if (byteCounts == NULL)
2696
            return MEMORY_E;
2697
    #endif
2698
0
        XMEMSET(byteCounts, 0, MAX_ENTROPY_BITS * sizeof(word16));
2699
2700
        /* Indices are WC_OCTET-masked: byteCounts has 256 entries, but a
2701
         * byte cell can exceed 255 where CHAR_BIT != 8, so an unmasked seed
2702
         * value would index out of bounds. */
2703
0
        for (i = 0; i < windowSize; i++) {
2704
0
            byteCounts[WC_OCTET(seed[i])]++;
2705
0
        }
2706
2707
        /* Check first window - scan all 256 counts */
2708
0
        for (i = 0; i < MAX_ENTROPY_BITS; i++) {
2709
0
            aptFailed |= (byteCounts[i] >= WC_RNG_SEED_APT_CUTOFF);
2710
0
        }
2711
2712
        /* Slide window through remaining seed data */
2713
0
        while ((windowStart + windowSize) < seedSz) {
2714
            /* Remove byte leaving the window */
2715
0
            byteCounts[WC_OCTET(seed[windowStart])]--;
2716
0
            windowStart++;
2717
2718
            /* Add byte entering the window */
2719
0
            newIdx = windowStart + windowSize - 1;
2720
0
            byteCounts[WC_OCTET(seed[newIdx])]++;
2721
2722
            /* Accumulate failure flag for new byte's count */
2723
0
            aptFailed |= (byteCounts[WC_OCTET(seed[newIdx])] >=
2724
0
                          WC_RNG_SEED_APT_CUTOFF);
2725
0
        }
2726
2727
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
2728
        XFREE(byteCounts, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2729
    #endif
2730
0
    }
2731
2732
    /* Set return code based on accumulated failure flags */
2733
0
    if (rctFailed) {
2734
0
        ret = ENTROPY_RT_E;
2735
0
    }
2736
0
    else if (aptFailed) {
2737
0
        ret = ENTROPY_APT_E;
2738
0
    }
2739
2740
0
    return ret;
2741
0
}
2742
/* Runtime DRBG disable/enable API -- only available in non-selftest and
2743
 * FIPS v7+ builds (older FIPS/selftest random.c doesn't have these) */
2744
#if !defined(HAVE_SELFTEST) && \
2745
    (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
2746
#ifndef NO_SHA256
2747
int wc_Sha256Drbg_Disable(void)
2748
0
{
2749
0
    int ret;
2750
0
#ifdef WOLFSSL_DRBG_SHA512
2751
0
    ret = LockDrbgState();
2752
0
    if (ret != 0)
2753
0
        return ret;
2754
0
    if (sha512DrbgDisabled) {
2755
0
        UnlockDrbgState();
2756
0
        return BAD_STATE_E;  /* can't disable both */
2757
0
    }
2758
0
    sha256DrbgDisabled = 1;
2759
0
    UnlockDrbgState();
2760
0
    return 0;
2761
#else
2762
    (void)ret;
2763
    return NOT_COMPILED_IN;
2764
#endif
2765
0
}
2766
2767
int wc_Sha256Drbg_Enable(void)
2768
0
{
2769
0
    int ret = LockDrbgState();
2770
0
    if (ret != 0)
2771
0
        return ret;
2772
0
    sha256DrbgDisabled = 0;
2773
0
    UnlockDrbgState();
2774
0
    return 0;
2775
0
}
2776
2777
int wc_Sha256Drbg_IsDisabled(void)
2778
0
{
2779
0
    int val;
2780
0
    if (LockDrbgState() != 0)
2781
0
        return 1; /* fail-safe: report disabled on mutex error */
2782
0
    val = sha256DrbgDisabled;
2783
0
    UnlockDrbgState();
2784
0
    return val;
2785
0
}
2786
#else
2787
/* When SHA-256 is not compiled in, these are stubs */
2788
int wc_Sha256Drbg_Disable(void) { return NOT_COMPILED_IN; }
2789
int wc_Sha256Drbg_Enable(void) { return 0; }
2790
int wc_Sha256Drbg_IsDisabled(void) { return 1; } /* always disabled */
2791
#endif /* !NO_SHA256 */
2792
2793
#ifdef WOLFSSL_DRBG_SHA512
2794
int wc_Sha512Drbg_Disable(void)
2795
0
{
2796
0
    int ret = LockDrbgState();
2797
0
    if (ret != 0)
2798
0
        return ret;
2799
0
#ifndef NO_SHA256
2800
0
    if (sha256DrbgDisabled) {
2801
0
        UnlockDrbgState();
2802
0
        return BAD_STATE_E;  /* can't disable both */
2803
0
    }
2804
0
#endif
2805
0
    sha512DrbgDisabled = 1;
2806
0
    UnlockDrbgState();
2807
0
    return 0;
2808
0
}
2809
2810
int wc_Sha512Drbg_Enable(void)
2811
0
{
2812
0
    int ret = LockDrbgState();
2813
0
    if (ret != 0)
2814
0
        return ret;
2815
0
    sha512DrbgDisabled = 0;
2816
0
    UnlockDrbgState();
2817
0
    return 0;
2818
0
}
2819
2820
int wc_Sha512Drbg_IsDisabled(void)
2821
0
{
2822
0
    int val;
2823
0
    if (LockDrbgState() != 0)
2824
0
        return 1; /* fail-safe: report disabled on mutex error */
2825
0
    val = sha512DrbgDisabled;
2826
0
    UnlockDrbgState();
2827
0
    return val;
2828
0
}
2829
#endif /* WOLFSSL_DRBG_SHA512 */
2830
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
2831
#else
2832
    /* no Hash DRBG, so no lock for the backends to hold */
2833
    #define RngAutoLockEnter(rng) 0
2834
    #define RngAutoLockExit(rng)  WC_DO_NOTHING
2835
#endif /* HAVE_HASHDRBG */
2836
/* End NIST DRBG Code */
2837
2838
/* Semantics of "flags":
2839
 *
2840
 * Security attributes are fixed at instantiation and caller-declared -- the
2841
 * constructor never reads the target object.  _LOCK_REQUIRED sets the sticky
2842
 * WC_RNG_LOCK_REQUIRED latch bit at birth, so there is no reachable state in
2843
 * which the instance serves without its lock policy.  _LOCK_INITIALLY sets
2844
 * WC_RNG_LOCK_HELD at birth: the caller is the lease holder from the first
2845
 * instruction -- the flag for constructing into a held lease (a lease-holding
2846
 * reinitialization keeps the instance invariantly locked across the reinit), to
2847
 * be released by wc_RNG_lock_put() as usual.  _USE_FULL_MUTEX layers a blocking
2848
 * wolfSSL_Mutex outermost around wc_RNG_lock_get() and wc_RNG_lock_put*() --
2849
 * for user-mode sharing of one instance among threads, where spinning on the
2850
 * CAS would be wrong; contending getters sleep in wc_LockMutex().  The inner
2851
 * latch (and every other wc_RNG_lock_*() operation) is unchanged.
2852
 * NOT_COMPILED_IN unless WC_RNG_HAVE_LOCK_FULL_MUTEX; composes with
2853
 * _LOCK_INITIALLY (born held at both layers).  wc_FreeRng() releases (if the
2854
 * latch is held) and frees the mutex.
2855
 */
2856
static WARN_UNUSED_RESULT int _InitRng(WC_RNG* rng,
2857
                    const byte* nonce, word32 nonceSz,
2858
                    const byte *perso, word32 persoSz,
2859
                    void* heap, int devId, WC_RNG* seedRng, word32 flags)
2860
0
{
2861
0
    int ret = 0;
2862
0
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
2863
#if !defined(HAVE_FIPS) && defined(WOLFSSL_RNG_USE_FULL_SEED)
2864
    word32 seedSz = SEED_SZ;
2865
#else
2866
0
    word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
2867
0
#endif
2868
0
    WC_DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
2869
0
    int drbg_instantiated = 0;
2870
#ifdef WOLFSSL_SMALL_STACK_CACHE
2871
    int drbg_scratch_instantiated = 0;
2872
#endif
2873
0
#endif
2874
2875
0
    (void)nonce;
2876
0
    (void)nonceSz;
2877
0
    (void)perso;
2878
0
    (void)persoSz;
2879
    /* seedRng is consumed only in the seed-acquisition arm; cast for
2880
     * configurations that compile that arm out. */
2881
0
    (void)seedRng;
2882
2883
0
    if (rng == NULL)
2884
0
        return BAD_FUNC_ARG;
2885
0
    if (nonce == NULL && nonceSz != 0)
2886
0
        return BAD_FUNC_ARG;
2887
0
    if (perso == NULL && persoSz != 0)
2888
0
        return BAD_FUNC_ARG;
2889
2890
    /* Checked before the build tests below, so a contradictory request is
2891
     * refused the same way everywhere rather than depending on the build. */
2892
0
    if ((flags & WC_RNG_INIT_FLAG_USE_AUTO_LOCK) &&
2893
0
        (flags & (WC_RNG_INIT_FLAG_NO_AUTO_LOCK |
2894
0
                  WC_RNG_INIT_FLAG_USE_FULL_MUTEX)))
2895
0
    {
2896
0
        return BAD_FUNC_ARG;
2897
0
    }
2898
0
#ifndef WC_RNG_HAVE_NEXT_SEED
2899
0
    if (flags & WC_RNG_INIT_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED)
2900
0
        return NOT_COMPILED_IN;
2901
0
#endif
2902
0
#ifndef WC_RNG_HAVE_LOCK_FULL_MUTEX
2903
0
    if (flags & WC_RNG_INIT_FLAG_USE_FULL_MUTEX)
2904
0
        return NOT_COMPILED_IN;
2905
0
#endif
2906
#ifndef WC_RNG_HAVE_AUTO_LOCK
2907
    /* Refuse rather than return an instance the caller believes is locked.
2908
     * Turning it off where there is none to turn off stays a no-op. */
2909
    if (flags & WC_RNG_INIT_FLAG_USE_AUTO_LOCK)
2910
        return NOT_COMPILED_IN;
2911
#endif
2912
2913
#ifdef WC_RNG_HAVE_LOCK
2914
    if (flags & (WC_RNG_INIT_FLAG_LOCK_REQUIRED |
2915
                 WC_RNG_INIT_FLAG_LOCK_INITIALLY))
2916
    {
2917
        word32 initial_flags =
2918
            ((flags & WC_RNG_INIT_FLAG_LOCK_REQUIRED) ?
2919
             WC_RNG_LOCK_REQUIRED : 0) |
2920
            ((flags & WC_RNG_INIT_FLAG_LOCK_INITIALLY) ?
2921
             WC_RNG_LOCK_HELD : 0);
2922
        XMEMSET(rng, 0, WC_OFFSETOF(WC_RNG, lock));
2923
        XMEMSET((byte *)rng + WC_OFFSETOF(WC_RNG, lock) + sizeof(rng->lock), 0,
2924
                sizeof(*rng) -
2925
                (WC_OFFSETOF(WC_RNG, lock) + sizeof(rng->lock)));
2926
        #ifdef WC_RNG_DEBUG_STATS
2927
        if (flags & WC_RNG_INIT_FLAG_LOCK_INITIALLY)
2928
            rng->_stats_locks_taken = 1;
2929
        #endif
2930
#ifdef WOLFSSL_NO_ATOMICS
2931
        rng->lock = initial_flags;
2932
#else
2933
        wolfSSL_Atomic_Uint_Init(&rng->lock, initial_flags);
2934
#endif
2935
    }
2936
    else
2937
#endif /* WC_RNG_HAVE_LOCK */
2938
0
    {
2939
0
        XMEMSET(rng, 0, sizeof(*rng));
2940
0
    }
2941
2942
#ifdef WC_RNG_HAVE_RBGC
2943
    if (seedRng == NULL)
2944
        rng->RBGCStratum = 0;
2945
    else {
2946
        if (seedRng->RBGCStratum >= WC_MAX_SINT_OF(int))
2947
            return SEQ_OVERFLOW_E;
2948
        else if (seedRng->RBGCStratum == WC_RNG_RBGC_USER_SEED_STRATUM - 1)
2949
            return SEQ_OVERFLOW_E;
2950
        rng->RBGCStratum = seedRng->RBGCStratum + 1;
2951
    }
2952
#endif
2953
2954
#ifdef WOLFSSL_HEAP_TEST
2955
    rng->heap = (void*)WOLFSSL_HEAP_TEST;
2956
    (void)heap;
2957
#else
2958
0
    rng->heap = heap;
2959
0
#endif
2960
0
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
2961
0
    rng->pid = getpid();
2962
0
#endif
2963
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
2964
    rng->devId = devId;
2965
    #if defined(WOLF_CRYPTO_CB)
2966
        rng->seed.devId = devId;
2967
    #endif
2968
#else
2969
0
    (void)devId;
2970
0
#endif
2971
2972
0
#ifdef HAVE_HASHDRBG
2973
    /* init the DBRG to known values */
2974
0
#ifndef NO_SHA256
2975
0
    rng->drbg = NULL;
2976
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2977
    rng->drbg_scratch = NULL;
2978
    #endif
2979
0
#endif /* !NO_SHA256 */
2980
0
#ifdef WOLFSSL_DRBG_SHA512
2981
0
    rng->drbg512 = NULL;
2982
    #ifdef WOLFSSL_SMALL_STACK_CACHE
2983
    rng->drbg512_scratch = NULL;
2984
    rng->health_check_scratch_512 = NULL;
2985
    #endif
2986
0
#endif /* WOLFSSL_DRBG_SHA512 */
2987
#ifdef WOLFSSL_SMALL_STACK_CACHE
2988
    rng->newSeed_buf = NULL;
2989
    #ifndef NO_SHA256
2990
    rng->health_check_scratch = NULL;
2991
    #endif /* !NO_SHA256 */
2992
#endif /* WOLFSSL_SMALL_STACK_CACHE */
2993
0
    rng->status = DRBG_NOT_INIT;
2994
2995
    /* Select DRBG type: prefer SHA-512 unless disabled or not compiled.
2996
     * Hold the mutex for a consistent snapshot of both disable flags. */
2997
0
#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
2998
0
    ret = LockDrbgState();
2999
0
    if (ret != 0)
3000
0
        return ret;
3001
0
    #ifdef WOLFSSL_DRBG_SHA512
3002
0
    if (!sha512DrbgDisabled)
3003
0
        rng->drbgType = WC_DRBG_SHA512;
3004
0
    else
3005
0
    #endif /* WOLFSSL_DRBG_SHA512 */
3006
0
    #ifndef NO_SHA256
3007
0
    if (!sha256DrbgDisabled)
3008
0
        rng->drbgType = WC_DRBG_SHA256;
3009
0
    else
3010
0
    #endif /* !NO_SHA256 */
3011
0
    {
3012
0
        UnlockDrbgState();
3013
0
        return BAD_STATE_E; /* no DRBG available */
3014
0
    }
3015
0
    UnlockDrbgState();
3016
#else
3017
    rng->drbgType = WC_DRBG_SHA256;
3018
#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
3019
0
#endif /* HAVE_HASHDRBG */
3020
3021
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) || \
3022
    defined(HAVE_AMD_RDSEED)
3023
    /* init the intel RD seed and/or rand */
3024
    wc_InitRng_IntelRD();
3025
#endif
3026
3027
    /* configure async RNG source if available */
3028
#ifdef WOLFSSL_ASYNC_CRYPT
3029
    ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
3030
                                                        rng->heap, rng->devId);
3031
    if (ret != 0) {
3032
    #ifdef HAVE_HASHDRBG
3033
        rng->status = DRBG_OK;
3034
    #endif
3035
        return ret;
3036
    }
3037
#endif
3038
3039
#ifdef HAVE_INTEL_RDRAND
3040
    /* if CPU supports RDRAND, use it directly and bypass DRBG init */
3041
    if (IS_INTEL_RDRAND(intel_flags)) {
3042
    #ifdef HAVE_HASHDRBG
3043
        rng->status = DRBG_OK;
3044
    #endif
3045
#ifdef WC_RNG_HAVE_RBGC
3046
        /* undo stratum increment */
3047
        if (seedRng != NULL)
3048
            rng->RBGCStratum = 0;
3049
#endif
3050
        return 0;
3051
    }
3052
#endif
3053
3054
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
3055
    ret = wc_VersalTrngInit(nonce, nonceSz);
3056
    if (ret) {
3057
    #ifdef HAVE_HASHDRBG
3058
        rng->status = DRBG_OK;
3059
    #endif
3060
        return ret;
3061
    }
3062
#endif
3063
3064
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && !defined(USE_WINDOWS_API)
3065
    if (!rng->seed.seedFdOpen)
3066
        rng->seed.fd = XBADFD;
3067
#endif
3068
3069
#ifdef CUSTOM_RAND_GENERATE_BLOCK
3070
    ret = 0; /* success */
3071
#else
3072
3073
#ifdef WC_RNG_HAVE_NEXT_SEED
3074
    wolfSSL_Atomic_Int_Init(&rng->nextStirLen,
3075
                            WC_DRBG_NEXT_SEED_EMPTY);
3076
#endif
3077
3078
 /* not CUSTOM_RAND_GENERATE_BLOCK follows */
3079
0
#ifdef HAVE_HASHDRBG
3080
0
    if (nonceSz == 0) {
3081
0
        seedSz = MAX_SEED_SZ;
3082
0
    }
3083
3084
0
#ifndef NO_SHA256
3085
0
    if (rng->drbgType == WC_DRBG_SHA256) {
3086
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
3087
0
        rng->drbg =
3088
0
            (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap,
3089
0
                                  DYNAMIC_TYPE_RNG);
3090
0
        if (rng->drbg == NULL) {
3091
        #if defined(DEBUG_WOLFSSL)
3092
            WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
3093
                           sizeof(DRBG_internal));
3094
        #endif
3095
0
            ret = MEMORY_E;
3096
0
            rng->status = DRBG_FAILED;
3097
0
        }
3098
    #else
3099
        rng->drbg = (struct DRBG*)&rng->drbg_data;
3100
    #endif /* WOLFSSL_NO_MALLOC or WOLFSSL_STATIC_MEMORY */
3101
3102
    #ifdef WOLFSSL_SMALL_STACK_CACHE
3103
        if (ret == 0) {
3104
            rng->drbg_scratch =
3105
                (DRBG_internal *)XMALLOC(sizeof(DRBG_internal), rng->heap,
3106
                                         DYNAMIC_TYPE_RNG);
3107
            if (rng->drbg_scratch == NULL) {
3108
    #if defined(DEBUG_WOLFSSL)
3109
                WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
3110
                               sizeof(DRBG_internal));
3111
    #endif
3112
                ret = MEMORY_E;
3113
                rng->status = DRBG_FAILED;
3114
            }
3115
        }
3116
3117
        if (ret == 0) {
3118
            ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch,
3119
                        NULL, 0, NULL, 0, NULL, 0, rng->heap, devId);
3120
            if (ret == 0)
3121
                drbg_scratch_instantiated = 1;
3122
        }
3123
3124
        if (ret == 0) {
3125
            rng->health_check_scratch =
3126
                (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, rng->heap,
3127
                                DYNAMIC_TYPE_TMP_BUFFER);
3128
            if (rng->health_check_scratch == NULL) {
3129
                ret = MEMORY_E;
3130
                rng->status = DRBG_FAILED;
3131
            }
3132
        }
3133
    #endif /* WOLFSSL_SMALL_STACK_CACHE */
3134
0
    } /* WC_DRBG_SHA256 */
3135
0
#endif /* !NO_SHA256 */
3136
3137
0
#ifdef WOLFSSL_DRBG_SHA512
3138
0
    if (rng->drbgType == WC_DRBG_SHA512) {
3139
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
3140
0
        rng->drbg512 =
3141
0
            (struct DRBG_SHA512*)XMALLOC(sizeof(DRBG_SHA512_internal),
3142
0
                                         rng->heap, DYNAMIC_TYPE_RNG);
3143
0
        if (rng->drbg512 == NULL) {
3144
        #if defined(DEBUG_WOLFSSL)
3145
            WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
3146
                           sizeof(DRBG_SHA512_internal));
3147
        #endif
3148
0
            ret = MEMORY_E;
3149
0
            rng->status = DRBG_FAILED;
3150
0
        }
3151
    #else
3152
        rng->drbg512 = (struct DRBG_SHA512*)&rng->drbg512_data;
3153
    #endif
3154
3155
    #ifdef WOLFSSL_SMALL_STACK_CACHE
3156
        if (ret == 0) {
3157
            rng->drbg512_scratch =
3158
                (DRBG_SHA512_internal *)XMALLOC(sizeof(DRBG_SHA512_internal),
3159
                    rng->heap, DYNAMIC_TYPE_RNG);
3160
            if (rng->drbg512_scratch == NULL) {
3161
                ret = MEMORY_E;
3162
                rng->status = DRBG_FAILED;
3163
            }
3164
        }
3165
3166
        if (ret == 0) {
3167
            ret = Hash512_DRBG_Instantiate(rng->drbg512_scratch,
3168
                        NULL, 0, NULL, 0, NULL, 0, rng->heap, devId);
3169
            if (ret == 0)
3170
                drbg_scratch_instantiated = 1;
3171
        }
3172
3173
        if (ret == 0) {
3174
            rng->health_check_scratch_512 =
3175
                (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE_SHA512, rng->heap,
3176
                                DYNAMIC_TYPE_TMP_BUFFER);
3177
            if (rng->health_check_scratch_512 == NULL) {
3178
                ret = MEMORY_E;
3179
                rng->status = DRBG_FAILED;
3180
            }
3181
        }
3182
    #endif /* WOLFSSL_SMALL_STACK_CACHE */
3183
0
    } /* WC_DRBG_SHA512 */
3184
0
#endif /* WOLFSSL_DRBG_SHA512 */
3185
3186
    /* newSeed_buf shared by both DRBG types for PollAndReSeed */
3187
#ifdef WOLFSSL_SMALL_STACK_CACHE
3188
    if (ret == 0) {
3189
        rng->newSeed_buf = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
3190
                           DYNAMIC_TYPE_SEED);
3191
        if (rng->newSeed_buf == NULL) {
3192
            ret = MEMORY_E;
3193
            rng->status = DRBG_FAILED;
3194
        }
3195
    }
3196
#endif /* WOLFSSL_SMALL_STACK_CACHE */
3197
3198
0
    if (ret == 0) {
3199
0
        ret = wc_RNG_HealthTestLocal(rng, 0, rng->heap, devId);
3200
0
        if (ret != 0) {
3201
        #if defined(DEBUG_WOLFSSL)
3202
            WOLFSSL_MSG_EX("wc_RNG_HealthTestLocal failed err = %d", ret);
3203
        #endif
3204
0
        }
3205
0
    }
3206
3207
    #ifdef WOLFSSL_SMALL_STACK
3208
    if (ret == 0) {
3209
        WC_ALLOC_VAR_EX(seed, byte, MAX_SEED_SZ, rng->heap, DYNAMIC_TYPE_SEED,
3210
                        WC_DO_NOTHING);
3211
        if (seed == NULL) {
3212
            ret = MEMORY_E;
3213
            rng->status = DRBG_FAILED;
3214
        }
3215
    }
3216
    #endif
3217
3218
0
    if (ret != 0) {
3219
#if defined(DEBUG_WOLFSSL)
3220
        WOLFSSL_MSG_EX("_InitRng failed. err = %d", ret);
3221
#endif
3222
0
    }
3223
0
    else {
3224
0
        if (seedRng != NULL) {
3225
            /* RBGC spawn: draw the seed material from the parent DRBG's
3226
             * generate function in place of the module's seed source -- the SP
3227
             * 800-90C RBG chain construction.  The root DRBG is implicitly
3228
             * healthy, so the seed Health test is omitted; all subsequent
3229
             * handling (seed byte accounting, instantiate, failure disposition)
3230
             * is then identical to the primary seed path. */
3231
0
            ret = wc_RNG_GenerateBlock(seedRng, seed, seedSz);
3232
0
        }
3233
0
        else {
3234
#ifdef WC_RNG_SEED_CB
3235
            if (seedCb == NULL) {
3236
                ret = DRBG_NO_SEED_CB;
3237
            }
3238
            else {
3239
                ret = seedCb(&rng->seed, seed, seedSz);
3240
                if (ret != 0) {
3241
#ifdef WC_VERBOSE_RNG
3242
                    WOLFSSL_DEBUG_PRINTF(
3243
                        "ERROR: seedCb in _InitRng() failed with err = %d",
3244
                        ret);
3245
#endif
3246
                    ret = DRBG_FAILURE;
3247
                }
3248
            }
3249
#else
3250
0
            ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
3251
0
#endif /* WC_RNG_SEED_CB */
3252
0
        }
3253
3254
#ifdef WOLFSSL_CHECK_MEM_ZERO
3255
        /* seed now holds entropy; register across DRBG instantiation */
3256
        wc_MemZero_Add("_InitRng seed", seed, seedSz);
3257
#endif
3258
3259
0
        if (ret != 0) {
3260
    #if defined(DEBUG_WOLFSSL)
3261
            WOLFSSL_MSG_EX("Seed generation failed... %d", ret);
3262
    #elif defined(WC_VERBOSE_RNG)
3263
            WOLFSSL_DEBUG_PRINTF(
3264
                "ERROR: seed acquisition in _InitRng() failed with err %d",
3265
                ret);
3266
    #endif
3267
0
            ret = DRBG_FAILURE;
3268
0
            rng->status = DRBG_FAILED;
3269
0
        }
3270
3271
        /* Health-check the primary seed -- RBGC seed is implicitly healthy. */
3272
3273
0
        if ((ret == 0) && (seedRng == NULL)) {
3274
0
            ret = wc_RNG_TestSeed(seed, seedSz);
3275
            #if defined(DEBUG_WOLFSSL)
3276
            if (ret != 0) {
3277
                WOLFSSL_MSG_EX("wc_RNG_TestSeed failed... %d", ret);
3278
            }
3279
            #elif defined(WC_VERBOSE_RNG)
3280
            if (ret != DRBG_SUCCESS) {
3281
                WOLFSSL_DEBUG_PRINTF(
3282
                    "ERROR: wc_RNG_TestSeed() in _InitRng() returned err %d.",
3283
                    ret);
3284
            }
3285
            #endif
3286
0
        }
3287
3288
        /* Instantiate the DRBG */
3289
3290
0
        if (ret == DRBG_SUCCESS) {
3291
0
#ifndef NO_SHA256
3292
0
            if (rng->drbgType == WC_DRBG_SHA256)
3293
0
                ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg,
3294
0
                #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED)
3295
0
                            seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
3296
                #else
3297
                            seed, seedSz,
3298
                #endif
3299
0
                            nonce, nonceSz, perso, persoSz, rng->heap, devId);
3300
0
#endif
3301
0
#ifdef WOLFSSL_DRBG_SHA512
3302
0
            if (rng->drbgType == WC_DRBG_SHA512)
3303
0
                ret = Hash512_DRBG_Instantiate(
3304
0
                    (DRBG_SHA512_internal *)rng->drbg512,
3305
0
                #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED)
3306
0
                    seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
3307
                #else
3308
                    seed, seedSz,
3309
                #endif
3310
0
                    nonce, nonceSz, perso, persoSz, rng->heap, devId);
3311
0
#endif
3312
0
            if (ret == 0)
3313
0
                drbg_instantiated = 1;
3314
0
        }
3315
0
    } /* ret == 0 */
3316
3317
    /* Unconditionally burn the seed data. */
3318
3319
    #ifdef WOLFSSL_SMALL_STACK
3320
    if (seed)
3321
    #endif
3322
0
    {
3323
0
        ForceZero(seed, seedSz);
3324
    #if !defined(WOLFSSL_SMALL_STACK) && defined(WOLFSSL_CHECK_MEM_ZERO)
3325
        /* heap build's WC_FREE_VAR_EX/XFREE auto-checks; stack build needs it */
3326
        wc_MemZero_Check(seed, seedSz);
3327
    #endif
3328
0
    }
3329
0
    WC_FREE_VAR_EX(seed, rng->heap, DYNAMIC_TYPE_SEED);
3330
3331
0
    if (ret == DRBG_SUCCESS) {
3332
#ifdef WOLFSSL_CHECK_MEM_ZERO
3333
    #ifndef NO_SHA256
3334
        if (rng->drbgType == WC_DRBG_SHA256) {
3335
            struct DRBG_internal* drbg = (struct DRBG_internal*)rng->drbg;
3336
            wc_MemZero_Add("DRBG V", &drbg->V, sizeof(drbg->V));
3337
            wc_MemZero_Add("DRBG C", &drbg->C, sizeof(drbg->C));
3338
        }
3339
    #endif
3340
#endif
3341
3342
0
        rng->status = DRBG_OK;
3343
0
        ret = 0;
3344
0
    }
3345
0
    else if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
3346
0
        rng->status = DRBG_CONT_FAILED;
3347
0
        ret = DRBG_CONT_FIPS_E;
3348
0
    }
3349
0
    else if (ret == WC_NO_ERR_TRACE(DRBG_FAILURE)) {
3350
0
        rng->status = DRBG_FAILED;
3351
0
        ret = RNG_FAILURE_E;
3352
0
    }
3353
0
    else {
3354
0
        rng->status = DRBG_FAILED;
3355
0
    }
3356
0
#endif /* HAVE_HASHDRBG */
3357
0
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
3358
3359
#ifdef WC_RNG_HAVE_NEXT_SEED
3360
    if ((ret == 0) &&
3361
        (flags & WC_RNG_INIT_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED))
3362
    {
3363
        rng->flags |= WC_RNG_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED;
3364
    }
3365
#endif
3366
0
    if ((ret == 0) && (flags & WC_RNG_INIT_FLAG_USE_FULL_MUTEX)) {
3367
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3368
        /* deliberately the last init step: no failure path can strand an
3369
         * initialized mutex. */
3370
        ret = wc_InitMutex(&rng->mutex);
3371
        if (ret == 0) {
3372
            rng->flags |= WC_RNG_FLAG_FULL_MUTEX;
3373
            if (flags & WC_RNG_INIT_FLAG_LOCK_INITIALLY) {
3374
                /* born held at both layers: the constructor's caller holds
3375
                 * the whole latch, mutex included. */
3376
                ret = wc_LockMutex(&rng->mutex);
3377
            }
3378
        }
3379
#endif
3380
0
    }
3381
3382
0
    if (ret != 0) {
3383
    #ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3384
        if (rng->flags & WC_RNG_FLAG_FULL_MUTEX) {
3385
            /* covers wc_LockMutex() failure after successful
3386
             * wc_InitMutex() (WC_RNG_INIT_FLAG_LOCK_INITIALLY). */
3387
            (void)wc_FreeMutex(&rng->mutex);
3388
            rng->flags &= ~WC_RNG_FLAG_FULL_MUTEX;
3389
        }
3390
    #endif
3391
0
    #if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
3392
0
    #ifndef NO_SHA256
3393
0
        if (rng->drbgType == WC_DRBG_SHA256) {
3394
0
            if (drbg_instantiated) {
3395
0
                (void)Hash_DRBG_Uninstantiate(
3396
0
                    (DRBG_internal *)rng->drbg);
3397
0
            }
3398
0
            #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
3399
0
            XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
3400
0
            #endif
3401
0
            rng->drbg = NULL;
3402
            #ifdef WOLFSSL_SMALL_STACK_CACHE
3403
            XFREE(rng->health_check_scratch, rng->heap,
3404
                   DYNAMIC_TYPE_TMP_BUFFER);
3405
            rng->health_check_scratch = NULL;
3406
            if (drbg_scratch_instantiated)
3407
                (void)Hash_DRBG_Uninstantiate(
3408
                    (DRBG_internal *)rng->drbg_scratch);
3409
            XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
3410
            rng->drbg_scratch = NULL;
3411
            #endif /* WOLFSSL_SMALL_STACK_CACHE */
3412
0
        }
3413
0
    #endif /* !NO_SHA256 */
3414
0
    #ifdef WOLFSSL_DRBG_SHA512
3415
0
        if (rng->drbgType == WC_DRBG_SHA512) {
3416
0
            if (drbg_instantiated) {
3417
0
                (void)Hash512_DRBG_Uninstantiate(
3418
0
                    (DRBG_SHA512_internal *)rng->drbg512);
3419
0
            }
3420
0
            #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
3421
0
            XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG);
3422
0
            #endif
3423
0
            rng->drbg512 = NULL;
3424
            #ifdef WOLFSSL_SMALL_STACK_CACHE
3425
            XFREE(rng->health_check_scratch_512, rng->heap,
3426
                   DYNAMIC_TYPE_TMP_BUFFER);
3427
            rng->health_check_scratch_512 = NULL;
3428
            if (drbg_scratch_instantiated)
3429
                (void)Hash512_DRBG_Uninstantiate(rng->drbg512_scratch);
3430
            XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG);
3431
            rng->drbg512_scratch = NULL;
3432
            #endif /* WOLFSSL_SMALL_STACK_CACHE */
3433
0
        }
3434
0
    #endif /* WOLFSSL_DRBG_SHA512 */
3435
    #ifdef WOLFSSL_SMALL_STACK_CACHE
3436
        XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED);
3437
        rng->newSeed_buf = NULL;
3438
    #endif
3439
0
    #endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */
3440
0
    }
3441
3442
0
#ifdef WC_RNG_HAVE_AUTO_LOCK
3443
0
    if ((ret == 0) && !(flags & WC_RNG_INIT_FLAG_NO_AUTO_LOCK) &&
3444
0
        (WC_RNG_AUTO_LOCK_DEFAULT ||
3445
0
         (flags & WC_RNG_INIT_FLAG_USE_AUTO_LOCK))) {
3446
0
        ret = RngAutoLockInit(rng);
3447
0
        if (ret != 0)
3448
0
            (void)wc_FreeRng(rng);
3449
0
    }
3450
0
#endif
3451
0
    return ret;
3452
0
}
3453
3454
3455
WOLFSSL_ABI
3456
WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap)
3457
0
{
3458
0
    int ret = 0;
3459
0
    WC_RNG* rng = NULL;
3460
3461
    /* Assume if WC_USE_DEVID it is intended for default usage */
3462
#ifdef WC_USE_DEVID
3463
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, WC_USE_DEVID);
3464
#else
3465
0
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, INVALID_DEVID);
3466
0
#endif
3467
3468
0
    if (ret != 0) {
3469
0
        return NULL;
3470
0
    }
3471
3472
0
    return rng;
3473
0
}
3474
3475
3476
int wc_rng_new_ex(WC_RNG **rng, byte* nonce, word32 nonceSz,
3477
                  void* heap, int devId)
3478
0
{
3479
0
    int ret;
3480
3481
0
    if (rng == NULL) {
3482
0
        return BAD_FUNC_ARG;
3483
0
    }
3484
3485
0
    *rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
3486
0
    if (*rng == NULL) {
3487
0
        return MEMORY_E;
3488
0
    }
3489
3490
0
    ret = _InitRng(*rng, nonce, nonceSz, NULL, 0, heap, devId, NULL,
3491
0
                   WC_RNG_INIT_FLAG_NONE);
3492
0
    if (ret != 0) {
3493
0
        XFREE(*rng, heap, DYNAMIC_TYPE_RNG);
3494
0
        *rng = NULL;
3495
0
    }
3496
3497
0
    return ret;
3498
0
}
3499
3500
3501
WOLFSSL_ABI
3502
void wc_rng_free(WC_RNG* rng)
3503
0
{
3504
0
    if (rng) {
3505
0
        void* heap = rng->heap;
3506
3507
0
        wc_FreeRng(rng);
3508
0
        ForceZero(rng, sizeof(WC_RNG));
3509
0
        XFREE(rng, heap, DYNAMIC_TYPE_RNG);
3510
0
        (void)heap;
3511
0
    }
3512
0
}
3513
3514
WOLFSSL_ABI
3515
int wc_InitRng(WC_RNG* rng)
3516
0
{
3517
0
    return _InitRng(rng, NULL, 0, NULL, 0, NULL, INVALID_DEVID, NULL,
3518
0
                    WC_RNG_INIT_FLAG_NONE);
3519
0
}
3520
3521
3522
int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
3523
0
{
3524
0
    return _InitRng(rng, NULL, 0, NULL, 0, heap, devId, NULL,
3525
0
                    WC_RNG_INIT_FLAG_NONE);
3526
0
}
3527
3528
3529
int wc_InitRngNonce(WC_RNG* rng, const byte* nonce, word32 nonceSz)
3530
0
{
3531
0
    return _InitRng(rng, nonce, nonceSz, NULL, 0, NULL, INVALID_DEVID, NULL,
3532
0
                    WC_RNG_INIT_FLAG_NONE);
3533
0
}
3534
3535
3536
int wc_InitRngNonce_ex(WC_RNG* rng, const byte* nonce, word32 nonceSz,
3537
                       void* heap, int devId)
3538
0
{
3539
0
    return _InitRng(rng, nonce, nonceSz, NULL, 0, heap, devId, NULL,
3540
0
                    WC_RNG_INIT_FLAG_NONE);
3541
0
}
3542
3543
int wc_InitRng_ex2(WC_RNG* rng, void* heap, int devId, word32 flags)
3544
0
{
3545
0
    return _InitRng(rng, NULL, 0, NULL, 0, heap, devId, NULL, flags);
3546
0
}
3547
3548
int wc_InitRngNonce_ex2(WC_RNG* rng, const byte* nonce, word32 nonceSz,
3549
                        const byte *perso, word32 persoSz,
3550
                        void* heap, int devId, word32 flags)
3551
0
{
3552
0
    return _InitRng(rng, nonce, nonceSz, perso, persoSz,
3553
0
                    heap, devId, NULL, flags);
3554
0
}
3555
3556
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
3557
3558
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
3559
static WARN_UNUSED_RESULT int PollAndReSeed(WC_RNG* rng, const byte* additional,
3560
                         word32 additionalSz);
3561
#endif
3562
3563
/* rng_pid_change_check() is used by wc_RNG_Pool_Extract(),
3564
 * wc_RNG_DRBG_NextSeedNow_Nonce(), and wc_RNG_GenerateBlock(), to assure that
3565
 * the RNG is freshly seeded after a fork(), to avoid seeding or generating from
3566
 * duplicated internal state.
3567
 */
3568
0
static WARN_UNUSED_RESULT WC_MAYBE_UNUSED int rng_pid_change_check(WC_RNG* rng) {
3569
0
    int ret = 0;
3570
0
    int my_pid = getpid();
3571
3572
0
    if (rng->pid == my_pid)
3573
0
        return 0;
3574
3575
0
    rng->pid = my_pid;
3576
3577
0
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
3578
0
    ret = PollAndReSeed(rng, NULL, 0);
3579
0
    if (ret != DRBG_SUCCESS) {
3580
0
        rng->status = DRBG_FAILED;
3581
0
        ret = RNG_FAILURE_E;
3582
0
    }
3583
0
#endif
3584
3585
#ifdef WC_RNG_HAVE_POOL
3586
    {
3587
        int ret2 = PoolPurge(rng);
3588
        if ((ret == 0) &&
3589
            (ret2 != 0) &&
3590
            (ret2 != WC_NO_ERR_TRACE(ALREADY_E)))
3591
        {
3592
            ret = ret2;
3593
        }
3594
    }
3595
#endif
3596
3597
#ifdef WC_RNG_HAVE_NEXT_SEED
3598
    WOLFSSL_ATOMIC_STORE(rng->nextStirLen,
3599
                         WC_DRBG_NEXT_SEED_EMPTY);
3600
    #ifndef NO_SHA256
3601
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
3602
        int ret2 = NextSeedPurge(&((DRBG_internal *)rng->drbg)->nextSeedLen,
3603
            ((DRBG_internal *)rng->drbg)->nextSeed,
3604
            (word32)sizeof(((DRBG_internal *)rng->drbg)->nextSeed));
3605
        if ((ret == 0) &&
3606
            (ret2 != 0) &&
3607
            (ret2 != WC_NO_ERR_TRACE(ALREADY_E)))
3608
        {
3609
            ret = ret2;
3610
        }
3611
    }
3612
    #endif
3613
    #ifdef WOLFSSL_DRBG_SHA512
3614
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
3615
        int ret2 =
3616
            NextSeedPurge(&((DRBG_SHA512_internal *)rng->drbg512)->nextSeedLen,
3617
            ((DRBG_SHA512_internal *)rng->drbg512)->nextSeed,
3618
            (word32)sizeof(((DRBG_SHA512_internal *)rng->drbg512)->nextSeed));
3619
        if ((ret == 0) &&
3620
            (ret2 != 0) &&
3621
            (ret2 != WC_NO_ERR_TRACE(ALREADY_E)))
3622
        {
3623
            ret = ret2;
3624
        }
3625
    }
3626
    #endif
3627
#endif /* WC_RNG_HAVE_NEXT_SEED */
3628
3629
0
    return ret;
3630
0
}
3631
#endif /* HAVE_GETPID && !WOLFSSL_NO_GETPID */
3632
3633
#ifdef WC_RNG_HAVE_LOCK
3634
3635
/* Note, in CAS updates here, the stored value derives only from expected and
3636
 * the caller's arguments, never from a prior load.  This assures no race with
3637
 * unlocked changes to any bits.
3638
 */
3639
3640
int wc_RNG_lock_get(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
3641
{
3642
    WC_RNG_lock_arg_t cur_lock;
3643
3644
    if (rng == NULL)
3645
        return BAD_FUNC_ARG;
3646
3647
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3648
    /* outermost blocking layer, when constructed with _USE_FULL_MUTEX:
3649
     * contending getters sleep here rather than seeing BUSY_E. */
3650
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX) {
3651
        if (wc_LockMutex(&rng->mutex) != 0) {
3652
            #ifdef WC_RNG_DEBUG_STATS
3653
            ++rng->_stats_locks_refused; /* racy */
3654
            #endif
3655
            return BAD_MUTEX_E;
3656
        }
3657
    }
3658
#endif
3659
3660
    /* extra_bits is allowed to assert WC_RNG_LOCK_REQUIRED, which is in the
3661
     * reserved section. */
3662
    extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3663
        WC_RNG_LOCK_REQUIRED;
3664
3665
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3666
3667
    if (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) {
3668
#ifdef WC_RNG_HAVE_NEXT_SEED
3669
        WC_ATOMIC_INT_ARG NextSeedCurrent;
3670
        if ((rng->flags & WC_RNG_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED) &&
3671
            (wc_RNG_DRBG_NextSeedCurrent(rng, &NextSeedCurrent) == 0) &&
3672
            (NextSeedCurrent == WC_DRBG_NEXT_SEED_READY))
3673
        {
3674
            /* cheap inline recovery available. */
3675
        }
3676
        else
3677
#endif
3678
        {
3679
            #ifdef WC_RNG_DEBUG_STATS
3680
            ++rng->_stats_locks_refused; /* racy */
3681
            #endif
3682
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3683
            if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3684
                (void)wc_UnLockMutex(&rng->mutex);
3685
#endif
3686
            return NEEDS_RECOVERY_E;
3687
        }
3688
    }
3689
3690
    if ((! (cur_lock & WC_RNG_LOCK_HELD)) &&
3691
        (wolfSSL_Atomic_Uint_CompareExchange(
3692
            &rng->lock, &cur_lock,
3693
            cur_lock | WC_RNG_LOCK_HELD | extra_bits)))
3694
    {
3695
        #ifdef WC_RNG_DEBUG_STATS
3696
        ++rng->_stats_locks_taken;
3697
        #endif
3698
3699
        /* If we arrived here via _RECOVER_AND_PROMOTE_FROM_NEXT_SEED with a
3700
         * pending NextSeed, there is a finite though minuscule chance that a
3701
         * second invalidation left the RNG without a banked seed to consume.
3702
         * In that case, the holder's generate falls through to the regular
3703
         * inline forced-reseed machinery.  This is the same outcome as an
3704
         * invalidation landing immediately after a successful acquire.
3705
         */
3706
3707
        return 0;
3708
    }
3709
3710
    #ifdef WC_RNG_DEBUG_STATS
3711
    ++rng->_stats_locks_refused;
3712
    #endif
3713
3714
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3715
    /* CAS failure with the mutex held means a non-mutex claimant holds
3716
     * the latch (mixed-discipline use); back out the mutex. */
3717
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3718
        (void)wc_UnLockMutex(&rng->mutex);
3719
#endif
3720
3721
    if (cur_lock & WC_RNG_LOCK_HELD)
3722
        return BUSY_E;
3723
    else if (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)
3724
        return NEEDS_RECOVERY_E;
3725
    else /* not reachable */
3726
        return UNEXPECTED_STATE_E;
3727
}
3728
3729
int wc_RNG_lock_get_conditional(WC_RNG* rng,
3730
                                WC_RNG_lock_arg_t expected_extra_bits,
3731
                                WC_RNG_lock_arg_t want_extra_bits)
3732
{
3733
    WC_RNG_lock_arg_t cur_lock, expected;
3734
3735
    if (rng == NULL)
3736
        return BAD_FUNC_ARG;
3737
3738
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3739
    /* outermost blocking layer, when constructed with _USE_FULL_MUTEX:
3740
     * contending getters sleep here rather than seeing BUSY_E. */
3741
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX) {
3742
        if (wc_LockMutex(&rng->mutex) != 0) {
3743
            #ifdef WC_RNG_DEBUG_STATS
3744
            ++rng->_stats_locks_refused; /* racy */
3745
            #endif
3746
            return BAD_MUTEX_E;
3747
        }
3748
    }
3749
#endif
3750
3751
    /* *_extra_bits are allowed to assert WC_RNG_LOCK_REQUIRED, which is in the
3752
     * reserved section.  Additionally, expected_extra_bits is allowed to
3753
     * include WC_RNG_LOCK_ENTROPY_INVALIDATED, for purposes of recovery. */
3754
    expected_extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3755
        WC_RNG_LOCK_REQUIRED | WC_RNG_LOCK_ENTROPY_INVALIDATED;
3756
    want_extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3757
        WC_RNG_LOCK_REQUIRED;
3758
3759
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3760
3761
    if ((cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) &&
3762
        (! (expected_extra_bits & WC_RNG_LOCK_ENTROPY_INVALIDATED)))
3763
    {
3764
        #ifdef WC_RNG_DEBUG_STATS
3765
        ++rng->_stats_locks_refused; /* racy */
3766
        #endif
3767
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3768
        if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3769
            (void)wc_UnLockMutex(&rng->mutex);
3770
#endif
3771
        return NEEDS_RECOVERY_E;
3772
    }
3773
3774
    expected = (cur_lock & (((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) &
3775
                            ~(WC_RNG_LOCK_HELD |
3776
                              WC_RNG_LOCK_ENTROPY_INVALIDATED))) |
3777
        expected_extra_bits;
3778
3779
    if ((! (cur_lock & WC_RNG_LOCK_HELD)) &&
3780
        (wolfSSL_Atomic_Uint_CompareExchange(
3781
            &rng->lock, &expected,
3782
            expected | WC_RNG_LOCK_HELD | want_extra_bits)))
3783
    {
3784
        #ifdef WC_RNG_DEBUG_STATS
3785
        ++rng->_stats_locks_taken;
3786
        #endif
3787
        return 0;
3788
    }
3789
3790
    #ifdef WC_RNG_DEBUG_STATS
3791
    ++rng->_stats_locks_refused; /* racy */
3792
    #endif
3793
3794
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3795
    /* CAS failure with the mutex held means a non-mutex claimant holds
3796
     * the latch (mixed-discipline use); back out the mutex. */
3797
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3798
        (void)wc_UnLockMutex(&rng->mutex);
3799
#endif
3800
3801
    if ((cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED) !=
3802
        (expected & WC_RNG_LOCK_ENTROPY_INVALIDATED))
3803
    {
3804
        return NEEDS_RECOVERY_E;
3805
    }
3806
    else if (expected & WC_RNG_LOCK_HELD)
3807
        return BUSY_E;
3808
    else
3809
        return UNEXPECTED_STATE_E;
3810
}
3811
3812
int wc_RNG_lock_put(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
3813
{
3814
    WC_RNG_lock_arg_t cur_lock, new_lock;
3815
    int cas_ret;
3816
    if (rng == NULL)
3817
        return BAD_FUNC_ARG;
3818
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3819
    if (! (cur_lock & WC_RNG_LOCK_HELD))
3820
        return OBJECT_NOT_LOCKED_E;
3821
3822
    #ifdef WC_RNG_DEBUG_STATS
3823
    ++rng->_stats_locks_released;
3824
    #endif
3825
3826
    WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, cas_ret) {
3827
        new_lock = cur_lock & (((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) &
3828
                               ~WC_RNG_LOCK_HELD);
3829
        /* extra_bits is allowed to assert WC_RNG_LOCK_REQUIRED, which is in the
3830
         * reserved section. */
3831
        extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3832
            WC_RNG_LOCK_REQUIRED;
3833
        new_lock |= extra_bits;
3834
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
3835
                                      &rng->lock, cur_lock, new_lock, cas_ret);
3836
    } WC_CAS_WITH_RETRY_END;
3837
3838
    if (cas_ret != 0) {
3839
        /* Aborted release (a port's retry clause): the latch is still ours
3840
         * and new_lock was never installed.  Keep ownership consistent --
3841
         * mutex included -- and percolate so the caller can retry the
3842
         * put. */
3843
        return cas_ret;
3844
    }
3845
3846
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3847
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3848
        (void)wc_UnLockMutex(&rng->mutex);
3849
#endif
3850
3851
    if (new_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)
3852
        return NEEDS_RECOVERY_E;
3853
    else
3854
        return 0;
3855
}
3856
3857
int wc_RNG_lock_put_conditional(WC_RNG* rng,
3858
                                WC_RNG_lock_arg_t expected_extra_bits,
3859
                                WC_RNG_lock_arg_t want_extra_bits)
3860
{
3861
    int cas_ret;
3862
    WC_CAS_WITH_RETRY_EXTRA_DECLS;
3863
    WC_RNG_lock_arg_t cur_lock, expected, new_lock;
3864
3865
    if (rng == NULL)
3866
        return BAD_FUNC_ARG;
3867
3868
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3869
    if (! (cur_lock & WC_RNG_LOCK_HELD))
3870
        return OBJECT_NOT_LOCKED_E;
3871
3872
    #ifdef WC_RNG_DEBUG_STATS
3873
    ++rng->_stats_locks_released;
3874
    #endif
3875
3876
    /* Note this CAS loop doesn't use WC_CAS_WITH_RETRY_*() (non-conformant code
3877
     * pattern), so the WC_CAS_WITH_RETRY_* hook macros are invoked directly. */
3878
    for (;;) {
3879
        new_lock = cur_lock & (((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) &
3880
                               ~WC_RNG_LOCK_HELD);
3881
        /* want_extra_bits is allowed to assert WC_RNG_LOCK_REQUIRED, which is
3882
         * in the reserved section. */
3883
        want_extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3884
            WC_RNG_LOCK_REQUIRED;
3885
        new_lock |= want_extra_bits;
3886
3887
        expected = WC_RNG_LOCK_HELD | expected_extra_bits |
3888
            (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED);
3889
3890
        new_lock |= (expected_extra_bits & WC_RNG_LOCK_REQUIRED) |
3891
            (cur_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED);
3892
3893
        /* release preserves the sticky bit if the caller reports it held */
3894
        if (wolfSSL_Atomic_Uint_CompareExchange(
3895
                &rng->lock, &expected,
3896
                new_lock))
3897
        {
3898
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
3899
            if (rng->flags & WC_RNG_FLAG_FULL_MUTEX)
3900
                (void)wc_UnLockMutex(&rng->mutex);
3901
#endif
3902
            if (new_lock & WC_RNG_LOCK_ENTROPY_INVALIDATED)
3903
                return NEEDS_RECOVERY_E;
3904
            else
3905
                return 0;
3906
        }
3907
        if ((expected & ((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U)) !=
3908
            (expected_extra_bits & ((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U)))
3909
        {
3910
            break;
3911
        }
3912
3913
        cur_lock = expected;
3914
3915
        cas_ret = WC_CAS_WITH_RETRY_FOREVER_CLAUSE;
3916
        if (cas_ret != 0)
3917
            return cas_ret;
3918
        WC_CAS_WITH_RETRY_ITER_CLAUSE(&rng->lock, cur_lock, new_lock, cas_ret);
3919
    }
3920
3921
    /* conditional release failed: the caller is still the holder, at both
3922
     * layers -- the mutex stays held. */
3923
3924
    #ifdef WC_RNG_DEBUG_STATS
3925
    --rng->_stats_locks_released;
3926
    #endif
3927
3928
    return UNEXPECTED_STATE_E;
3929
}
3930
3931
int wc_RNG_lock_read(WC_RNG* rng, WC_RNG_lock_arg_t* state)
3932
{
3933
    if ((rng == NULL) || (state == NULL))
3934
        return BAD_FUNC_ARG;
3935
    *state = WOLFSSL_ATOMIC_LOAD(rng->lock);
3936
    return 0;
3937
}
3938
3939
int wc_RNG_lock_set_extra(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
3940
{
3941
    WC_RNG_lock_arg_t cur_lock, new_lock;
3942
    int cas_ret;
3943
    if (rng == NULL)
3944
        return BAD_FUNC_ARG;
3945
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3946
3947
    WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, cas_ret) {
3948
        new_lock = cur_lock & ((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U);
3949
        /* extra_bits is allowed to assert WC_RNG_LOCK_REQUIRED, which is in the
3950
         * reserved section. */
3951
        extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3952
            WC_RNG_LOCK_REQUIRED;
3953
        new_lock |= extra_bits;
3954
3955
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
3956
                                      &rng->lock, cur_lock, new_lock, cas_ret);
3957
    } WC_CAS_WITH_RETRY_END;
3958
    /* 0 unless a port's retry clause aborted; the lock word is then
3959
     * untouched, so percolation is the whole handling. */
3960
    return cas_ret;
3961
}
3962
3963
int wc_RNG_lock_add_extra(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
3964
{
3965
    WC_RNG_lock_arg_t cur_lock;
3966
    int cas_ret;
3967
    if (rng == NULL)
3968
        return BAD_FUNC_ARG;
3969
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3970
3971
    /* extra_bits is allowed to assert WC_RNG_LOCK_REQUIRED, which is in the
3972
     * reserved section. */
3973
    extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U) |
3974
        WC_RNG_LOCK_REQUIRED;
3975
3976
    WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, cas_ret) {
3977
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
3978
                                      &rng->lock, cur_lock,
3979
                                      cur_lock | extra_bits, cas_ret);
3980
    } WC_CAS_WITH_RETRY_END;
3981
    /* see wc_RNG_lock_set_extra() re nonzero cas_ret. */
3982
    return cas_ret;
3983
}
3984
3985
int wc_RNG_lock_clear_extra(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
3986
{
3987
    WC_RNG_lock_arg_t cur_lock;
3988
    int cas_ret;
3989
    if (rng == NULL)
3990
        return BAD_FUNC_ARG;
3991
    if (extra_bits & WC_RNG_LOCK_REQUIRED) {
3992
        /* WC_RNG_LOCK_REQUIRED is sticky by contract */
3993
        return BAD_FUNC_ARG;
3994
    }
3995
    cur_lock = WOLFSSL_ATOMIC_LOAD(rng->lock);
3996
3997
    extra_bits &= ~((1U << WC_RNG_LOCK_EXTRA_SHIFT) - 1U);
3998
3999
    WC_CAS_WITH_RETRY_BEGIN(&rng->lock, cur_lock, cas_ret) {
4000
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
4001
                                      &rng->lock, cur_lock,
4002
                                      cur_lock & ~extra_bits, cas_ret);
4003
    } WC_CAS_WITH_RETRY_END;
4004
    /* see wc_RNG_lock_set_extra() re nonzero cas_ret. */
4005
    return cas_ret;
4006
}
4007
4008
#ifdef HAVE_HASHDRBG
4009
WOLFSSL_API int wc_RNG_invalidate_entropy(WC_RNG* rng) {
4010
    WC_RNG_lock_arg_t cur_lock;
4011
    int ret;
4012
4013
    if (rng == NULL)
4014
        return BAD_FUNC_ARG;
4015
4016
    /* If no lock is held, either the RNG is in use without a lock, in which
4017
     * case the reseedCtr is the only way to force invalidation semantics on the
4018
     * user, or it is not in use at all and scheduling a reseed is harmless.
4019
     *
4020
     * If a lock is held, the holder will learn of the invalidation at unlock
4021
     * time, and will implement its own mitigation strategy.  We do not force it
4022
     * into a synchronous reseed.
4023
     *
4024
     * In either case, the state purges here are best effort.  With
4025
     * WC_RNG_HAVE_LOCK, these purges are repeated, strictly serialized against
4026
     * concurrent recovery attempts, in Hash_DRBG_Reseed() (the sole recovery
4027
     * path from _ENTROPY_INVALIDATED).
4028
     */
4029
    ret = wc_RNG_DRBG_ScheduleReseed(rng);
4030
    if (ret == WC_NO_ERR_TRACE(WRONG_TYPE_OBJECT_E)) {
4031
        /* No DRBG (direct-RDRAND et al.): nothing to schedule, and nothing
4032
         * whose staleness the latch would mark -- not a condemnable
4033
         * failure.  Any applicable auxiliary-state purges below still
4034
         * run. */
4035
        ret = 0;
4036
    }
4037
4038
#ifdef WC_RNG_HAVE_POOL
4039
    {
4040
        int ret2 = PoolPurge(rng);
4041
        if ((ret2 != 0) && (ret == 0))
4042
            ret = ret2;
4043
    }
4044
#endif
4045
#ifdef WC_RNG_HAVE_NEXT_SEED
4046
    WOLFSSL_ATOMIC_STORE(rng->nextStirLen,
4047
                         WC_DRBG_NEXT_SEED_EMPTY);
4048
#ifndef NO_SHA256
4049
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
4050
        int ret2 = NextSeedPurge(&((DRBG_internal *)rng->drbg)->nextSeedLen,
4051
            ((DRBG_internal *)rng->drbg)->nextSeed,
4052
            (word32)sizeof(((DRBG_internal *)rng->drbg)->nextSeed));
4053
        if ((ret2 != 0) &&
4054
            (ret2 != WC_NO_ERR_TRACE(ALREADY_E)) &&
4055
            (ret == 0))
4056
        {
4057
            ret = ret2;
4058
        }
4059
    }
4060
#endif
4061
#ifdef WOLFSSL_DRBG_SHA512
4062
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
4063
        int ret2 =
4064
            NextSeedPurge(&((DRBG_SHA512_internal *)rng->drbg512)->nextSeedLen,
4065
            ((DRBG_SHA512_internal *)rng->drbg512)->nextSeed,
4066
            (word32)sizeof(((DRBG_SHA512_internal *)rng->drbg512)->nextSeed));
4067
        if ((ret2 != 0) &&
4068
            (ret2 != WC_NO_ERR_TRACE(ALREADY_E)) &&
4069
            (ret == 0))
4070
        {
4071
            ret = ret2;
4072
        }
4073
    }
4074
#endif
4075
#endif /* WC_RNG_HAVE_NEXT_SEED */
4076
4077
    /* Assert _ENTROPY_INVALIDATED last: latch-after-purge makes the latch a
4078
     * provenance marker.  Any consumer that observes the latch observes
4079
     * post-purge apertures, so a READY it then claims necessarily postdates
4080
     * this event; a consumer that raced ahead of the latch loses its claim
4081
     * to the purge above and is refused at its release CAS (see
4082
     * wc_RNG_DRBG_NextSeedNow_Nonce()); and an event landing mid-reseed
4083
     * strips _ENTROPY_RECOVERING here, so the recovery's exit CAS refuses
4084
     * the clear.  No interleaving recovers from pre-event material. */
4085
4086
    {
4087
        int cas_ret;
4088
        WC_CAS_WITH_RETRY_BEGIN_INIT_CUR(&rng->lock, cur_lock, cas_ret) {
4089
            WC_CAS_WITH_RETRY_LOOP_FOREVER(
4090
                wolfSSL_Atomic_Uint_CompareExchange, &rng->lock, cur_lock,
4091
                (cur_lock & ~WC_RNG_LOCK_ENTROPY_RECOVERING) |
4092
                WC_RNG_LOCK_ENTROPY_INVALIDATED,
4093
                cas_ret);
4094
        } WC_CAS_WITH_RETRY_END;
4095
        if ((cas_ret != 0) && (ret == 0))
4096
            ret = cas_ret;
4097
    }
4098
4099
    /* Postcondition: latch or condemn.  Zero return means _INVALIDATED is
4100
     * asserted; any nonzero return leaves the latch down (it is asserted last,
4101
     * above), so the instance is quarantined by counter saturation alone -- and
4102
     * the reseedCtr is subject to lost-update races.  DRBG_FAILED is the
4103
     * remaining stop no interleaving can lift: sticky until a full recovery.
4104
     *
4105
     * This is the one leaseless outsider write of DRBG_FAILED; the race against
4106
     * a lease-holder is benign both ways (a completing reseed's OK overwrite
4107
     * means the state was genuinely re-derived from post-event material; a
4108
     * FAILED overwrite of OK costs one spurious reinit, never unsound output).
4109
     * In the kernel build, bank instances are retired and recovered by the
4110
     * entropy daemon's out-of-service pass; a leaf's owner sees hard
4111
     * RNG_FAILURE_E and reinitializes.
4112
     */
4113
    if (ret != 0)
4114
        rng->status = DRBG_FAILED;
4115
4116
    return ret;
4117
}
4118
4119
#endif /* HAVE_HASHDRBG */
4120
#endif /* WC_RNG_HAVE_LOCK */
4121
4122
#ifdef WC_RNG_HAVE_FREE_HOOK
4123
/* This routine is used for mitigation of RNG cloning events, particularly by
4124
 * hypervisors. */
4125
WOLFSSL_API int wc_RNG_register_free_hook(WC_RNG* rng,
4126
                                          wc_RNG_free_hook_cb_t free_hook,
4127
                                          void *arg)
4128
{
4129
    if (rng == NULL)
4130
        return BAD_FUNC_ARG;
4131
    rng->free_hook = free_hook;
4132
    rng->free_hook_arg = arg;
4133
    return 0;
4134
}
4135
#endif /* WC_RNG_HAVE_FREE_HOOK */
4136
4137
#ifdef WC_RNG_HAVE_POOL
4138
4139
    /* In-boundary asynchronous DRBG output pool (wc_RNG_Pool_*()): a circular
4140
     * buffer of pre-generated output, held and zeroized under the module's CSP
4141
     * discipline and consumed destructively (each delivered or discarded byte
4142
     * is burned).
4143
     *
4144
     * Writer state coherence is enforced with a CAS; reader exclusivity is
4145
     * enforced by the umbrella WC_RNG.lock, or absent that, by caller contract.
4146
     *
4147
     * The reader is lock-free -- two plain loads of {head, epoch} bracketing
4148
     * the copy, then a plain store of {tail, epoch} exclusively written by the
4149
     * reader.  The writer CASes its publication, carrying the epoch it read; a
4150
     * purge during its generate results in an epoch mismatch, whereupon BUSY_E
4151
     * is returned to the caller.
4152
     *
4153
     * _Alloc() sizes the ring (2..32767 bytes), with positions running in [0,
4154
     * 2*size) and packing into 16 bits.  _Collect() tops up the pool from rng's
4155
     * own DRBG; _Collect2() tops dest's ring up from an independent src
4156
     * instance, generating directly into the free span and publishing with a
4157
     * single CAS -- callable WITHOUT any lease on dest (contending writers
4158
     * return BUSY_E on CAS failure; the final write of every published byte is
4159
     * certified DRBG output).  _Extract() (lease-holder only) delivers up to *n
4160
     * bytes destructively, burning each byte on the way out, and fails closed
4161
     * on an out-of-service DRBG; *n = 0 on empty, for fall-through to a direct
4162
     * generate.  _Current() reports the published count (racy snapshot).  No
4163
     * special free API: the ring lives until wc_FreeRng(), eliminating
4164
     * deallocation races by construction.
4165
     *
4166
     * Two words track FIFO state:
4167
     *
4168
     *   poolHead = {head, epoch}   written by the writer (publish, CAS) and by
4169
     *                               PoolPurge() (epoch bump, CAS)
4170
     *   poolTail = {tail, epoch}   written by the reader alone, plain store
4171
     *
4172
     * Position and epoch share one word, so the pairs are always mutually
4173
     * consistent -- there is no torn snapshot to reason about.
4174
     *
4175
     * head and tail are free-running positions in [0, 2*poolSize), advanced by
4176
     * conditional subtraction -- no division, and no modulus constraint on
4177
     * poolSize.  The writer publishes only into free space, so head can never
4178
     * pass tail + poolSize and the two can never lap.
4179
     *
4180
     * wc_RNG_lock_put{,_conditional}() return NEEDS_RECOVERY_E to the reader if
4181
     * an invalidation occurred after lock but before release (contingent on
4182
     * WC_RNG_HAVE_LOCK).  State coherence for the lock-free writers and purgers
4183
     * hinges on the CAS and epoch counter protocol in PoolPurge() and
4184
     * wc_RNG_Pool_Collect2().
4185
     *
4186
     * The reader never writes poolHead and never CASes anything, leveraging
4187
     * exclusivity enforced by WC_RNG.lock or arranged by caller contract.  It
4188
     * brackets its copy with leading and trailing loads of poolHead and
4189
     * compares the epoch: a purge that landed anywhere in between is caught,
4190
     * providing for early, pre-unlock failure upon invalidation.  The epoch is
4191
     * 16 bits, so defeating this early failure requires exactly k * 65536
4192
     * purges (k a positive integer) inside one copy-and-burn of at most
4193
     * poolSize bytes (implausible).
4194
     *
4195
     * PoolPurge() bumps epoch and touches nothing else.  It does not reset the
4196
     * counters: leaving them monotonic keeps the reader's burn span [tail,
4197
     * tail+m) and the writer's generate span [head, head+m') disjoint across
4198
     * the event, so a purge can never cause one to erase the other's bytes.
4199
     * Stale pre-purge material is discarded by the reader instead, which
4200
     * resynchronizes tail to head on any epoch change -- whether it observed
4201
     * the purge mid-serve or merely arrives afterwards.
4202
     *
4203
     * The writer still CASes, and its publication carries the epoch it read.  A
4204
     * purge during its generate makes that CAS fail, and it abandons rather
4205
     * than publishing material that predates the event.  This protocol is
4206
     * airtight in the same sense as the credited next-seed aperture
4207
     * (NextSeedPurge()): no invalidation can go unobserved by either side.
4208
     *
4209
     * If multiple writers simultaneously write to the pool, their inputs are
4210
     * unpredictably but benignly interspersed, with one of the writers
4211
     * successfully finalizing its write with a CAS, while the rest fail their
4212
     * CAS and return BUSY_E.  Because all writers are tested for provenance
4213
     * compatible with that of the destination RNG (particularly, by the stratum
4214
     * test in wc_RNG_Pool_Collect2()), this interspersal is intrinsically
4215
     * benign.  It can be trivially avoided by single-writer caller contract;
4216
     * the fundamental benefit of this arrangement is the avoidance of an
4217
     * initial frivolous CAS at entry to _Collect2().
4218
     */
4219
4220
#define WC_RNG_POOL_POS(w)   ((word32)((word32)(w) & 0xFFFFU))
4221
#define WC_RNG_POOL_EPOCH(w) ((word32)(((word32)(w) >> 16) & 0xFFFFU))
4222
#define WC_RNG_POOL_PACK(pos, epoch)                                     \
4223
    ((WC_ATOMIC_UINT_ARG)((((word32)(pos)) & 0xFFFFU) |                  \
4224
                          ((((word32)(epoch)) & 0xFFFFU) << 16)))
4225
4226
wc_static_assert(sizeof(WC_ATOMIC_UINT_ARG) >= 4);
4227
4228
/* position -> ring index.  Positions run in [0, 2*poolSize). */
4229
static WC_INLINE word32 PoolAt(word32 pos, word32 poolSize)
4230
{
4231
    return (pos >= poolSize) ? (pos - poolSize) : pos;
4232
}
4233
4234
/* advance a position, wrapping at 2*poolSize. */
4235
static WC_INLINE word32 PoolAdvance(word32 pos, word32 by, word32 poolSize)
4236
{
4237
    word32 lim = poolSize * 2U;
4238
    pos += by;
4239
    return (pos >= lim) ? (pos - lim) : pos;
4240
}
4241
4242
static WC_INLINE word32 PoolUsed(word32 head, word32 tail, word32 poolSize)
4243
{
4244
    /* Note, the modular subtraction is unambiguous because the only publisher
4245
     * (wc_RNG_Pool_Collect2()) carefully bounds itself to the free span, so
4246
     * head never passes tail + poolSize. */
4247
    return (head >= tail) ? (head - tail) : (head + (poolSize * 2U) - tail);
4248
}
4249
4250
/* Wipe the retired span [tail, head): pooled bytes are finished DRBG output
4251
 * at rest, and a retiring event (invalidation, fork, credited reseed) has a
4252
 * sibling lineage that may serve its identical copy -- CSP by the doctrine
4253
 * at NextSeedPurge().  Race-free by ownership: the single reader is the
4254
 * only mover of tail, and writers write only past head. */
4255
static WC_INLINE void PoolWipeRetired(WC_RNG *rng, word32 tail, word32 head)
4256
{
4257
    word32 used = PoolUsed(head, tail, (word32)rng->poolSize);
4258
    word32 t = (tail >= (word32)rng->poolSize) ?
4259
        (tail - (word32)rng->poolSize) : tail;
4260
    word32 seg = (word32)rng->poolSize - t;
4261
    if (seg > used)
4262
        seg = used;
4263
    if (seg > 0)
4264
        ForceZero(rng->pool + t, seg);
4265
    if (used > seg)
4266
        ForceZero(rng->pool, used - seg);
4267
}
4268
4269
/* Retire pooled output: any event after which pre-event bytes must not be
4270
 * served -- state invalidation, fork, a credited reseed recovering from
4271
 * invalidation, the reader's
4272
 * fail-closed path.  Bumping epoch is the whole operation; see above for why
4273
 * the counters are deliberately left alone. */
4274
static WARN_UNUSED_RESULT int PoolPurge(WC_RNG* rng)
4275
{
4276
    WC_ATOMIC_UINT_ARG cur, want;
4277
    int ret;
4278
4279
    WC_CAS_WITH_RETRY_BEGIN_INIT_CUR(&rng->poolHead, cur, ret) {
4280
        want = WC_RNG_POOL_PACK(WC_RNG_POOL_POS(cur),
4281
                                WC_RNG_POOL_EPOCH(cur) + 1U);
4282
        WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Uint_CompareExchange,
4283
                                      &rng->poolHead, cur, want, ret);
4284
    } WC_CAS_WITH_RETRY_END;
4285
4286
    return ret;
4287
}
4288
4289
int wc_RNG_Pool_Alloc(WC_RNG* rng, word32 size)
4290
{
4291
    if ((rng == NULL) || (size < 2) || (size > 32767U))
4292
        return BAD_FUNC_ARG; /* halves are word16; current in [0, size] */
4293
    if (rng->pool != NULL)
4294
        return ALREADY_E;
4295
4296
    rng->pool = (byte*)XMALLOC(size, rng->heap, DYNAMIC_TYPE_RNG);
4297
    if (rng->pool == NULL)
4298
        return MEMORY_E;
4299
    rng->poolSize = (word16)size;
4300
    wolfSSL_Atomic_Uint_Init(&rng->poolHead, 0);
4301
    wolfSSL_Atomic_Uint_Init(&rng->poolTail, 0);
4302
4303
    return 0;
4304
}
4305
4306
int wc_RNG_Pool_Collect2(WC_RNG* rng_dest, WC_RNG* rng_src, word32 n)
4307
{
4308
    if ((rng_dest == NULL) || (rng_src == NULL))
4309
        return BAD_FUNC_ARG;
4310
    if (rng_dest->pool == NULL)
4311
        return BAD_STATE_E;
4312
4313
#ifdef WC_RNG_HAVE_RBGC
4314
    /* Pool data is served directly as DRBG output, via wc_RNG_Pool_Extract().
4315
     * To preserve the destination's provenance guarantee (SP 800-90C
4316
     * sect. 7.3.1 item 16, no output to a predecessor), the generator stratum
4317
     * must not be deeper than the destination stratum.  Contrast with stir data
4318
     * (wc_RNG_DRBG_ReseedRBGC_local() uncredited path), which has and imparts
4319
     * no provenance. */
4320
    if (rng_src->RBGCStratum > rng_dest->RBGCStratum)
4321
        return BAD_FUNC_ARG;
4322
#endif
4323
4324
    if (n == 0)
4325
        return 0;
4326
4327
    /* Note, a second writer can read the same head, generate into the same
4328
     * span, then lose the publication CAS, having already overwritten part of
4329
     * the winner's published bytes.  This is benign -- every byte in the span
4330
     * is output of compatible provenance from one generate or the other, and
4331
     * the loser just returns BUSY_E, while no invalidation is lost either way.
4332
     *
4333
     * If interspersal of bytes from multiple producers is undesirable, the
4334
     * caller can simply arrange not to have multiple concurrent producxers --
4335
     * this is the arrangement in the wolfSSL kernel module, for example, which
4336
     * has a single daemon (wc_linuxkm_entropy_daemon()) that is the sole pool
4337
     * collector.
4338
     */
4339
    {
4340
        WC_ATOMIC_UINT_ARG snap;
4341
        word32 head, epoch, tail, free_sz, m, done = 0;
4342
        int ret;
4343
4344
        WC_ATOMIC_UINT_ARG tw;
4345
4346
        snap = WOLFSSL_ATOMIC_LOAD(rng_dest->poolHead);
4347
        head = WC_RNG_POOL_POS(snap);
4348
        epoch = WC_RNG_POOL_EPOCH(snap);
4349
        tw = WOLFSSL_ATOMIC_LOAD(rng_dest->poolTail);
4350
4351
        if (WC_RNG_POOL_EPOCH(tw) != epoch) {
4352
            /* A purge landed and the reader has not yet acknowledged it.  Its
4353
             * resync discards everything published before the purge -- which
4354
             * would include anything we published now -- so there is no useful
4355
             * work here until a read happens.  Reporting NOT_READY_E rather
4356
             * than success also keeps a collector that polls fullness from
4357
             * spinning: wc_RNG_Pool_Current() reports empty across this
4358
             * window, while tail still describes the retired span, so a
4359
             * free-span computation from it would say full.  Those two
4360
             * disagree only here, and only until the reader resyncs. */
4361
            return NOT_READY_E;
4362
        }
4363
4364
        tail = WC_RNG_POOL_POS(tw);
4365
4366
        free_sz = (word32)rng_dest->poolSize
4367
                  - PoolUsed(head, tail, (word32)rng_dest->poolSize);
4368
        if (free_sz == 0)
4369
            return 0; /* full: success no-op */
4370
        m = (free_sz > n) ? n : free_sz;
4371
4372
        /* generate directly into the unpublished span (up to two contiguous
4373
         * segments), then publish the whole of it with one CAS. */
4374
        while (done < m) {
4375
            word32 at =
4376
                PoolAt(PoolAdvance(head, done, (word32)rng_dest->poolSize),
4377
                       (word32)rng_dest->poolSize);
4378
            word32 chunk = (word32)rng_dest->poolSize - at;
4379
            if (chunk > m - done)
4380
                chunk = m - done;
4381
            ret = wc_RNG_GenerateBlock(rng_src, rng_dest->pool + at, chunk);
4382
            if (ret != 0) {
4383
                /* Abandon in place.  The written bytes lie beyond head and
4384
                 * are therefore unpublished -- benign in-boundary content
4385
                 * awaiting overwrite.  Not burned: the reader's burn span and
4386
                 * ours are disjoint, and zeroing here would be
4387
                 * indistinguishable from published zeros to the next writer. */
4388
                return ret;
4389
            }
4390
            done += chunk;
4391
        }
4392
4393
        if (wolfSSL_Atomic_Uint_CompareExchange(
4394
                &rng_dest->poolHead, &snap,
4395
                WC_RNG_POOL_PACK(
4396
                    PoolAdvance(head, m, (word32)rng_dest->poolSize), epoch)))
4397
        {
4398
            return 0;
4399
        }
4400
        else {
4401
            /* Either we're competing with another writer, or the epoch changed
4402
             * (invalidation).  In either case, we return BUSY_E.
4403
             */
4404
            return BUSY_E;
4405
        }
4406
    }
4407
}
4408
4409
int wc_RNG_Pool_Collect(WC_RNG* rng, word32 n)
4410
{
4411
    return wc_RNG_Pool_Collect2(rng, rng, n);
4412
}
4413
4414
int wc_RNG_Pool_Extract(WC_RNG* rng, byte* out, word32* n)
4415
{
4416
    WC_ATOMIC_UINT_ARG w1, w2, tw;
4417
    word32 head, epoch, tail, avail, m, done = 0;
4418
4419
    if ((rng == NULL) || (out == NULL) || (n == NULL))
4420
        return BAD_FUNC_ARG;
4421
    {
4422
        int lock_ret = rng_lock_required_check(rng);
4423
        if (lock_ret != 0)
4424
            return lock_ret;
4425
    }
4426
    if (rng->pool == NULL)
4427
        return BAD_STATE_E;
4428
4429
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
4430
    {
4431
        int ret = rng_pid_change_check(rng);
4432
        if (ret != 0)
4433
            return ret;
4434
    }
4435
#endif
4436
4437
    /* Fail closed: no serving output on behalf of an out-of-service DRBG, and
4438
     * its pooled output is unusable material at rest.  A writer mid-fill sees
4439
     * the epoch move and abandons rather than publishing. */
4440
    if (wc_RNG_DRBG_Present(rng) && (rng->status != DRBG_OK)) {
4441
        int ret = PoolPurge(rng);
4442
        if (ret != 0)
4443
            return ret;
4444
        /* Reader-owned fail-closed wipe and resync of whatever was
4445
         * pending. */
4446
        tw = WOLFSSL_ATOMIC_LOAD(rng->poolTail);
4447
        w1 = WOLFSSL_ATOMIC_LOAD(rng->poolHead);
4448
        PoolWipeRetired(rng, WC_RNG_POOL_POS(tw), WC_RNG_POOL_POS(w1));
4449
        WOLFSSL_ATOMIC_STORE(rng->poolTail,
4450
                             WC_RNG_POOL_PACK(WC_RNG_POOL_POS(w1),
4451
                                              WC_RNG_POOL_EPOCH(w1)));
4452
        return RNG_FAILURE_E;
4453
    }
4454
4455
    tw = WOLFSSL_ATOMIC_LOAD(rng->poolTail);
4456
    w1 = WOLFSSL_ATOMIC_LOAD(rng->poolHead);
4457
    head = WC_RNG_POOL_POS(w1);
4458
    epoch = WC_RNG_POOL_EPOCH(w1);
4459
4460
    if (WC_RNG_POOL_EPOCH(tw) != epoch) {
4461
        /* A purge landed since our last visit.  Everything published before
4462
         * it is retired: resynchronize to head and report empty.  Anything
4463
         * the writer publishes after this point is post-event and stands. */
4464
        PoolWipeRetired(rng, WC_RNG_POOL_POS(tw), head);
4465
        WOLFSSL_ATOMIC_STORE(rng->poolTail, WC_RNG_POOL_PACK(head, epoch));
4466
#ifdef WC_RNG_DEBUG_STATS
4467
        rng->_stats_pool_bytes_missed += *n;
4468
#endif
4469
        return NOT_READY_E;
4470
    }
4471
4472
    tail = WC_RNG_POOL_POS(tw);
4473
    avail = PoolUsed(head, tail, (word32)rng->poolSize);
4474
    if (avail == 0) {
4475
#ifdef WC_RNG_DEBUG_STATS
4476
        rng->_stats_pool_bytes_missed += *n;
4477
#endif
4478
        return NOT_READY_E;
4479
    }
4480
    m = (avail > *n) ? *n : avail;
4481
4482
    while (done < m) {
4483
        word32 at = PoolAt(PoolAdvance(tail, done, (word32)rng->poolSize),
4484
                           (word32)rng->poolSize);
4485
        word32 chunk = (word32)rng->poolSize - at;
4486
        if (chunk > m - done)
4487
            chunk = m - done;
4488
        XMEMCPY(out + done, rng->pool + at, chunk);
4489
        /* burn on the way out the door, before the span is republished.
4490
         * [tail, tail+m) and the writer's [head, head+m') are disjoint by
4491
         * construction, so this can never erase published bytes. */
4492
        ForceZero(rng->pool + at, chunk);
4493
        done += chunk;
4494
    }
4495
4496
    /* The linearization point.  Both loads read head and epoch as one word,
4497
     * so a purge anywhere in our window is caught here -- epoch moves and
4498
     * never moves back.  Our bytes then predate the event and must not be
4499
     * served, so discard the whole pre-event span rather than advancing. */
4500
    w2 = WOLFSSL_ATOMIC_LOAD(rng->poolHead);
4501
    if (WC_RNG_POOL_EPOCH(w2) != epoch) {
4502
        /* We own [tail, old head) exclusively; the purged span is wiped
4503
         * before it is skipped. */
4504
        PoolWipeRetired(rng, tail, head);
4505
        WOLFSSL_ATOMIC_STORE(rng->poolTail,
4506
                             WC_RNG_POOL_PACK(WC_RNG_POOL_POS(w2),
4507
                                              WC_RNG_POOL_EPOCH(w2)));
4508
#ifdef WC_RNG_DEBUG_STATS
4509
        rng->_stats_pool_bytes_missed += *n;
4510
#endif
4511
        return BUSY_E;
4512
    }
4513
4514
    /* Sole writer of poolTail: a plain store, no CAS on the reader path. */
4515
    WOLFSSL_ATOMIC_STORE(rng->poolTail,
4516
                         WC_RNG_POOL_PACK(
4517
                             PoolAdvance(tail, m, (word32)rng->poolSize),
4518
                             epoch));
4519
4520
#ifdef WC_RNG_DEBUG_STATS
4521
    rng->_stats_pool_bytes_produced += m;
4522
    rng->_stats_pool_bytes_missed += *n - m; /* shortfall on partial serve */
4523
#endif
4524
    *n = m;
4525
4526
    return 0;
4527
}
4528
4529
int wc_RNG_Pool_Current(WC_RNG* rng, word32* n)
4530
{
4531
    if ((rng == NULL) || (n == NULL))
4532
        return BAD_FUNC_ARG;
4533
    if (rng->pool != NULL) {
4534
        WC_ATOMIC_UINT_ARG w = WOLFSSL_ATOMIC_LOAD(rng->poolHead);
4535
        WC_ATOMIC_UINT_ARG tw = WOLFSSL_ATOMIC_LOAD(rng->poolTail);
4536
        /* a purge not yet observed by the reader retires everything
4537
         * published before it: report empty. */
4538
        *n = (WC_RNG_POOL_EPOCH(tw) != WC_RNG_POOL_EPOCH(w)) ? 0 :
4539
             PoolUsed(WC_RNG_POOL_POS(w), WC_RNG_POOL_POS(tw),
4540
                      (word32)rng->poolSize);
4541
    }
4542
    else {
4543
        *n = 0;
4544
    }
4545
    return 0;
4546
}
4547
#endif /* WC_RNG_HAVE_POOL */
4548
4549
#ifdef WC_RNG_HAVE_RBGC
4550
4551
/* Unified mechanics for the four wc_InitRng*RBGC() APIs: instantiate a child
4552
 * DRBG subordinate to parent in an SP 800-90C RBG chain, drawing its seed
4553
 * material from parent's generate function in place of the module's seed
4554
 * source; every other aspect of instantiation -- seed byte accounting, nonce
4555
 * handling, failure disposition -- is _InitRng()'s, identically to
4556
 * wc_InitRngNonce_ex() with the omission of health testing, which is
4557
 * superfluous when a healthy DRBG generates the seed data.
4558
 *
4559
 * SP 800-90C accounting: the child's claimable security strength is capped by
4560
 * the parent's, and the child has no formal prediction resistance.  The child's
4561
 * own reseeds default to the module's seed source (the reseed-interval
4562
 * backstop, wc_RNG_DRBG_Reseed_Now()); wc_RNG_DRBG_ReseedRBGC() reseeds it from
4563
 * a supplied root instead.  In configurations with no DRBG (RDRAND et al.), the
4564
 * child comes up as _InitRng() dictates for such configurations and the parent
4565
 * is not consulted.
4566
 *
4567
 * Exactly one of new_child_stack (caller-provided WC_RNG, uninitialized) and
4568
 * new_child_heap (callee-allocated from parent's heap, to be released with
4569
 * wc_rng_free()) must be non-NULL.  The caller must hold exclusive access
4570
 * to parent for the duration of the call, as for all WC_RNG operations; the
4571
 * spawn debits parent's reseed counter by one generate.
4572
 */
4573
static WARN_UNUSED_RESULT int SpawnRngRBGC(
4574
                        WC_RNG* new_child_stack, WC_RNG** new_child_heap,
4575
                        WC_RNG* parent, const byte* nonce, word32 nonceSz,
4576
                        const byte *perso, word32 persoSz,
4577
                        word32 flags)
4578
{
4579
    WC_RNG* child = new_child_stack;
4580
    int ret;
4581
4582
    if (parent == NULL)
4583
        return BAD_FUNC_ARG;
4584
4585
    if ((new_child_stack == NULL) == (new_child_heap == NULL))
4586
        return BAD_FUNC_ARG;
4587
4588
    if (new_child_stack == parent)
4589
        return BAD_FUNC_ARG;
4590
4591
    if ((nonce == NULL) && (nonceSz > 0))
4592
        return BAD_FUNC_ARG;
4593
4594
    if (new_child_heap != NULL) {
4595
        *new_child_heap = (WC_RNG*)XMALLOC(sizeof(WC_RNG), parent->heap,
4596
        DYNAMIC_TYPE_RNG);
4597
        if (*new_child_heap == NULL)
4598
            return MEMORY_E;
4599
        child = *new_child_heap;
4600
    }
4601
4602
    ret = _InitRng(child, nonce, nonceSz, perso, persoSz, parent->heap,
4603
    #if defined(WOLF_CRYPTO_CB)
4604
                   parent->devId,
4605
    #else
4606
                   INVALID_DEVID,
4607
    #endif
4608
                   parent, flags);
4609
4610
    if (new_child_heap != NULL) {
4611
        if (ret != 0) {
4612
            XFREE(child, parent->heap, DYNAMIC_TYPE_RNG);
4613
            *new_child_heap = child = NULL;
4614
        }
4615
    }
4616
4617
    return ret;
4618
}
4619
4620
int wc_InitRngRBGC(WC_RNG* child, WC_RNG* parent, word32 flags)
4621
{
4622
    return SpawnRngRBGC(child, NULL, parent, NULL, 0, NULL, 0, flags);
4623
}
4624
4625
int wc_InitRngNonceRBGC(WC_RNG* child, WC_RNG* parent, const byte* nonce,
4626
                        word32 nonceSz, const byte *perso, word32 persoSz,
4627
                        word32 flags)
4628
{
4629
    return SpawnRngRBGC(child, NULL, parent, nonce, nonceSz, perso, persoSz,
4630
                        flags);
4631
}
4632
4633
#ifndef WC_NO_CONSTRUCTORS
4634
int wc_InitRngRBGC_New(WC_RNG** child, WC_RNG* parent, word32 flags)
4635
{
4636
    return SpawnRngRBGC(NULL, child, parent, NULL, 0, NULL, 0, flags);
4637
}
4638
4639
int wc_InitRngNonceRBGC_New(WC_RNG** child, WC_RNG* parent, const byte* nonce,
4640
                            word32 nonceSz, const byte *perso, word32 persoSz,
4641
                            word32 flags)
4642
{
4643
    return SpawnRngRBGC(NULL, child, parent, nonce, nonceSz, perso, persoSz,
4644
                        flags);
4645
}
4646
#endif /* !WC_NO_CONSTRUCTORS */
4647
4648
/* Immediately reseed rng from root's generate output -- the reseed counterpart
4649
 * of the wc_InitRng*RBGC() spawn.  The reseed counter is reset iff the reseed
4650
 * succeeds and credited.  The nonce, if any, rides the same reseed derivation
4651
 * as (uncredited) additional input.  The caller must hold exclusive access to
4652
 * BOTH rng and root.  On credited success, rng is (or remains) a chain RNG:
4653
 * its current seed period is chain-backed, so RBGCStratum is set, and it is not
4654
 * usable as a reseed root.
4655
 *
4656
 * By default, consistent with SP 800-90C 7.1.2.2, reseed by an RBGC root is
4657
 * allowed, provided its stratum is less than the child's stratum (no stratum
4658
 * downgrade allowed, no cycles possible); build-time option
4659
 * WC_RNG_NO_RBGC_RESEED restricts credited reseeds to primary-seeded roots.
4660
 *
4661
 * Uncredited reseeds by wc_RNG_DRBG_ReseedRBGC_local() are unconditionally
4662
 * permitted (these are just stirs).
4663
 */
4664
static WARN_UNUSED_RESULT int wc_RNG_DRBG_ReseedRBGC_local(
4665
                                        WC_RNG* rng, WC_RNG* root,
4666
                                        const byte* nonce, word32 nonceSz,
4667
                                        int credited)
4668
{
4669
#ifdef WOLFSSL_SMALL_STACK_CACHE
4670
    byte *seed;
4671
#else
4672
    byte seed[SEED_SZ];
4673
#endif
4674
    int ret;
4675
4676
    if ((rng == NULL) || (root == NULL) || (rng == root) ||
4677
        ((nonce == NULL) && (nonceSz > 0)))
4678
    {
4679
        return BAD_FUNC_ARG;
4680
    }
4681
4682
    ret = rng_lock_required_check(rng);
4683
    if (ret != 0)
4684
        return ret;
4685
4686
    ret = rng_lock_required_check(root);
4687
    if (ret != 0)
4688
        return ret;
4689
4690
    if (credited) {
4691
        if (root->RBGCStratum >= WC_MAX_SINT_OF(int))
4692
            return SEQ_OVERFLOW_E;
4693
        else if (root->RBGCStratum == WC_RNG_RBGC_USER_SEED_STRATUM - 1)
4694
            return SEQ_OVERFLOW_E;
4695
    }
4696
    /* else the RBGC strata are irrelevant -- stir data has no implication of
4697
     * provenance, and can legitimately be wall clock time or even strings of
4698
     * zeros. */
4699
4700
#ifdef WOLFSSL_SMALL_STACK_CACHE
4701
    seed = rng->newSeed_buf;
4702
#endif
4703
4704
    if (credited && (root->RBGCStratum > 0)
4705
#ifndef WC_RNG_NO_RBGC_RESEED
4706
        && (root->RBGCStratum >= rng->RBGCStratum)
4707
#else
4708
    /* Credited reseed from root only, by policy. */
4709
#endif
4710
        )
4711
    {
4712
        return BAD_FUNC_ARG;
4713
    }
4714
4715
    if (rng->status != DRBG_OK)
4716
        return RNG_FAILURE_E;
4717
4718
    if (! wc_RNG_DRBG_Present(rng)) {
4719
        return 0;
4720
    }
4721
4722
    ret = wc_RNG_GenerateBlock(root, seed, SEED_SZ);
4723
    if (ret == 0) {
4724
        if (credited) {
4725
            ret = Hash_DRBG_Reseed(rng, seed, SEED_SZ, nonce, nonceSz,
4726
                                   0 /* in_bracketed_consume */);
4727
            if (ret == 0) {
4728
                rng->RBGCStratum = root->RBGCStratum + 1;
4729
    #ifdef WC_RNG_DEBUG_STATS
4730
                ++rng->_stats_RBGC_reseeds;
4731
    #endif
4732
            }
4733
        }
4734
        else {
4735
            ret = wc_RNG_DRBG_Stir_Nonce_local(rng, seed, SEED_SZ, nonce,
4736
                                                      nonceSz);
4737
        }
4738
    }
4739
    ForceZero(seed, SEED_SZ);
4740
4741
    return ret;
4742
}
4743
4744
int wc_RNG_DRBG_ReseedRBGC(WC_RNG* rng, WC_RNG* root, const byte* nonce,
4745
                           word32 nonceSz)
4746
{
4747
    return wc_RNG_DRBG_ReseedRBGC_local(rng, root, nonce, nonceSz, 1);
4748
}
4749
4750
int wc_RNG_DRBG_StirRBGC(WC_RNG* rng, WC_RNG* root,
4751
                                      const byte* nonce, word32 nonceSz)
4752
{
4753
    return wc_RNG_DRBG_ReseedRBGC_local(rng, root, nonce, nonceSz, 0);
4754
}
4755
4756
#endif /* WC_RNG_HAVE_RBGC */
4757
4758
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
4759
4760
static WARN_UNUSED_RESULT int PollAndReSeed(WC_RNG* rng, const byte* additional,
4761
                         word32 additionalSz)
4762
0
{
4763
0
    int ret   = WC_NO_ERR_TRACE(DRBG_NEED_RESEED);
4764
0
    int devId = INVALID_DEVID;
4765
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
4766
    devId = rng->devId;
4767
#endif
4768
0
    ret = wc_RNG_HealthTestLocal(rng, 1, rng->heap, devId);
4769
0
    if (ret == 0) {
4770
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
4771
        byte* newSeed = rng->newSeed_buf;
4772
        ret = DRBG_SUCCESS;
4773
    #elif defined(WOLFSSL_SMALL_STACK)
4774
        byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
4775
            DYNAMIC_TYPE_SEED);
4776
        ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS;
4777
    #else
4778
0
        byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
4779
0
        ret = DRBG_SUCCESS;
4780
0
    #endif
4781
0
        if (ret == DRBG_SUCCESS) {
4782
        #ifdef WC_RNG_SEED_CB
4783
            if (seedCb == NULL) {
4784
                ret = DRBG_NO_SEED_CB;
4785
            }
4786
            else {
4787
                ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
4788
                if (ret != 0) {
4789
    #ifdef WC_VERBOSE_RNG
4790
                    WOLFSSL_DEBUG_PRINTF("ERROR: seedCb() in PollAndReSeed() "
4791
                                         "failed with err %d", ret);
4792
    #endif
4793
                    if (ret > 0) /* app callback: keep negative codes */
4794
                        ret = DRBG_FAILURE;
4795
                }
4796
            }
4797
        #else
4798
0
            ret = wc_GenerateSeed(&rng->seed, newSeed,
4799
0
                              SEED_SZ + SEED_BLOCK_SZ);
4800
0
            if (ret != 0) {
4801
    #ifdef WC_RNG_DEBUG_STATS
4802
                ++rng->_stats_seed_failures;
4803
    #endif
4804
    #ifdef WC_VERBOSE_RNG
4805
                WOLFSSL_DEBUG_PRINTF(
4806
                    "ERROR: wc_GenerateSeed() in PollAndReSeed() failed with "
4807
                    "err %d", ret);
4808
    #endif
4809
0
            }
4810
0
        #endif
4811
0
        }
4812
0
        if (ret == DRBG_SUCCESS) {
4813
0
            ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
4814
    #ifdef WC_RNG_DEBUG_STATS
4815
            if (ret != DRBG_SUCCESS)
4816
                ++rng->_stats_seed_failures;
4817
    #endif
4818
    #ifdef WC_VERBOSE_RNG
4819
            if (ret != DRBG_SUCCESS)
4820
                WOLFSSL_DEBUG_PRINTF(
4821
                    "ERROR: wc_RNG_TestSeed() in PollAndReSeed() returned "
4822
                    "err %d.", ret);
4823
    #endif
4824
0
        }
4825
0
        if (ret == DRBG_SUCCESS) {
4826
0
            ret = Hash_DRBG_Reseed(rng, newSeed + SEED_BLOCK_SZ, SEED_SZ,
4827
0
                                   additional, additionalSz,
4828
0
                                   0 /* in_bracketed_consume */);
4829
4830
        #ifdef WC_RNG_HAVE_RBGC
4831
            if (ret == 0)
4832
                rng->RBGCStratum = 0;
4833
        #endif
4834
0
        }
4835
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
4836
        if (newSeed != NULL) {
4837
            ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ);
4838
        }
4839
        XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED);
4840
    #else
4841
        /* newSeed is a byte[] in the plain build but a byte* in the
4842
         * SMALL_STACK_CACHE build, so use the explicit buffer length (not
4843
         * sizeof) to zero the whole reseed entropy buffer in both cases. */
4844
    #ifdef WOLFSSL_CHECK_MEM_ZERO
4845
        wc_MemZero_Add("PollAndReSeed newSeed", newSeed,
4846
            SEED_SZ + SEED_BLOCK_SZ);
4847
    #endif
4848
0
        ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ);
4849
    #ifdef WOLFSSL_CHECK_MEM_ZERO
4850
        wc_MemZero_Check(newSeed, SEED_SZ + SEED_BLOCK_SZ);
4851
    #endif
4852
0
    #endif
4853
0
    }
4854
    /* else pass back the failure code from wc_RNG_HealthTestLocal():
4855
     * DRBG_CONT_FAILURE from the KAT means ConstantCompare mismatch, i.e.  a
4856
     * machinery failure; infrastructure codes (MEMORY_E, or DRBG_FAILURE as the
4857
     * internal ops' catch-all) are distinct and retryable.
4858
     */
4859
4860
0
    return ret;
4861
0
}
4862
4863
/* Immediately reseed rng from the module's built-in or previously registered
4864
 * seed source, exactly as the WC_RESEED_INTERVAL backstop does during a
4865
 * generate operation: the gathered seed is health-tested and applied by the
4866
 * module's own reseed function, and the reseed counter is reset iff the
4867
 * reseed succeeds.  If nonceSz > 0, nonce is incorporated into the same
4868
 * reseed derivation as (uncredited) additional input, with the semantics of
4869
 * wc_RNG_DRBG_Stir(), in a single state transition.  On failure
4870
 * the reseed counter is not reset and rng->status reflects the failure
4871
 * exactly as a generate-time reseed failure would.  The caller must hold
4872
 * exclusive access to rng, as for all WC_RNG operations. */
4873
int wc_RNG_DRBG_Reseed_Now(WC_RNG* rng, const byte* nonce, word32 nonceSz)
4874
0
{
4875
0
    int ret;
4876
4877
0
    if (rng == NULL)
4878
0
        return BAD_FUNC_ARG;
4879
0
    if ((nonce == NULL) && (nonceSz > 0))
4880
0
        return BAD_FUNC_ARG;
4881
0
    ret = rng_lock_required_check(rng);
4882
0
    if (ret != 0)
4883
0
        return ret;
4884
4885
    /* Not reached from the generate path, so it takes the lock here.  The
4886
     * checks below read state a generate writes under it, so they follow. */
4887
0
    ret = RngAutoLockEnter(rng);
4888
0
    if (ret != 0)
4889
0
        return ret;
4890
4891
    /* Mirror wc_RNG_GenerateBlock(): only an in-service DRBG may reseed. */
4892
0
    if (rng->status != DRBG_OK) {
4893
0
        ret = RNG_FAILURE_E;
4894
0
        goto out;
4895
0
    }
4896
4897
0
    if (! wc_RNG_DRBG_Present(rng)) {
4898
        /* No DRBG instantiated -- nothing to reseed (RDRAND et al.). */
4899
0
        ret = 0;
4900
0
        goto out;
4901
0
    }
4902
4903
0
    ret = PollAndReSeed(rng, nonce, nonceSz);
4904
4905
0
    if (ret == DRBG_SUCCESS) {
4906
0
        ret = 0;
4907
0
    }
4908
0
    else if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
4909
0
        rng->status = DRBG_CONT_FAILED;
4910
0
        ret = DRBG_CONT_FIPS_E;
4911
0
    }
4912
0
    else {
4913
0
        wc_drbg_reseed_ctr_t ctr = WC_RESEED_INTERVAL;
4914
0
        (void)wc_RNG_DRBG_GetReseedCtr(rng, &ctr);
4915
0
        if (ctr >= WC_RESEED_INTERVAL) {
4916
            /* The instance is out of generate runway -- condemn now, matching
4917
             * wc_RNG_GenerateBlock()'s behavior for mandatory reseeds. */
4918
0
            rng->status = DRBG_FAILED;
4919
0
        }
4920
0
        if (ret > 0) {
4921
            /* Translate protocol-domain codes at the API boundary. */
4922
0
            ret = (ctr >= WC_RESEED_INTERVAL) ? RNG_FAILURE_E : NOT_READY_E;
4923
0
        }
4924
        /* else distinct wolfCrypt codes (ENTROPY_RT_E/APT_E, MEMORY_E, etc.)
4925
         * pass through verbatim -- source health is never masked. */
4926
0
    }
4927
4928
0
    out:
4929
4930
0
    RngAutoLockExit(rng);
4931
0
    return ret;
4932
0
}
4933
4934
#ifdef WC_RNG_HAVE_NEXT_SEED
4935
4936
    /* Banked-next-seed services.  _NextSeedGenerate() banks up to n more
4937
     * bytes from the module's seed source (clamped to the space remaining;
4938
     * ALREADY_E when the bank is ready or being consumed), health-testing
4939
     * and publishing the bank when it completes (NOT_READY_E when the health
4940
     * test could not run and the call should simply be retried); a
4941
     * scheduling daemon may call it without owning the instance.
4942
     * _NextSeedCurrent() reports the raw aperture value (racy snapshot).
4943
     * _NextSeedNow() claims a ready bank and performs a source-free
4944
     * credited reseed with it -- safe in atomic context -- or returns
4945
     * NOT_READY_E when no bank is ready; _NextSeedNow_Nonce() is the same
4946
     * with a nonce as uncredited additional input.  All report
4947
     * MISSING_RNG_E for an instance with no DRBG (RDRAND et al.).  The
4948
     * caller must own the instance for _NextSeedNow[_Nonce](). */
4949
4950
/* Banked-next-seed protocol.
4951
 *
4952
 * Entropy is gathered incrementally, in-boundary, from the
4953
 * module's seed source by wc_RNG_DRBG_NextSeedGenerate(), and consumed
4954
 * (source-free, atomic-context-safe) by wc_RNG_DRBG_NextSeedNow().
4955
 * nextSeedLen is the hand-off aperture: values in [0, bank length)
4956
 * count banked bytes (filling); WC_DRBG_NEXT_SEED_READY marks a complete,
4957
 * health-tested bank; WC_DRBG_NEXT_SEED_CONSUMING marks exclusive ownership by a
4958
 * consumer.
4959
 *
4960
 * DRBG_internal.nextSeedLen (and the DRBG_SHA512_internal analog) is a
4961
 * wolfSSL_Atomic_Int with C-native atomic semantics (release stores, acquire
4962
 * loads, sequentially consistent RMWs):
4963
 *
4964
 * The single scheduling daemon (one writer per instance, by contract) advances
4965
 * the fill with the AddFetch in wc_RNG_DRBG_NextSeedGenerate() and publishes by
4966
 * storing _READY; a consumer claims with a CAS from _READY to _CONSUMING,
4967
 * consumes, zeroizes, and releases to _EMPTY.  Ownership-taking transitions are
4968
 * atomic RMWs and releases are atomic stores with release semantics, so the
4969
 * hand-off is ordered on all supported targets, and the daemon never touches
4970
 * any other DRBG state.  Gathering draws from the configured / installed
4971
 * entropy source directly, never from rng->seed, so the daemon also does not
4972
 * race an owner's own source reseed. */
4973
4974
/* Locate the aperture members for rng's live DRBG.  Returns nonzero when no
4975
 * DRBG is instantiated (RDRAND et al.). */
4976
static WARN_UNUSED_RESULT WC_INLINE int NextSeedPtrs(WC_RNG* rng,
4977
                                  byte** seed, word32 *nextSeedSz,
4978
                                  wolfSSL_Atomic_Int** len,
4979
                                  int **nextSeedRBGCStratum)
4980
{
4981
#ifndef NO_SHA256
4982
    if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
4983
        *seed = ((DRBG_internal*)rng->drbg)->nextSeed;
4984
        *nextSeedSz = (word32)sizeof(((DRBG_internal*)rng->drbg)->nextSeed);
4985
        *len  = &((DRBG_internal*)rng->drbg)->nextSeedLen;
4986
        if (nextSeedRBGCStratum) {
4987
        #ifdef WC_RNG_HAVE_RBGC
4988
            *nextSeedRBGCStratum =
4989
                &((DRBG_internal*)rng->drbg)->nextSeedRBGCStratum;
4990
        #else
4991
            *nextSeedRBGCStratum = NULL;
4992
        #endif
4993
        }
4994
        return 0;
4995
    }
4996
#endif
4997
#ifdef WOLFSSL_DRBG_SHA512
4998
    if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
4999
        *seed = ((DRBG_SHA512_internal*)rng->drbg512)->nextSeed;
5000
        *nextSeedSz =
5001
            (word32)sizeof(((DRBG_SHA512_internal*)rng->drbg512)->nextSeed);
5002
        *len  = &((DRBG_SHA512_internal*)rng->drbg512)->nextSeedLen;
5003
        if (nextSeedRBGCStratum) {
5004
        #ifdef WC_RNG_HAVE_RBGC
5005
            *nextSeedRBGCStratum =
5006
                &((DRBG_SHA512_internal*)rng->drbg512)->nextSeedRBGCStratum;
5007
        #else
5008
            *nextSeedRBGCStratum = NULL;
5009
        #endif
5010
        }
5011
        return 0;
5012
    }
5013
#endif
5014
    return MISSING_RNG_E;
5015
}
5016
5017
/* Bank up to n more bytes of seed material from a supplied root RNG into
5018
 * rng's next-seed bank.  Callable without owning the instance (the scheduling
5019
 * daemon's entry point); deliberately independent of rng->status so that
5020
 * banking can proceed for any instantiated DRBG.  n is clamped to the space
5021
 * remaining; a ready or consuming bank is signaled with ALREADY_E.  On
5022
 * completing the bank, the material is health-tested (wc_RNG_TestSeed()) and
5023
 * published; a failed test consumes the material (use-once) and returns the
5024
 * test's error, leaving an empty bank for the next cycle.  A gather failure
5025
 * leaves the partial bank intact for retry. */
5026
static WARN_UNUSED_RESULT int wc_RNG_DRBG_NextSeedGenerate_local(
5027
                                              WC_RNG* rng, WC_RNG* root,
5028
                                              word32 n)
5029
{
5030
    int claim_ret;
5031
    byte* seed = NULL;
5032
    wolfSSL_Atomic_Int* lenp = NULL;
5033
    int* nextSeedRBGCStratum_p = NULL;
5034
    WC_ATOMIC_INT_ARG cur;
5035
    word32 nextSeedSz = 0;
5036
    int ret;
5037
5038
    if ((rng == NULL) || (n == 0) || (rng == root))
5039
        return BAD_FUNC_ARG;
5040
5041
    /* Note, rng need not be locked -- that's the whole point of the
5042
     * banked-next-seed aperture protocol.  However, the two aperture lanes
5043
     * (WC_RNG.nextStir and DRBG_internal.nextSeed) earn that differently.  The
5044
     * stir lane is WC_RNG-resident: uncredited material carries no
5045
     * adjudication, so it survives DRBG teardown/reinit harmlessly, and
5046
     * depositors (wc_RNG_DRBG_NextStirStore()) are blind by design -- they
5047
     * never dereference rng->drbg.  This (credited) lane is DRBG-resident: a
5048
     * banked seed carries health-test and stratum adjudication that must die
5049
     * with the generation it was banked for, so it must not outlive rng->drbg
5050
     * -- and therefore fills here race wc_FreeRng().  In-bank,
5051
     * bank->inst_op_gate mutually excludes production
5052
     * (wc_rng_bank_next_seed_generate_local()) from instance free/reinit
5053
     * (wc_rng_bank_inst_reinit()); outside banks, the instance is caller-owned
5054
     * and the caller is the only party doing either. */
5055
5056
    if (root) {
5057
        ret = rng_lock_required_check(root);
5058
        if (ret != 0)
5059
            return ret;
5060
#ifdef WC_RNG_HAVE_RBGC
5061
        if ((root->RBGCStratum > 0)
5062
    #ifndef WC_RNG_NO_RBGC_RESEED
5063
            && (root->RBGCStratum >= rng->RBGCStratum)
5064
    #else
5065
            /* Credited reseed from root only, by policy. */
5066
    #endif
5067
            )
5068
        {
5069
            return BAD_FUNC_ARG;
5070
        }
5071
        if (root->RBGCStratum >= WC_MAX_SINT_OF(int))
5072
            return SEQ_OVERFLOW_E;
5073
        else if (root->RBGCStratum == WC_RNG_RBGC_USER_SEED_STRATUM - 1)
5074
            return SEQ_OVERFLOW_E;
5075
#else
5076
        return NOT_COMPILED_IN;
5077
#endif
5078
    }
5079
5080
    ret = NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp,
5081
                       &nextSeedRBGCStratum_p);
5082
    if (ret != 0) {
5083
        /* No DRBG instantiated -- nothing to bank (RDRAND et al.). */
5084
        return ret;
5085
    }
5086
5087
    cur = WOLFSSL_ATOMIC_LOAD(*lenp);
5088
    {
5089
        /* Producer claim: exactly one banker may fill or publish at a
5090
         * time.  Concurrent fills would be tolerable as BYTES (a torn
5091
         * mix is still entropy) but poisonous as CLAIMS: interleaved
5092
         * primary/RBGC production could publish material under the
5093
         * wrong stratum or health-test disposition.  The claim makes
5094
         * produce-side exclusivity a CAS, matching the consume side's
5095
         * READY -> CONSUMING claim.  This lane only: the uncredited
5096
         * accumulator above stays multi-writer by design. */
5097
        WC_CAS_WITH_RETRY_BEGIN(lenp, cur, claim_ret) {
5098
            if ((cur == WC_DRBG_NEXT_SEED_PRODUCING) ||
5099
                (cur == WC_DRBG_NEXT_SEED_PURGED))
5100
            {
5101
                /* A producer is in flight (or unwinding a purge):
5102
                 * retryable on a later banking cycle.  Traced: the
5103
                 * competing producer -- typically the entropy daemon
5104
                 * -- is the diagnosis a surprised caller needs. */
5105
                return BUSY_E;
5106
            }
5107
            if (cur < 0) {
5108
                /* Ready or consuming -- nothing to do. */
5109
                return WC_NO_ERR_TRACE(ALREADY_E); /* not an error */
5110
            }
5111
            WC_CAS_WITH_RETRY_LOOP_FOREVER(wolfSSL_Atomic_Int_CompareExchange,
5112
                                          lenp, cur,
5113
                                          WC_DRBG_NEXT_SEED_PRODUCING,
5114
                                          claim_ret);
5115
        } WC_CAS_WITH_RETRY_END;
5116
        if (claim_ret != 0) {
5117
            /* Aborted claim (a port's retry clause): nothing claimed,
5118
             * nothing moved.  Proceeding would fill and adjudicate an
5119
             * unclaimed aperture -- the torn-claims disease the
5120
             * producer mutex exists to prevent. */
5121
            return claim_ret;
5122
        }
5123
        if (cur == (WC_ATOMIC_INT_ARG)nextSeedSz) {
5124
            /* Complete but unpublished (interrupted between fill
5125
             * completion and publication): retry the health test and
5126
             * publication below. */
5127
            n = 0;
5128
        }
5129
        /* From here to release/publication the aperture word is
5130
         * PRODUCING; fill progress lives only in the local cur, and
5131
         * every exit passes through NextSeedProducerRelease(). */
5132
    }
5133
5134
    if (n > 0) {
5135
#ifdef WC_RNG_HAVE_RBGC
5136
        if (root) {
5137
            /* If primary seed bytes were carried forward, reset now to avoid
5138
             * wc_RNG_TestSeed() at completion.  Local only: the word is
5139
             * held at PRODUCING. */
5140
            if ((cur > 0) && (*nextSeedRBGCStratum_p == 0))
5141
                cur = 0;
5142
5143
            if (n > nextSeedSz - (word32)cur)
5144
                n = nextSeedSz - (word32)cur;
5145
5146
            ret = wc_RNG_GenerateBlock(root, seed + cur, n);
5147
            if (ret != 0) {
5148
                /* Partial bank preserved -- retry on a later cycle.
5149
                 * (If a purge landed meanwhile, the release discards
5150
                 * instead; the draw failure is the more informative
5151
                 * code and wins over the release's BUSY_E.)
5152
                 *
5153
                 * Note, a failed release cannot brick the RNG and needs no
5154
                 * disposition at the several (void) sites below: its one cause
5155
                 * is a purge's _PURGED repaint (producers cannot claim a
5156
                 * PRODUCING word, consumers exchange only from READY, and the
5157
                 * purge is the sole other writer), and the BUSY arm is its own
5158
                 * compensation -- it wipes and reopens the aperture EMPTY
5159
                 * before returning.  Afterward the world is fully consistent:
5160
                 * aperture empty and healthy, rng->status untouched, recovery
5161
                 * proceeding through the event's normal channels.  BUSY_E is
5162
                 * information, not a condition awaiting action; the caller's
5163
                 * own error outranks it wherever one is in flight.  Cost of
5164
                 * swallowing it: at worst one silent refill from offset
5165
                 * zero.
5166
                 */
5167
                (void)NextSeedProducerRelease(lenp, seed, nextSeedSz, cur);
5168
                return ret;
5169
            }
5170
5171
            /* If RBGC seed bytes were carried forward, make sure we're
5172
             * pessimistic about the RBGC stratum. */
5173
            if ((cur == 0) || (*nextSeedRBGCStratum_p < root->RBGCStratum + 1))
5174
                *nextSeedRBGCStratum_p = root->RBGCStratum + 1;
5175
        }
5176
        else
5177
#endif /* WC_RNG_HAVE_RBGC */
5178
        {
5179
            /* wc_GenerateSeed() must be called completely independent of rng,
5180
             * aside from the memory aperture itself.  For safety, we pass a
5181
             * dummy OS_Seed, which will be ignored by the wc_GenerateSeed()
5182
             * typically used in conjunction with WC_RNG_HAVE_NEXT_SEED.
5183
             */
5184
            struct OS_Seed os;
5185
5186
            /* Named-member init: layout-proof against OS_Seed growing or
5187
             * reordering members under its several config axes. */
5188
            XMEMSET(&os, 0, sizeof(os));
5189
#ifndef USE_WINDOWS_API
5190
            os.fd = -1;
5191
#endif
5192
#ifdef WOLF_CRYPTO_CB
5193
            /* devId is config, not state: a callback-only seed source must
5194
             * serve the bank the same way it serves wc_InitRng(). */
5195
            os.devId = rng->seed.devId;
5196
#endif
5197
5198
#ifdef WC_RNG_HAVE_RBGC
5199
            /* If RBGC seed bytes were carried forward, reset now to avoid
5200
             * intermixture and force wc_RNG_TestSeed() at completion.
5201
             * Local only: the word is held at PRODUCING. */
5202
            if ((cur > 0) && (*nextSeedRBGCStratum_p > 0))
5203
                cur = 0;
5204
#endif
5205
5206
            if (n > nextSeedSz - (word32)cur)
5207
                n = nextSeedSz - (word32)cur;
5208
5209
            ret = wc_GenerateSeed(&os, seed + cur, n);
5210
            if (ret != 0) {
5211
                /* Partial bank preserved -- retry on a later cycle.
5212
                 * (If a purge landed meanwhile, the release discards
5213
                 * instead; the seed-gather failure is the more
5214
                 * informative code and wins over the release's
5215
                 * BUSY_E.) */
5216
                (void)NextSeedProducerRelease(lenp, seed, nextSeedSz, cur);
5217
                return ret;
5218
            }
5219
5220
#ifdef WC_RNG_HAVE_RBGC
5221
            *nextSeedRBGCStratum_p = 0;
5222
#endif
5223
        }
5224
5225
        cur += (int)n;
5226
    }
5227
5228
    if (cur < (WC_ATOMIC_INT_ARG)nextSeedSz) {
5229
        /* Partial credited fill this call: release the claim back to
5230
         * the fill offset for a later cycle to resume.  A purge
5231
         * meanwhile discards instead, and the release's BUSY_E
5232
         * percolates -- returning 0 would claim banked progress the
5233
         * purge just evaporated. */
5234
        return NextSeedProducerRelease(lenp, seed, nextSeedSz, cur);
5235
    }
5236
5237
    if (cur == (WC_ATOMIC_INT_ARG)nextSeedSz) {
5238
#ifdef WC_RNG_HAVE_RBGC
5239
        /* If RBGC bytes were used for the reseed, then we can skip
5240
         * wc_RNG_TestSeed(). */
5241
        if (*nextSeedRBGCStratum_p > 0) {
5242
            ret = NextSeedProducerRelease(lenp, seed, nextSeedSz,
5243
                                          WC_DRBG_NEXT_SEED_READY);
5244
            if (ret != 0) {
5245
                /* Purged while producing (BUSY_E): nothing banked;
5246
                 * post-event material wanted.  Retryable. */
5247
                return ret;
5248
            }
5249
            #ifdef WC_RNG_DEBUG_STATS
5250
            ++rng->_stats_nextseedsbanked;
5251
            #endif
5252
            return 0;
5253
        }
5254
#endif
5255
        /* Bank complete: health-test now, in advance of consumption, so
5256
         * that wc_RNG_DRBG_NextSeedNow() is pure computation. */
5257
        ret = wc_RNG_TestSeed(seed, nextSeedSz);
5258
        if (ret == 0) {
5259
            ret = NextSeedProducerRelease(lenp, seed, nextSeedSz,
5260
                                          WC_DRBG_NEXT_SEED_READY);
5261
            if (ret != 0) {
5262
                /* Purged while producing (BUSY_E): nothing banked;
5263
                 * post-event material wanted.  Retryable. */
5264
                return ret;
5265
            }
5266
            #ifdef WC_RNG_DEBUG_STATS
5267
            ++rng->_stats_nextseedsbanked;
5268
            #endif
5269
            return 0;
5270
        }
5271
        else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
5272
            /* wc_RNG_TestSeed() did nothing with the data -- not
5273
             * dispositive.  Release complete-but-unpublished for a
5274
             * later retry; a purge-discard's BUSY_E percolates (the
5275
             * retry cause is then the purge, not the test). */
5276
            ret = NextSeedProducerRelease(lenp, seed, nextSeedSz,
5277
                                          (WC_ATOMIC_INT_ARG)nextSeedSz);
5278
            if (ret != 0)
5279
                return ret;
5280
            return NOT_READY_E;
5281
        }
5282
        else if ((ret == WC_NO_ERR_TRACE(ENTROPY_RT_E)) ||
5283
                 (ret == WC_NO_ERR_TRACE(ENTROPY_APT_E)))
5284
        {
5285
            /* Use-once: a failed test consumes the material. */
5286
            #ifdef WC_RNG_DEBUG_STATS
5287
            ++rng->_stats_seed_failures;
5288
            #endif
5289
            /* Use-once on a failed test is enforced by the sentinel
5290
             * alone: an EMPTY aperture is never consumed, and the next
5291
             * fill overwrites from offset zero.  The buffer is never
5292
             * zeroized (house rule for the seed apertures).  Burn and
5293
             * purge-discard converge on EMPTY; the release handles
5294
             * both, and the health-test failure is the more
5295
             * informative code and wins over the release's BUSY_E. */
5296
            /* Sentinel-only by doctrine: rejection here is deterministic
5297
             * on the bytes (RCT/APT), so every sibling lineage rejects the
5298
             * identical material -- no copy is ever consumed anywhere. */
5299
            (void)NextSeedProducerRelease(lenp, seed, nextSeedSz,
5300
                                          WC_DRBG_NEXT_SEED_EMPTY);
5301
5302
            /* The health-test failure belongs to the depositor's seed
5303
             * collection, not to the destination RNG.  The depositor collects
5304
             * via wc_GenerateSeed(), banks into rng's aperture, and tests
5305
             * before publishing; on failure the aperture is reset to _EMPTY,
5306
             * so nothing untested is ever visible to rng.  rng is a passive
5307
             * destination here -- it did not consume the material, and its
5308
             * state, status and reseed schedule are untouched.  Do not mark it
5309
             * failed.
5310
             *
5311
             * PollAndReSeed() looks similar and is not: there, rng is reseeding
5312
             * itself from its own seed source, the tested material is on the
5313
             * path into its own state, and a failure indeed means that that
5314
             * instance's source has failed.  DRBG_FAILED is correct there and
5315
             * wrong here.  Per-instance attribution is meaningful, not
5316
             * arbitrary: seed sources are frequently core-local (RDSEED among
5317
             * them), so one instance's source can fail while its siblings' are
5318
             * healthy.
5319
             *
5320
             * Bigger picture: An RCT/APT failure is an entropy-source event (SP
5321
             * 800-90B 4.4), and wc_RNG_TestSeed's cutoffs carry a designed
5322
             * false-positive rate.  A terminal response from a thread that is
5323
             * not the instance's owner would effectively be a remote kill
5324
             * primitive on a tuned statistical alarm.
5325
             */
5326
5327
            return ret;
5328
        }
5329
        else {
5330
            /* Buggy or brokey.  Release complete-but-unpublished; the
5331
             * material is untested but intact, and a later cycle
5332
             * re-adjudicates.  The primary error is the more
5333
             * informative code and wins over a purge-discard's
5334
             * BUSY_E. */
5335
            (void)NextSeedProducerRelease(lenp, seed, nextSeedSz,
5336
                                          (WC_ATOMIC_INT_ARG)nextSeedSz);
5337
            return ret;
5338
        }
5339
    }
5340
5341
    return 0;
5342
}
5343
5344
#ifdef WC_RNG_HAVE_RBGC
5345
int wc_RNG_DRBG_NextSeedGenerate_RBGC(WC_RNG* rng, WC_RNG *root, word32 n) {
5346
    if (root == NULL)
5347
        return BAD_FUNC_ARG;
5348
    return wc_RNG_DRBG_NextSeedGenerate_local(rng, root, n);
5349
}
5350
#endif
5351
5352
int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n) {
5353
    return wc_RNG_DRBG_NextSeedGenerate_local(rng, NULL, n);
5354
}
5355
5356
/* Report the raw aperture value: a racy snapshot by design.  Values in [0, bank
5357
 * length) count banked bytes; WC_DRBG_NEXT_SEED_READY and
5358
 * WC_DRBG_NEXT_SEED_CONSUMING indicate a ready or in-consumption bank,
5359
 * respectively.  With no DRBG instantiated, reports WC_DRBG_NEXT_SEED_EMPTY. */
5360
int wc_RNG_DRBG_NextSeedCurrent(WC_RNG* rng, WC_ATOMIC_INT_ARG* n)
5361
{
5362
    byte* seed;
5363
    wolfSSL_Atomic_Int* lenp;
5364
    word32 nextSeedSz;
5365
5366
    if ((rng == NULL) || (n == NULL))
5367
        return BAD_FUNC_ARG;
5368
5369
    if (NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp, NULL) != 0) {
5370
        *n = WC_DRBG_NEXT_SEED_EMPTY;
5371
        return 0;
5372
    }
5373
5374
    *n = *lenp;
5375
    return 0;
5376
}
5377
5378
/* Consume a ready next-seed bank in an immediate credited reseed.  The caller
5379
 * must own the instance.  Source-free by construction -- the material was
5380
 * gathered from the module's seed source and health-tested at bank time -- so
5381
 * consumption is pure computation and safe in atomic context: the one credited
5382
 * primary reseed shape with that property.  Distinct protocol results:
5383
 * NOT_READY_E when no bank is ready (nothing consumed) or when an elective
5384
 * redemption failed after consuming the bank (use-once); MISSING_RNG_E when
5385
 * the instance has no DRBG (RDRAND et al.) -- both deliberately loud, so a
5386
 * direct caller must demonstrate it understands the instance it holds.  (The
5387
 * WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED checkout arm is return-agnostic by
5388
 * construction and needs neither.)  Use-once: the bank is consumed by the
5389
 * attempt, success or failure.  Note that a banked reseed can never provide SP
5390
 * 800-90 prediction resistance (the material predates the request by
5391
 * construction); wc_RNG_DRBG_Reseed_Now() remains the live-gather shape. */
5392
static WARN_UNUSED_RESULT int wc_RNG_DRBG_NextSeedNow_Nonce_local(
5393
                                  WC_RNG* rng, const byte* nonce,
5394
                                  word32 nonceSz)
5395
{
5396
    byte* seed;
5397
    wolfSSL_Atomic_Int* lenp;
5398
    word32 nextSeedSz;
5399
    int *nextSeedRBGCStratum_p;
5400
    WC_ATOMIC_INT_ARG expected = WC_DRBG_NEXT_SEED_READY;
5401
    int ret;
5402
    int devId;
5403
5404
    if (rng == NULL)
5405
        return BAD_FUNC_ARG;
5406
5407
    if ((nonce == NULL) && (nonceSz != 0))
5408
        return BAD_FUNC_ARG;
5409
5410
    ret = rng_lock_required_check(rng);
5411
    if (ret != 0)
5412
        return ret;
5413
5414
    /* Mirror wc_RNG_GenerateBlock(): only an in-service DRBG may reseed. */
5415
    if (rng->status != DRBG_OK)
5416
        return RNG_FAILURE_E;
5417
5418
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
5419
    devId = rng->devId;
5420
#else
5421
    devId = INVALID_DEVID;
5422
#endif
5423
    ret = wc_RNG_HealthTestLocal(rng, 1, rng->heap, devId);
5424
    if (ret != 0) {
5425
        if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
5426
            rng->status = DRBG_CONT_FAILED;
5427
            return DRBG_CONT_FIPS_E;
5428
        }
5429
        if (ret > 0) /* protocol-domain catch-all: translate at the API */
5430
            ret = RNG_FAILURE_E;
5431
        return ret;
5432
    }
5433
5434
    ret = NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp, &nextSeedRBGCStratum_p);
5435
    if (ret != 0) {
5436
        /* No DRBG instantiated -- nothing to reseed (RDRAND et al.). */
5437
        return ret;
5438
    }
5439
5440
    if (! wolfSSL_Atomic_Int_CompareExchange(lenp, &expected,
5441
                                             WC_DRBG_NEXT_SEED_CONSUMING))
5442
    {
5443
        /* No ready bank -- nothing consumed; reported distinctly. */
5444
        return NOT_READY_E;
5445
    }
5446
5447
    /* Identical byte accounting to PollAndReSeed(): the SEED_BLOCK_SZ
5448
     * prefix was consumed by the bank-time health testing. */
5449
    ret = Hash_DRBG_Reseed(rng, seed + SEED_BLOCK_SZ, SEED_SZ, nonce, nonceSz,
5450
                           1 /* in_bracketed_consume */);
5451
5452
    /* Use-once: consumed by the attempt, success or not.  The scrub must be
5453
     * visible before the aperture reopens. */
5454
    ForceZero(seed, WC_DRBG_NEXT_SEED_LEN);
5455
5456
    /* Release by CAS -- one-shot, and its failure is information, not
5457
     * contention: only NextSeedPurge() writes over a _CONSUMING claim, so a
5458
     * failed release proves an invalidation event landed after this consume
5459
     * claimed the material, i.e. the seed just fed to the reseed was banked
5460
     * pre-event.  The reseed's own latch handling could not see that (an epoch
5461
     * crossing shows only at the aperture's claim word, never in the lock
5462
     * word), and if it entered invalidated and ran undisturbed it has already
5463
     * cleared the latch -- so compensate: re-latch, and re-saturate the counter
5464
     * (the stale credited reseed reset it, leaving the latch as sole
5465
     * enforcement; wc_RNG_DRBG_ScheduleReseed() restores the second layer --
5466
     * race-free here, under the exclusive lease).  Claims (stats, stratum
5467
     * adoption) are made only behind a successful release.  Do NOT re-run
5468
     * wc_RNG_invalidate_entropy() here: the event's purges already ran, and
5469
     * re-purging would discard post-event material the banker may have
5470
     * re-banked meanwhile. */
5471
    {
5472
        int cas_ret;
5473
        WC_ATOMIC_INT_ARG expected_out = WC_DRBG_NEXT_SEED_CONSUMING;
5474
        WC_CAS_WITH_RETRY_BEGIN(lenp, expected_out, cas_ret) {
5475
            WC_CAS_WITH_RETRY_LOOP_UNTIL(wolfSSL_Atomic_Int_CompareExchange,
5476
                                         lenp, expected_out,
5477
                                         WC_DRBG_NEXT_SEED_EMPTY, cas_ret,
5478
                                         NEEDS_RECOVERY_E);
5479
        } WC_CAS_WITH_RETRY_END;
5480
        if (cas_ret != 0) {
5481
    #ifdef WC_RNG_HAVE_LOCK
5482
            {
5483
                WC_RNG_lock_arg_t cur_lock;
5484
                int relatch_ret;
5485
                WC_CAS_WITH_RETRY_BEGIN_INIT_CUR(&rng->lock, cur_lock,
5486
                                                 relatch_ret) {
5487
                    WC_CAS_WITH_RETRY_LOOP_FOREVER(
5488
                        wolfSSL_Atomic_Uint_CompareExchange, &rng->lock,
5489
                        cur_lock,
5490
                        cur_lock | WC_RNG_LOCK_ENTROPY_INVALIDATED,
5491
                        relatch_ret);
5492
                } WC_CAS_WITH_RETRY_END;
5493
                if (relatch_ret != 0) {
5494
                    /* Aborted re-latch: latch down, counter scheduled.
5495
                     * Latch-or-condemn (see wc_RNG_invalidate_entropy()):
5496
                     * condemn. */
5497
                    rng->status = DRBG_FAILED;
5498
                }
5499
            }
5500
    #endif
5501
            {
5502
                int sched_ret = wc_RNG_DRBG_ScheduleReseed_local(rng);
5503
                if ((ret == DRBG_SUCCESS) && (sched_ret != 0))
5504
                    return sched_ret;
5505
            }
5506
            if (ret == DRBG_SUCCESS) {
5507
                /* The discarded recovery is the whole story. */
5508
                return cas_ret;
5509
            }
5510
            /* Else the reseed's own failure is the more informative code:
5511
             * fall through to the standard outcome mapping.
5512
             *
5513
             * Note that the ordering here matters: the
5514
             * wc_RNG_DRBG_ScheduleReseed() above has just saturated the reseed
5515
             * counter (unless it too failed, leaving the re-upped latch as sole
5516
             * enforcement); the failed reseed will fall through below and the
5517
             * DRBG will be condemned by the runway gate.  This is intentional:
5518
             * an invalidation-crossed failure is never elective, and the seed
5519
             * just consumed was banked pre-event, so the instance has no
5520
             * trustworthy runway for the gate's leniency to protect, and
5521
             * lenient NOT_READY_E here would misreport a quarantined instance
5522
             * as merely not-yet-ready. */
5523
        }
5524
        else {
5525
    #ifdef WC_RNG_DEBUG_STATS
5526
            if (ret == 0) {
5527
        #ifdef WC_RNG_HAVE_RBGC
5528
                if (*nextSeedRBGCStratum_p > 0)
5529
                    ++rng->_stats_nextseedsRBGC_redeemed;
5530
                else
5531
        #endif
5532
                    ++rng->_stats_nextseedsprimary_redeemed;
5533
            }
5534
    #endif
5535
    #ifdef WC_RNG_HAVE_RBGC
5536
            if (ret == 0) {
5537
                rng->RBGCStratum = *nextSeedRBGCStratum_p;
5538
                *nextSeedRBGCStratum_p = 0;
5539
            }
5540
    #endif
5541
        }
5542
    }
5543
5544
    if (ret == DRBG_SUCCESS) {
5545
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
5546
        /* Check for PID change after consuming the banked seed. */
5547
        ret = rng_pid_change_check(rng);
5548
#else
5549
        ret = 0;
5550
#endif
5551
    }
5552
    else {
5553
        wc_drbg_reseed_ctr_t ctr = WC_RESEED_INTERVAL;
5554
        (void)wc_RNG_DRBG_GetReseedCtr(rng, &ctr);
5555
        if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
5556
            /* Not reachable here -- retained only for uniformity with
5557
             * wc_RNG_GenerateBlock() and wc_RNG_DRBG_Reseed_Now().  Where
5558
             * reachable, the suspect seed was rejected before use, and the DRBG
5559
             * state and runway are intact. */
5560
            if (ctr >= WC_RESEED_INTERVAL) {
5561
                /* The instance is out of generate runway -- condemn now, matching
5562
                 * wc_RNG_GenerateBlock()'s behavior for mandatory reseeds. */
5563
                rng->status = DRBG_CONT_FAILED;
5564
            }
5565
            ret = DRBG_CONT_FIPS_E;
5566
        }
5567
        else if (ctr >= WC_RESEED_INTERVAL) {
5568
            /* The instance is out of generate runway -- condemn now, matching
5569
             * wc_RNG_GenerateBlock()'s behavior for mandatory reseeds. */
5570
            rng->status = DRBG_FAILED;
5571
            ret = RNG_FAILURE_E;
5572
        }
5573
        else {
5574
            ret = NOT_READY_E;
5575
        }
5576
    }
5577
5578
    return ret;
5579
}
5580
5581
int wc_RNG_DRBG_NextSeedNow_Nonce(WC_RNG* rng, const byte* nonce,
5582
                                  word32 nonceSz)
5583
{
5584
    int ret;
5585
5586
    if (rng == NULL)
5587
        return BAD_FUNC_ARG;
5588
    ret = RngAutoLockEnter(rng);
5589
    if (ret != 0)
5590
        return ret;
5591
    ret = wc_RNG_DRBG_NextSeedNow_Nonce_local(rng, nonce, nonceSz);
5592
    RngAutoLockExit(rng);
5593
    return ret;
5594
}
5595
5596
#if defined(WC_RNG_HAVE_NEXT_SEED) && defined(WC_RNG_HAVE_LOCK) && \
5597
    defined(WC_RNG_HAVE_RBGC)
5598
/* For the generate path, which holds the lock already.  Guarded to match
5599
 * its one call site, which needs the lock and RBGC builds as well. */
5600
static WARN_UNUSED_RESULT int wc_RNG_DRBG_NextSeedNow_local(WC_RNG* rng) {
5601
    return wc_RNG_DRBG_NextSeedNow_Nonce_local(rng, NULL, 0);
5602
}
5603
#endif
5604
5605
int wc_RNG_DRBG_NextSeedNow(WC_RNG* rng) {
5606
    return wc_RNG_DRBG_NextSeedNow_Nonce(rng, NULL, 0);
5607
}
5608
5609
/* Deposit raw uncredited stir material into rng's accumulator.  Callable from
5610
 * any context and without owning the instance: the deposit protocol
5611
 * (read-copy-store) is multi-writer-tolerant -- every published span was
5612
 * written by its publisher, lost updates merely drop entropy, and interleaved
5613
 * fragments of compatible provenance are harmless.  A full accumulator
5614
 * publishes WC_DRBG_NEXT_SEED_READY (no health test -- no claim is being made)
5615
 * and shunts further deposits to xorbuf() until consumed. */
5616
int wc_RNG_DRBG_NextStirStore(WC_RNG* rng, const byte *nonce, word32 nonceSz)
5617
{
5618
    WC_ATOMIC_INT_ARG cur;
5619
5620
    if ((rng == NULL) || (nonce == NULL) || (nonceSz == 0))
5621
        return BAD_FUNC_ARG;
5622
5623
    /* Note, rng need not be locked -- that's the whole point of the
5624
     * banked-next-stir aperture protocol.
5625
     */
5626
5627
    cur = WOLFSSL_ATOMIC_LOAD(rng->nextStirLen);
5628
5629
    if ((cur >= 0) && (cur < (WC_ATOMIC_INT_ARG)sizeof(rng->nextStir))) {
5630
        word32 fill = (word32)cur;
5631
        word32 room = (word32)sizeof(rng->nextStir) - fill;
5632
        word32 take = (nonceSz < room) ? nonceSz : room;
5633
5634
        XMEMCPY(rng->nextStir + fill, nonce, take);
5635
        fill += take;
5636
        if (fill == (word32)sizeof(rng->nextStir)) {
5637
            WOLFSSL_ATOMIC_STORE(rng->nextStirLen, WC_DRBG_NEXT_SEED_READY);
5638
            #ifdef WC_RNG_DEBUG_STATS
5639
            ++rng->_stats_nextstirs_banked; /* racy */
5640
            #endif
5641
            nonce += take;
5642
            nonceSz -= take; /* spillover falls through to the xorbuf() */
5643
        }
5644
        else {
5645
            WOLFSSL_ATOMIC_STORE(rng->nextStirLen,
5646
                                 cur + (WC_ATOMIC_INT_ARG)take);
5647
            return 0;
5648
        }
5649
        if (nonceSz == 0)
5650
            return 0;
5651
    }
5652
5653
    if (nonceSz > (word32)sizeof(rng->nextStir))
5654
        nonceSz = (word32)sizeof(rng->nextStir);
5655
    xorbuf(rng->nextStir, nonce, nonceSz);
5656
5657
    return 0;
5658
}
5659
5660
/* Consume a ready uncredited accumulator in an immediate uncredited
5661
 * (stirring) reseed.  The caller must own the instance.  The credited=0
5662
 * path holds the three no-ops by construction: the reseed counter is not
5663
 * reset, WC_RNG_LOCK_ENTROPY_INVALIDATED is not cleared, and RBGCStratum
5664
 * is unchanged -- a stir must never masquerade as recovery or promotion.
5665
 * Use-once: the material is consumed (accumulation reopens) whether or not
5666
 * the reseed succeeds.  The buffer is never zeroized (racy against
5667
 * depositors, and zeroing is always a net entropy loss). */
5668
static WARN_UNUSED_RESULT int wc_RNG_DRBG_NextStirNow_local(WC_RNG* rng)
5669
{
5670
    WC_ATOMIC_INT_ARG expected = WC_DRBG_NEXT_SEED_READY;
5671
    wc_drbg_reseed_ctr_t reseedCtr;
5672
    int ret;
5673
5674
    if (rng == NULL)
5675
        return BAD_FUNC_ARG;
5676
5677
    ret = rng_lock_required_check(rng);
5678
    if (ret != 0)
5679
        return ret;
5680
5681
    /* Mirror wc_RNG_GenerateBlock(): only an in-service DRBG may reseed. */
5682
    if (rng->status != DRBG_OK)
5683
        return RNG_FAILURE_E;
5684
5685
    /* If a reseed is due, the RNG is not ready for a stir. */
5686
    ret = wc_RNG_DRBG_GetReseedCtr(rng, &reseedCtr);
5687
    if (ret < 0)
5688
        return ret;
5689
    if (reseedCtr >= WC_RESEED_INTERVAL)
5690
        return NOT_READY_E;
5691
5692
    if (! wolfSSL_Atomic_Int_CompareExchange(&rng->nextStirLen, &expected,
5693
                                             WC_DRBG_NEXT_SEED_CONSUMING))
5694
    {
5695
        /* Accumulator not READY. */
5696
        if (expected < 0) {
5697
            /* claimed by a racing consumer. */
5698
            return BUSY_E;
5699
        }
5700
        else {
5701
            /* empty or still accumulating -- nothing consumable yet. */
5702
            return NOT_READY_E;
5703
        }
5704
    }
5705
5706
    ret = Hash_DRBG_StirGenerate(rng, rng->nextStir,
5707
                                 (word32)sizeof(rng->nextStir));
5708
5709
#ifdef WC_RNG_DEBUG_STATS
5710
    if (ret == 0)
5711
        ++rng->_stats_nextstirs_redeemed;
5712
#endif
5713
5714
    /* Always burn consumed data before releasing it, even if it's uncredited
5715
     * noise.  Unlike the seed aperture, the stir aperture has no producer
5716
     * claim: lease-free depositors xorbuf() into it at any time during
5717
     * _CONSUMING, so the burn here can only discard an incoming overflow
5718
     * fragment, after the full aperture has already been absorbed by
5719
     * the StirGenerate() above. */
5720
    ForceZero(rng->nextStir, (word32)sizeof(rng->nextStir));
5721
    WOLFSSL_ATOMIC_STORE(rng->nextStirLen, WC_DRBG_NEXT_SEED_EMPTY);
5722
5723
    return ret;
5724
}
5725
5726
int wc_RNG_DRBG_NextStirNow(WC_RNG* rng)
5727
{
5728
    int ret;
5729
5730
    if (rng == NULL)
5731
        return BAD_FUNC_ARG;
5732
    ret = RngAutoLockEnter(rng);
5733
    if (ret != 0)
5734
        return ret;
5735
    ret = wc_RNG_DRBG_NextStirNow_local(rng);
5736
    RngAutoLockExit(rng);
5737
    return ret;
5738
}
5739
5740
#endif /* WC_RNG_HAVE_NEXT_SEED */
5741
5742
#endif /* HAVE_HASHDRBG */
5743
5744
/* place a generated block in output */
5745
#ifdef WC_HAVE_RNG_BANKREF
5746
static WARN_UNUSED_RESULT int wc_local_RNG_GenerateBlock(WC_RNG* rng,
5747
                                                         byte* output,
5748
                                                         word32 sz)
5749
#else
5750
WOLFSSL_ABI
5751
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
5752
#endif
5753
0
{
5754
0
    int ret;
5755
5756
0
    if (rng == NULL || output == NULL)
5757
0
        return BAD_FUNC_ARG;
5758
5759
0
    ret = rng_lock_required_check(rng);
5760
0
    if (ret != 0)
5761
0
        return ret;
5762
5763
0
    if (sz == 0)
5764
0
        return 0;
5765
5766
#ifdef WOLF_CRYPTO_CB
5767
    /* before the lock: a callback may fall back to this same instance */
5768
    #ifndef WOLF_CRYPTO_CB_FIND
5769
    if (rng->devId != INVALID_DEVID)
5770
    #endif
5771
    {
5772
        ret = wc_CryptoCb_RandomBlock(rng, output, sz);
5773
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
5774
            return ret;
5775
        /* fall-through when unavailable */
5776
    }
5777
#endif
5778
5779
    /* These read a device, not this instance, so a lock protects nothing here.
5780
     * On RDRAND hardware wc_InitRng() creates no lock at all, as tested. */
5781
#ifdef HAVE_INTEL_RDRAND
5782
    if (IS_INTEL_RDRAND(intel_flags))
5783
        return wc_GenerateRand_IntelRD(NULL, output, sz);
5784
#endif
5785
5786
#if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_TRNG)
5787
    return silabs_GenerateRand(output, sz);
5788
#endif
5789
5790
0
    ret = RngAutoLockEnter(rng);   /* held across every other backend */
5791
0
    if (ret != 0)
5792
0
        return ret;
5793
5794
#if defined(WOLFSSL_ASYNC_CRYPT)
5795
    if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
5796
        /* these are blocking */
5797
    #ifdef HAVE_CAVIUM
5798
        ret = NitroxRngGenerateBlock(rng, output, sz);
5799
        RngAutoLockExit(rng);
5800
        return ret;
5801
    #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
5802
        ret = IntelQaDrbg(&rng->asyncDev, output, sz);
5803
        RngAutoLockExit(rng);
5804
        return ret;
5805
    #else
5806
        /* simulator not supported */
5807
    #endif
5808
    }
5809
#endif
5810
5811
#ifdef CUSTOM_RAND_GENERATE_BLOCK
5812
    XMEMSET(output, 0, sz);
5813
    ret = (int)CUSTOM_RAND_GENERATE_BLOCK(output, sz);
5814
    #ifdef WC_VERBOSE_RNG
5815
    if (ret != 0)
5816
        WOLFSSL_DEBUG_PRINTF(
5817
            "ERROR: CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
5818
    #endif
5819
    RngAutoLockExit(rng);   /* a no-op here today; the gate excludes this build */
5820
#else
5821
5822
0
#ifdef HAVE_HASHDRBG
5823
0
    if (sz > RNG_MAX_BLOCK_LEN) {
5824
0
        RngAutoLockExit(rng);
5825
0
        return BAD_FUNC_ARG;
5826
0
    }
5827
5828
0
    if (rng->status != DRBG_OK) {
5829
0
        RngAutoLockExit(rng);
5830
0
        return RNG_FAILURE_E;
5831
0
    }
5832
5833
#ifdef WC_RNG_DEBUG_STATS
5834
    ++rng->_stats_total_requests;
5835
    rng->_stats_total_bytes_requested += sz;
5836
#endif
5837
5838
0
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
5839
0
    ret = rng_pid_change_check(rng);
5840
0
    if (ret != 0) {
5841
0
        RngAutoLockExit(rng);
5842
0
        return ret;
5843
0
    }
5844
0
#endif
5845
5846
#if defined(WC_RNG_HAVE_NEXT_SEED) && defined(WC_RNG_HAVE_LOCK) && \
5847
    defined(WC_RNG_HAVE_RBGC)
5848
    if (rng->flags & WC_RNG_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED) {
5849
        /* externally-refreshed instance: consume a READY banked seed to
5850
         * recover from entropy invalidation (any provenance -- the purge
5851
         * in wc_RNG_invalidate_entropy() guarantees a READY seed is
5852
         * post-event), or to promote a chain-backed instance to primary.
5853
         * Consumption is a credited reseed, clearing the flag and
5854
         * resetting the schedule; failure falls through to the ordinary
5855
         * forced-reseed machinery. */
5856
        int banked_stratum = wc_RNG_DRBG_GetNextSeedRBGCStratum(rng);
5857
        if (banked_stratum >= 0) {
5858
            if (((WOLFSSL_ATOMIC_LOAD(rng->lock) &
5859
                  WC_RNG_LOCK_ENTROPY_INVALIDATED))
5860
                ||
5861
                ((rng->RBGCStratum > 0) && (banked_stratum == 0)))
5862
            {
5863
                ret = wc_RNG_DRBG_NextSeedNow_local(rng);
5864
                if ((ret == WC_NO_ERR_TRACE(DRBG_CONT_FIPS_E)) ||
5865
                    (ret == WC_NO_ERR_TRACE(RNG_FAILURE_E)))
5866
                {
5867
                    RngAutoLockExit(rng);
5868
                    return ret;
5869
                }
5870
            }
5871
        }
5872
    }
5873
#endif
5874
5875
#ifdef WC_RNG_HAVE_NEXT_SEED
5876
    /* Universal opportunistic stir: a READY uncredited accumulator is
5877
     * consumed by any generate, unconditionally -- stirs are always
5878
     * harmless, and are invisible to the credited legs above (no counter
5879
     * reset, no flag clear, no stratum change).  One relaxed load when
5880
     * empty. */
5881
    if (WOLFSSL_ATOMIC_LOAD(rng->nextStirLen) == WC_DRBG_NEXT_SEED_READY) {
5882
        int stir_ret = wc_RNG_DRBG_NextStirNow_local(rng);
5883
        if (stir_ret == WC_NO_ERR_TRACE(RNG_FAILURE_E)) {
5884
            /* The DRBG broke while we were stirring it. */
5885
            RngAutoLockExit(rng);
5886
            return stir_ret;
5887
        }
5888
    }
5889
#endif /* WC_RNG_HAVE_NEXT_SEED */
5890
5891
#ifdef WC_RNG_HAVE_LOCK
5892
    if (WOLFSSL_ATOMIC_LOAD(rng->lock) & WC_RNG_LOCK_ENTROPY_INVALIDATED) {
5893
        if (PollAndReSeed(rng, NULL, 0) != DRBG_SUCCESS) {
5894
            rng->status = DRBG_FAILED;
5895
            RngAutoLockExit(rng);
5896
            return RNG_FAILURE_E;
5897
        }
5898
    }
5899
#endif
5900
5901
0
#ifndef NO_SHA256
5902
0
    if (rng->drbgType == WC_DRBG_SHA256) {
5903
0
        ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz,
5904
0
                                 NULL, 0);
5905
0
        if (ret == WC_NO_ERR_TRACE(DRBG_NEED_RESEED)) {
5906
0
            ret = PollAndReSeed(rng, NULL, 0);
5907
0
            if (ret != DRBG_SUCCESS) {
5908
0
                if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE))
5909
0
                    rng->status = DRBG_CONT_FAILED;
5910
0
                else
5911
0
                    rng->status = DRBG_FAILED;
5912
0
            }
5913
0
            else {
5914
0
                ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output,
5915
0
                                         sz, NULL, 0);
5916
0
            }
5917
0
        }
5918
0
    }
5919
0
    else
5920
0
#endif
5921
0
#ifdef WOLFSSL_DRBG_SHA512
5922
0
    if (rng->drbgType == WC_DRBG_SHA512) {
5923
0
        ret = Hash512_DRBG_Generate((DRBG_SHA512_internal *)rng->drbg512,
5924
0
                                    output, sz, NULL, 0);
5925
0
        if (ret == WC_NO_ERR_TRACE(DRBG_NEED_RESEED)) {
5926
0
            ret = PollAndReSeed(rng, NULL, 0);
5927
0
            if (ret != DRBG_SUCCESS) {
5928
0
                if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE))
5929
0
                    rng->status = DRBG_CONT_FAILED;
5930
0
                else
5931
0
                    rng->status = DRBG_FAILED;
5932
0
            }
5933
0
            else {
5934
0
                ret = Hash512_DRBG_Generate(
5935
0
                    (DRBG_SHA512_internal *)rng->drbg512, output, sz,
5936
0
                    NULL, 0);
5937
0
            }
5938
0
        }
5939
0
    }
5940
0
    else
5941
0
#endif
5942
0
    {
5943
0
        ret = DRBG_FAILURE;
5944
0
        rng->status = DRBG_FAILED;
5945
0
    }
5946
5947
0
    if (ret == DRBG_SUCCESS) {
5948
0
        ret = 0;
5949
#ifdef WC_RNG_DEBUG_STATS
5950
        rng->_stats_total_bytes_produced += sz;
5951
    #ifdef WC_RNG_HAVE_RBGC
5952
        /* chain-provenance output: generated while chain-backed */
5953
        if (rng->RBGCStratum > 0)
5954
            rng->_stats_RBGC_bytes_produced += sz;
5955
    #endif
5956
#endif
5957
0
    }
5958
0
    else if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
5959
0
        ret = DRBG_CONT_FIPS_E;
5960
0
        rng->status = DRBG_CONT_FAILED;
5961
0
    }
5962
0
    else {
5963
0
        ret = RNG_FAILURE_E;
5964
        /* Note, Hash_DRBG_Generate() always leaves the DRBG in a
5965
         * self-consistent state, success or failure, and can fail for retryable
5966
         * causes (e.g. failed memory allocation), so we only update rng->status
5967
         * above.
5968
         */
5969
0
    }
5970
0
    RngAutoLockExit(rng);
5971
#else
5972
5973
    /* if we get here then there is an RNG configuration error */
5974
    ret = RNG_FAILURE_E;
5975
    RngAutoLockExit(rng);   /* a no-op here today; the gate excludes this build */
5976
5977
#endif /* HAVE_HASHDRBG */
5978
0
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
5979
5980
0
    return ret;
5981
0
}
5982
5983
#ifdef WC_HAVE_RNG_BANKREF
5984
WOLFSSL_ABI
5985
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
5986
{
5987
    if (rng == NULL)
5988
        return BAD_FUNC_ARG;
5989
5990
    {
5991
        int lock_ret = rng_lock_required_check(rng);
5992
        if (lock_ret != 0)
5993
            return lock_ret;
5994
    }
5995
5996
    if (rng->flags & WC_RNG_FLAG_BANKREF) {
5997
        int ret;
5998
        struct wc_rng_bank_inst *bank_inst = NULL;
5999
6000
        ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst);
6001
        if (ret != 0)
6002
            return ret;
6003
        if (bank_inst == NULL)
6004
            return BAD_STATE_E;
6005
        ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst),
6006
                                         output, sz);
6007
        {
6008
            int checkin_ret = wc_rng_bank_inst_checkin(&bank_inst);
6009
            if (checkin_ret != 0) {
6010
#ifdef WC_VERBOSE_RNG
6011
                WOLFSSL_DEBUG_PRINTF(
6012
                    "ERROR: wc_RNG_GenerateBlock() wc_rng_bank_inst_checkin() "
6013
                    "failed with err %d.", checkin_ret);
6014
#endif
6015
                if (ret == 0)
6016
                    ret = checkin_ret;
6017
            }
6018
        }
6019
        return ret;
6020
    }
6021
    else
6022
        return wc_local_RNG_GenerateBlock(rng, output, sz);
6023
}
6024
#endif
6025
6026
int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
6027
0
{
6028
0
    return wc_RNG_GenerateBlock(rng, b, 1);
6029
0
}
6030
6031
6032
int wc_FreeRng(WC_RNG* rng)
6033
0
{
6034
0
    int ret = 0;
6035
6036
0
    if (rng == NULL)
6037
0
        return BAD_FUNC_ARG;
6038
6039
    /* Note, deallocation proceeds regardless of RNG lock status.  Lifecycle
6040
     * management is the caller's responsibility, and a lock inside the object
6041
     * cannot arbitrate deallocation.
6042
     */
6043
6044
#ifdef WC_HAVE_RNG_BANKREF
6045
    if (rng->flags & WC_RNG_FLAG_BANKREF)
6046
        return wc_BankRef_Release(rng);
6047
#endif /* WC_HAVE_RNG_BANKREF */
6048
6049
#ifdef WC_RNG_HAVE_FREE_HOOK
6050
    if (rng->free_hook != NULL) {
6051
        /* one-shot, cleared before firing: re-entrant frees from the hook
6052
         * (not that they would be a good idea) can't loop. */
6053
        wc_RNG_free_hook_cb_t free_hook = rng->free_hook;
6054
        rng->free_hook = NULL;
6055
        ret = free_hook(rng, rng->free_hook_arg);
6056
        rng->free_hook_arg = NULL;
6057
    }
6058
#endif
6059
6060
#ifdef WC_RNG_HAVE_POOL
6061
    /* single-owner teardown; the only pool deallocation site */
6062
    if (rng->pool != NULL) {
6063
        ForceZero(rng->pool, rng->poolSize);
6064
        XFREE(rng->pool, rng->heap, DYNAMIC_TYPE_RNG);
6065
        rng->pool = NULL;
6066
        rng->poolSize = 0;
6067
        WOLFSSL_ATOMIC_STORE(rng->poolHead, 0);
6068
        WOLFSSL_ATOMIC_STORE(rng->poolTail, 0);
6069
    }
6070
#endif
6071
6072
0
#ifdef WC_RNG_HAVE_AUTO_LOCK
6073
0
    RngAutoLockFree(rng);
6074
0
#endif
6075
6076
#ifdef WC_RNG_HAVE_NEXT_SEED
6077
    /* The stir accumulator is WC_RNG-resident (it survives DRBG teardown so
6078
     * that blind depositors never dereference rng->drbg), so the DRBG
6079
     * teardown below cannot wipe it -- wipe it here.  A concurrent blind
6080
     * deposit can tear the wipe harmlessly (uncredited material, and
6081
     * all-zeros decodes as empty/accumulating).  Note the contrast with the
6082
     * lock word, which deliberately survives deallocation. */
6083
    ForceZero(rng->nextStir, (word32)sizeof(rng->nextStir));
6084
    WOLFSSL_ATOMIC_STORE(rng->nextStirLen, WC_DRBG_NEXT_SEED_EMPTY);
6085
#endif
6086
6087
#if defined(WOLFSSL_ASYNC_CRYPT)
6088
    wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
6089
#endif
6090
6091
0
#ifdef HAVE_HASHDRBG
6092
0
#ifndef NO_SHA256
6093
0
    if (rng->drbg != NULL) {
6094
0
      if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg) != DRBG_SUCCESS)
6095
0
            ret = RNG_FAILURE_E;
6096
6097
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
6098
0
        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
6099
    #elif defined(WOLFSSL_CHECK_MEM_ZERO)
6100
        wc_MemZero_Check(rng->drbg, sizeof(DRBG_internal));
6101
    #endif
6102
0
        rng->drbg = NULL;
6103
0
    }
6104
6105
    #ifdef WOLFSSL_SMALL_STACK_CACHE
6106
    /* Scratch buffers are tracked independently of rng->drbg so that a
6107
     * partial-construction failure path that nulled rng->drbg early
6108
     * (or any future restructure that does the same) cannot leak them.
6109
     * Free on their own NULL check rather than nesting under drbg. */
6110
    if (rng->drbg_scratch != NULL) {
6111
        if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch)
6112
                            != DRBG_SUCCESS)
6113
            ret = RNG_FAILURE_E;
6114
        XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
6115
        rng->drbg_scratch = NULL;
6116
    }
6117
    if (rng->health_check_scratch != NULL) {
6118
        XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_TMP_BUFFER);
6119
        rng->health_check_scratch = NULL;
6120
    }
6121
    #endif
6122
0
#endif /* !NO_SHA256 */
6123
6124
0
#ifdef WOLFSSL_DRBG_SHA512
6125
0
    if (rng->drbg512 != NULL) {
6126
0
        if (Hash512_DRBG_Uninstantiate(
6127
0
                (DRBG_SHA512_internal *)rng->drbg512) != DRBG_SUCCESS)
6128
0
            ret = RNG_FAILURE_E;
6129
6130
0
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
6131
0
        XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG);
6132
0
    #endif
6133
0
        rng->drbg512 = NULL;
6134
0
    }
6135
6136
    #ifdef WOLFSSL_SMALL_STACK_CACHE
6137
    /* Same independence rationale as the SHA-256 scratch above. */
6138
    if (rng->drbg512_scratch != NULL) {
6139
        if (Hash512_DRBG_Uninstantiate(rng->drbg512_scratch)
6140
                                != DRBG_SUCCESS)
6141
            ret = RNG_FAILURE_E;
6142
        XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG);
6143
        rng->drbg512_scratch = NULL;
6144
    }
6145
    if (rng->health_check_scratch_512 != NULL) {
6146
        XFREE(rng->health_check_scratch_512, rng->heap,
6147
               DYNAMIC_TYPE_TMP_BUFFER);
6148
        rng->health_check_scratch_512 = NULL;
6149
    }
6150
    #endif
6151
0
#endif /* WOLFSSL_DRBG_SHA512 */
6152
6153
#ifdef WOLFSSL_SMALL_STACK_CACHE
6154
    XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED);
6155
    rng->newSeed_buf = NULL;
6156
#endif
6157
6158
0
    rng->status = DRBG_NOT_INIT;
6159
0
#endif /* HAVE_HASHDRBG */
6160
6161
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
6162
    /* don't overwrite previously set error */
6163
    if (wc_VersalTrngReset() && !ret)
6164
        ret = WC_HW_E;
6165
#endif
6166
6167
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && defined(XCLOSE) && \
6168
    !defined(USE_WINDOWS_API)
6169
    if(rng->seed.seedFdOpen && rng->seed.fd != XBADFD) {
6170
        XCLOSE(rng->seed.fd);
6171
        rng->seed.fd = XBADFD;
6172
        rng->seed.seedFdOpen = 0;
6173
    }
6174
#endif
6175
6176
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
6177
    if (rng->flags & WC_RNG_FLAG_FULL_MUTEX) {
6178
        /* If the latch is held, the caller is the holder (enforced when
6179
         * _LOCK_REQUIRED) and owns the mutex: release it before
6180
         * destruction.  A free latch means the mutex is unowned. */
6181
        if (WOLFSSL_ATOMIC_LOAD(rng->lock) & WC_RNG_LOCK_HELD)
6182
            (void)wc_UnLockMutex(&rng->mutex);
6183
        (void)wc_FreeMutex(&rng->mutex);
6184
        rng->flags &= ~WC_RNG_FLAG_FULL_MUTEX;
6185
    }
6186
#endif
6187
6188
    /* Note, rng->lock must *not* be cleared -- it may still be arbitrating
6189
     * access even after wc_FreeRng().
6190
     */
6191
6192
0
    return ret;
6193
0
}
6194
6195
#ifdef HAVE_HASHDRBG
6196
/* The original wc_RNG_HealthTest{,_ex} entry points operate on the SHA-256
6197
 * Hash_DRBG (DRBG_internal). Gate them out under NO_SHA256; SHA-512-only
6198
 * builds use wc_RNG_HealthTest_SHA512_ex declared further down. */
6199
#ifndef NO_SHA256
6200
int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
6201
                                  const byte* seedB, word32 seedBSz,
6202
                                  byte* output, word32 outputSz)
6203
0
{
6204
0
    return wc_RNG_HealthTest_ex(reseed, NULL, 0,
6205
0
                                seedA, seedASz, seedB, seedBSz,
6206
0
                                output, outputSz,
6207
0
                                NULL, INVALID_DEVID);
6208
0
}
6209
6210
6211
static WARN_UNUSED_RESULT int wc_RNG_HealthTest_ex_internal(DRBG_internal* drbg,
6212
                                  int reseed, const byte* nonce, word32 nonceSz,
6213
                                  const byte* seedA, word32 seedASz,
6214
                                  const byte* seedB, word32 seedBSz,
6215
                                  byte* output, word32 outputSz,
6216
                                  void* heap, int devId)
6217
0
{
6218
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
6219
6220
0
    if (seedA == NULL || output == NULL) {
6221
0
        return BAD_FUNC_ARG;
6222
0
    }
6223
6224
0
    if (reseed != 0 && seedB == NULL) {
6225
0
        return BAD_FUNC_ARG;
6226
0
    }
6227
6228
0
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
6229
0
        return BAD_FUNC_ARG;
6230
0
    }
6231
6232
#ifdef WOLFSSL_SMALL_STACK_CACHE
6233
    (void)heap;
6234
    (void)devId;
6235
6236
    if (Hash_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz,
6237
                        NULL, 0) != 0) {
6238
        goto exit_rng_ht;
6239
    }
6240
#else
6241
0
    if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
6242
0
                              NULL, 0, heap, devId) != 0) {
6243
0
        goto exit_rng_ht;
6244
0
    }
6245
0
#endif
6246
6247
0
    if (reseed) {
6248
0
        if (Hash256_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0) != 0) {
6249
0
            goto exit_rng_ht;
6250
0
        }
6251
0
    }
6252
6253
    /* This call to generate is prescribed by the NIST DRBGVS
6254
     * procedure. The results are thrown away. The known
6255
     * answer test checks the second block of DRBG out of
6256
     * the generator to ensure the internal state is updated
6257
     * as expected. */
6258
0
    if (Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0) != 0) {
6259
0
        goto exit_rng_ht;
6260
0
    }
6261
6262
0
    if (Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0) != 0) {
6263
0
        goto exit_rng_ht;
6264
0
    }
6265
6266
    /* Mark success */
6267
0
    ret = 0;
6268
6269
0
exit_rng_ht:
6270
6271
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
6272
    /* This is safe to call even if Hash_DRBG_Instantiate fails */
6273
0
    if ((Hash_DRBG_Uninstantiate(drbg) != 0) && (ret == 0)) {
6274
0
        ret = DRBG_FAILURE;
6275
0
    }
6276
0
#endif
6277
6278
0
    return ret;
6279
0
}
6280
6281
int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
6282
                                  const byte* seedA, word32 seedASz,
6283
                                  const byte* seedB, word32 seedBSz,
6284
                                  byte* output, word32 outputSz,
6285
                                  void* heap, int devId)
6286
0
{
6287
0
    int ret = WC_NO_ERR_TRACE(WC_FAILURE);
6288
0
    DRBG_internal* drbg;
6289
0
#ifndef WOLFSSL_SMALL_STACK
6290
0
    DRBG_internal  drbg_var;
6291
0
#endif
6292
6293
#ifdef WOLFSSL_SMALL_STACK
6294
    drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap,
6295
        DYNAMIC_TYPE_RNG);
6296
    if (drbg == NULL) {
6297
        return MEMORY_E;
6298
    }
6299
#else
6300
0
    drbg = &drbg_var;
6301
0
#endif
6302
6303
#ifdef WOLFSSL_SMALL_STACK_CACHE
6304
    ret = Hash_DRBG_Instantiate(drbg,
6305
                    NULL /* seed */, 0, NULL /* nonce */, 0,
6306
                    NULL /* perso */, 0, heap, devId);
6307
    if (ret == 0)
6308
#endif
6309
0
    {
6310
0
        ret = wc_RNG_HealthTest_ex_internal(
6311
0
                drbg, reseed, nonce, nonceSz, seedA, seedASz,
6312
0
                seedB, seedBSz, output, outputSz, heap, devId);
6313
#ifdef WOLFSSL_SMALL_STACK_CACHE
6314
        Hash_DRBG_Uninstantiate(drbg);
6315
#endif
6316
0
    }
6317
0
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_RNG);
6318
6319
0
    if (ret > 0) {
6320
        /* Translate protocol-domain codes at the public boundary; negative
6321
         * codes (MEMORY_E, BAD_FUNC_ARG) pass verbatim. */
6322
0
        ret = WC_FAILURE;
6323
0
    }
6324
0
    return ret;
6325
0
}
6326
#endif /* !NO_SHA256 - wc_RNG_HealthTest{,_ex,_ex_internal} */
6327
6328
6329
const FLASH_QUALIFIER byte seedA_data[] = {
6330
    0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
6331
    0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
6332
    0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
6333
    0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
6334
};
6335
6336
const FLASH_QUALIFIER byte reseedSeedA_data[] = {
6337
    0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
6338
    0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
6339
    0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
6340
};
6341
6342
const FLASH_QUALIFIER byte outputA_data[] = {
6343
    0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
6344
    0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
6345
    0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
6346
    0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
6347
    0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
6348
    0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
6349
    0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
6350
    0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
6351
    0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
6352
    0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
6353
    0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
6354
};
6355
6356
const FLASH_QUALIFIER byte seedB_data[] = {
6357
    0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
6358
    0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
6359
    0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
6360
    0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
6361
    0xdb, 0xcb, 0xcc, 0x2e
6362
};
6363
6364
const FLASH_QUALIFIER byte outputB_data[] = {
6365
    0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
6366
    0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
6367
    0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
6368
    0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
6369
    0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
6370
    0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
6371
    0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
6372
    0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
6373
    0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
6374
    0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
6375
    0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
6376
};
6377
6378
6379
/* SHA-512 DRBG KAT vectors for local health test.
6380
 * Source: NIST CAVP Hash_DRBG.rsp, [SHA-512], PredictionResistance=False,
6381
 * EntropyInputLen=256, NonceLen=128, PersonalizationStringLen=0,
6382
 * AdditionalInputLen=0, ReturnedBitsLen=2048. */
6383
#ifdef WOLFSSL_DRBG_SHA512
6384
6385
/* Reseed test vectors (COUNT=0 from reseed section) */
6386
static const byte sha512_seedA_data[] = {
6387
    /* EntropyInput (32 bytes) || Nonce (16 bytes) */
6388
    0x31, 0x44, 0xe1, 0x7a, 0x10, 0xc8, 0x56, 0x12,
6389
    0x97, 0x64, 0xf5, 0x8f, 0xd8, 0xe4, 0x23, 0x10,
6390
    0x20, 0x54, 0x69, 0x96, 0xc0, 0xbf, 0x6c, 0xff,
6391
    0x8e, 0x91, 0xc2, 0x4e, 0xe0, 0x9b, 0xe3, 0x33,
6392
    0xb1, 0x6f, 0xcb, 0x1c, 0xf0, 0xc0, 0x10, 0xf3,
6393
    0x1f, 0xea, 0xb7, 0x33, 0x58, 0x8b, 0x8e, 0x04
6394
};
6395
static const byte sha512_reseedSeedA_data[] = {
6396
    /* EntropyInputReseed (32 bytes) */
6397
    0xa0, 0xb3, 0x58, 0x4c, 0x2c, 0x84, 0x12, 0xf6,
6398
    0x18, 0x40, 0x68, 0x34, 0x40, 0x4d, 0x1e, 0xb0,
6399
    0xce, 0x99, 0x9b, 0xa2, 0x89, 0x66, 0x05, 0x4d,
6400
    0x7e, 0x49, 0x7e, 0x0d, 0xb6, 0x08, 0xb9, 0x67
6401
};
6402
static const byte sha512_outputA_data[] = {
6403
    0xef, 0xa3, 0x5d, 0xd0, 0x36, 0x2a, 0xdb, 0x76,
6404
    0x26, 0x45, 0x6b, 0x36, 0xfa, 0xc7, 0x4d, 0x3c,
6405
    0x28, 0xd0, 0x1d, 0x92, 0x64, 0x20, 0x27, 0x5a,
6406
    0x28, 0xbe, 0xa9, 0xc9, 0xdd, 0x75, 0x47, 0xc1,
6407
    0x5e, 0x79, 0x31, 0x85, 0x2a, 0xc1, 0x27, 0x70,
6408
    0x76, 0x56, 0x75, 0x35, 0x23, 0x9c, 0x1f, 0x42,
6409
    0x9c, 0x7f, 0x75, 0xcf, 0x74, 0xc2, 0x26, 0x7d,
6410
    0xeb, 0x6a, 0x3e, 0x59, 0x6c, 0xf3, 0x26, 0x15,
6411
    0x6c, 0x79, 0x69, 0x41, 0x28, 0x3b, 0x8d, 0x58,
6412
    0x3f, 0x17, 0x1c, 0x2f, 0x6e, 0x33, 0x23, 0xf7,
6413
    0x55, 0x5e, 0x1b, 0x18, 0x1f, 0xfd, 0xa3, 0x05,
6414
    0x07, 0x21, 0x0c, 0xb1, 0xf5, 0x89, 0xb2, 0x3c,
6415
    0xd7, 0x18, 0x80, 0xfd, 0x44, 0x37, 0x0c, 0xac,
6416
    0xf4, 0x33, 0x75, 0xb0, 0xdb, 0x7e, 0x33, 0x6f,
6417
    0x12, 0xb3, 0x09, 0xbf, 0xd4, 0xf6, 0x10, 0xbb,
6418
    0x8f, 0x20, 0xe1, 0xa1, 0x5e, 0x25, 0x3a, 0x4f,
6419
    0xe5, 0x11, 0xa0, 0x27, 0x96, 0x8d, 0xf0, 0xb1,
6420
    0x05, 0xa1, 0xd7, 0x3a, 0xff, 0x7c, 0x7a, 0x82,
6421
    0x6d, 0x39, 0xf6, 0x40, 0xdf, 0xb8, 0xf5, 0x22,
6422
    0x25, 0x9e, 0xd4, 0x02, 0x28, 0x2e, 0x2c, 0x2e,
6423
    0x9d, 0x3a, 0x49, 0x8f, 0x51, 0x72, 0x5f, 0xe4,
6424
    0x14, 0x1b, 0x06, 0xda, 0x55, 0x98, 0xa4, 0x2a,
6425
    0xc1, 0xe0, 0x49, 0x4e, 0x99, 0x7d, 0x56, 0x6a,
6426
    0x1a, 0x39, 0xb6, 0x76, 0xb9, 0x6a, 0x60, 0x03,
6427
    0xa4, 0xc5, 0xdb, 0x84, 0xf2, 0x46, 0x58, 0x4e,
6428
    0xe6, 0x5a, 0xf7, 0x0f, 0xf2, 0x16, 0x02, 0x78,
6429
    0x16, 0x6d, 0xa1, 0x6d, 0x91, 0xc9, 0xb8, 0xf2,
6430
    0xde, 0xb0, 0x27, 0x51, 0xa1, 0x08, 0x8a, 0xd6,
6431
    0xbe, 0x4e, 0x80, 0xef, 0x96, 0x6e, 0xb7, 0x3e,
6432
    0x66, 0xbc, 0x87, 0xca, 0xd8, 0x7c, 0x77, 0xc0,
6433
    0xb3, 0x4a, 0x21, 0xba, 0x1d, 0xa0, 0xba, 0x6d,
6434
    0x16, 0xca, 0x50, 0x46, 0xdc, 0x4a, 0xbd, 0xa0
6435
};
6436
6437
/* No-reseed test vectors (COUNT=0 from no-reseed section) */
6438
static const byte sha512_seedB_data[] = {
6439
    /* EntropyInput (32 bytes) || Nonce (16 bytes) */
6440
    0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
6441
    0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
6442
    0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
6443
    0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
6444
    0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
6445
    0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25
6446
};
6447
static const byte sha512_outputB_data[] = {
6448
    0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
6449
    0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
6450
    0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
6451
    0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
6452
    0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
6453
    0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
6454
    0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
6455
    0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
6456
    0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
6457
    0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
6458
    0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
6459
    0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
6460
    0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
6461
    0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
6462
    0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
6463
    0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
6464
    0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
6465
    0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
6466
    0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
6467
    0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
6468
    0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
6469
    0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
6470
    0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
6471
    0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
6472
    0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
6473
    0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
6474
    0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
6475
    0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
6476
    0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
6477
    0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
6478
    0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
6479
    0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2
6480
};
6481
#endif /* WOLFSSL_DRBG_SHA512 */
6482
6483
6484
static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap,
6485
                                  int devId)
6486
0
{
6487
0
    int ret = 0;
6488
6489
0
#ifdef WOLFSSL_DRBG_SHA512
6490
    /* SHA-512 DRBG health test path */
6491
0
    if (rng->drbgType == WC_DRBG_SHA512) {
6492
    #ifdef WOLFSSL_SMALL_STACK_CACHE
6493
        byte *check512 = rng->health_check_scratch_512;
6494
        DRBG_SHA512_internal* drbg512 = rng->drbg512_scratch;
6495
    #else
6496
0
        WC_DECLARE_VAR(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, 0);
6497
0
        WC_DECLARE_VAR(drbg512, DRBG_SHA512_internal, 1, 0);
6498
6499
0
        WC_ALLOC_VAR_EX(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
6500
0
            heap, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
6501
0
        WC_ALLOC_VAR_EX(drbg512, DRBG_SHA512_internal, 1, heap,
6502
0
            DYNAMIC_TYPE_TMP_BUFFER, WC_DO_NOTHING);
6503
        #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
6504
        if (drbg512 == NULL) {
6505
            WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER);
6506
            return MEMORY_E;
6507
        }
6508
        #endif
6509
0
    #endif
6510
6511
0
        if (reseed) {
6512
            /* Reseed test with NIST CAVP SHA-512 vectors */
6513
0
            ret = wc_RNG_HealthTest_SHA512_ex_internal(
6514
0
                        drbg512, 1, NULL, 0, NULL, 0,
6515
0
                        sha512_seedA_data, sizeof(sha512_seedA_data),
6516
0
                        sha512_reseedSeedA_data,
6517
0
                        sizeof(sha512_reseedSeedA_data),
6518
0
                        NULL, 0, NULL, 0,
6519
0
                        check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
6520
0
                        heap, devId);
6521
0
            if (ret == 0) {
6522
0
                if (ConstantCompare(check512, sha512_outputA_data,
6523
0
                                    RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0)
6524
0
                    ret = DRBG_CONT_FAILURE;
6525
0
            }
6526
0
        }
6527
0
        else {
6528
            /* No-reseed test with NIST CAVP SHA-512 vectors */
6529
0
            ret = wc_RNG_HealthTest_SHA512_ex_internal(
6530
0
                        drbg512, 0, NULL, 0, NULL, 0,
6531
0
                        sha512_seedB_data, sizeof(sha512_seedB_data),
6532
0
                        NULL, 0,
6533
0
                        NULL, 0, NULL, 0,
6534
0
                        check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512,
6535
0
                        heap, devId);
6536
0
            if (ret == 0) {
6537
0
                if (ConstantCompare(check512, sha512_outputB_data,
6538
0
                                    RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0)
6539
0
                    ret = DRBG_CONT_FAILURE;
6540
0
            }
6541
0
        }
6542
6543
0
    #ifndef WOLFSSL_SMALL_STACK_CACHE
6544
0
        WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER);
6545
0
        WC_FREE_VAR_EX(drbg512, heap, DYNAMIC_TYPE_TMP_BUFFER);
6546
0
    #endif
6547
0
        return ret;
6548
0
    }
6549
0
#endif /* WOLFSSL_DRBG_SHA512 */
6550
6551
    /* SHA-256 DRBG health test path (original) */
6552
0
#ifndef NO_SHA256
6553
0
    {
6554
#ifdef WOLFSSL_SMALL_STACK_CACHE
6555
    byte *check = rng->health_check_scratch;
6556
    DRBG_internal* drbg = (DRBG_internal *)rng->drbg_scratch;
6557
#else
6558
0
    WC_DECLARE_VAR(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, 0);
6559
0
    WC_DECLARE_VAR(drbg, DRBG_internal, 1, 0);
6560
6561
0
    (void)rng;
6562
6563
0
    WC_ALLOC_VAR_EX(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, heap,
6564
0
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
6565
0
    WC_ALLOC_VAR_EX(drbg, DRBG_internal, 1, heap,
6566
0
        DYNAMIC_TYPE_TMP_BUFFER, WC_DO_NOTHING);
6567
    #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
6568
    if (drbg == NULL) {
6569
        WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
6570
        return MEMORY_E;
6571
    }
6572
    #endif
6573
0
#endif
6574
6575
0
    if (reseed) {
6576
#ifdef WOLFSSL_USE_FLASHMEM
6577
        byte* seedA = (byte*)XMALLOC(sizeof(seedA_data), heap,
6578
                             DYNAMIC_TYPE_TMP_BUFFER);
6579
        byte* reseedSeedA = (byte*)XMALLOC(sizeof(reseedSeedA_data), heap,
6580
                             DYNAMIC_TYPE_TMP_BUFFER);
6581
        byte* outputA = (byte*)XMALLOC(sizeof(outputA_data), heap,
6582
                             DYNAMIC_TYPE_TMP_BUFFER);
6583
6584
        if (!seedA || !reseedSeedA || !outputA) {
6585
            XFREE(seedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
6586
            XFREE(reseedSeedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
6587
            XFREE(outputA, heap, DYNAMIC_TYPE_TMP_BUFFER);
6588
            ret = MEMORY_E;
6589
        }
6590
        else {
6591
            XMEMCPY_P(seedA, seedA_data, sizeof(seedA_data));
6592
            XMEMCPY_P(reseedSeedA, reseedSeedA_data, sizeof(reseedSeedA_data));
6593
            XMEMCPY_P(outputA, outputA_data, sizeof(outputA_data));
6594
#else
6595
0
        const byte* seedA = seedA_data;
6596
0
        const byte* reseedSeedA = reseedSeedA_data;
6597
0
        const byte* outputA = outputA_data;
6598
0
#endif
6599
0
        ret = wc_RNG_HealthTest_ex_internal(drbg, 1, NULL, 0,
6600
0
                                   seedA, sizeof(seedA_data),
6601
0
                                   reseedSeedA, sizeof(reseedSeedA_data),
6602
0
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
6603
0
                                   heap, devId);
6604
0
        if (ret == 0) {
6605
0
            if (ConstantCompare(check, outputA,
6606
0
                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
6607
0
                ret = DRBG_CONT_FAILURE;
6608
0
        }
6609
6610
#ifdef WOLFSSL_USE_FLASHMEM
6611
            XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6612
            XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6613
            XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6614
        }
6615
#endif
6616
0
    }
6617
0
    else {
6618
#ifdef WOLFSSL_USE_FLASHMEM
6619
        byte* seedB = (byte*)XMALLOC(sizeof(seedB_data), heap,
6620
                             DYNAMIC_TYPE_TMP_BUFFER);
6621
        byte* outputB = (byte*)XMALLOC(sizeof(outputB_data), heap,
6622
                               DYNAMIC_TYPE_TMP_BUFFER);
6623
6624
        if (!seedB || !outputB) {
6625
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
6626
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
6627
            ret = MEMORY_E;
6628
        }
6629
        else {
6630
            XMEMCPY_P(seedB, seedB_data, sizeof(seedB_data));
6631
            XMEMCPY_P(outputB, outputB_data, sizeof(outputB_data));
6632
#else
6633
0
        const byte* seedB = seedB_data;
6634
0
        const byte* outputB = outputB_data;
6635
0
#endif
6636
#if defined(DEBUG_WOLFSSL)
6637
        WOLFSSL_MSG_EX("RNG_HEALTH_TEST_CHECK_SIZE = %d",
6638
                        RNG_HEALTH_TEST_CHECK_SIZE);
6639
        WOLFSSL_MSG_EX("sizeof(seedB_data)         = %d",
6640
                        (int)sizeof(outputB_data));
6641
#endif
6642
0
        ret = wc_RNG_HealthTest_ex_internal(drbg, 0, NULL, 0,
6643
0
                                   seedB, sizeof(seedB_data),
6644
0
                                   NULL, 0,
6645
0
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
6646
0
                                   heap, devId);
6647
0
        if (ret != 0) {
6648
            #if defined(DEBUG_WOLFSSL)
6649
            WOLFSSL_MSG_EX("RNG_HealthTest failed: err = %d", ret);
6650
            #endif
6651
0
        }
6652
0
        else {
6653
0
            ret = ConstantCompare(check, outputB,
6654
0
                                RNG_HEALTH_TEST_CHECK_SIZE);
6655
0
            if (ret != 0) {
6656
                #if defined(DEBUG_WOLFSSL)
6657
                WOLFSSL_MSG_EX("Random ConstantCompare failed: err = %d", ret);
6658
                #endif
6659
0
                ret = DRBG_CONT_FAILURE;
6660
0
            }
6661
0
        }
6662
6663
        /* The previous test cases use a large seed instead of a seed and nonce.
6664
         * seedB is actually from a test case with a seed and nonce, and
6665
         * just concatenates them. The pivot point between seed and nonce is
6666
         * byte 32, feed them into the health test separately. */
6667
0
        if (ret == 0) {
6668
0
            ret = wc_RNG_HealthTest_ex_internal(drbg, 0,
6669
0
                                       seedB + 32, sizeof(seedB_data) - 32,
6670
0
                                       seedB, 32,
6671
0
                                       NULL, 0,
6672
0
                                       check, RNG_HEALTH_TEST_CHECK_SIZE,
6673
0
                                       heap, devId);
6674
0
            if (ret == 0) {
6675
0
                if (ConstantCompare(check, outputB, sizeof(outputB_data)) != 0)
6676
0
                    ret = DRBG_CONT_FAILURE;
6677
0
            }
6678
0
        }
6679
6680
#ifdef WOLFSSL_USE_FLASHMEM
6681
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
6682
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
6683
        }
6684
#endif
6685
0
    }
6686
6687
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
6688
0
    WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
6689
0
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_TMP_BUFFER);
6690
0
#endif
6691
0
    } /* SHA-256 path */
6692
0
#endif /* !NO_SHA256 */
6693
6694
0
    return ret;
6695
0
}
6696
6697
/* ====================================================================== */
6698
/* SHA-512 Health Test API                                                 */
6699
/* ====================================================================== */
6700
#ifdef WOLFSSL_DRBG_SHA512
6701
6702
static int wc_RNG_HealthTest_SHA512_ex_internal(DRBG_SHA512_internal* drbg,
6703
                                  int reseed, const byte* nonce, word32 nonceSz,
6704
                                  const byte* perso, word32 persoSz,
6705
                                  const byte* seedA, word32 seedASz,
6706
                                  const byte* seedB, word32 seedBSz,
6707
                                  const byte* additionalA, word32 additionalASz,
6708
                                  const byte* additionalB, word32 additionalBSz,
6709
                                  byte* output, word32 outputSz,
6710
                                  void* heap, int devId)
6711
0
{
6712
0
    int ret = WC_NO_ERR_TRACE(DRBG_FAILURE);
6713
6714
0
    if (seedA == NULL || output == NULL) {
6715
0
        return BAD_FUNC_ARG;
6716
0
    }
6717
6718
0
    if (reseed != 0 && seedB == NULL) {
6719
0
        return BAD_FUNC_ARG;
6720
0
    }
6721
6722
0
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) {
6723
0
        return BAD_FUNC_ARG;
6724
0
    }
6725
6726
#ifdef WOLFSSL_SMALL_STACK_CACHE
6727
    (void)heap;
6728
    (void)devId;
6729
6730
    if (Hash512_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz,
6731
                          perso, persoSz) != 0) {
6732
        goto exit_rng_ht512;
6733
    }
6734
#else
6735
0
    if (Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
6736
0
                              perso, persoSz, heap, devId) != 0) {
6737
0
        goto exit_rng_ht512;
6738
0
    }
6739
0
#endif
6740
6741
0
    if (reseed) {
6742
0
        if (Hash512_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0) != 0)
6743
0
        {
6744
0
            goto exit_rng_ht512;
6745
0
        }
6746
0
    }
6747
6748
    /* First generate: output discarded per NIST DRBGVS procedure */
6749
0
    if (Hash512_DRBG_Generate(drbg, output, outputSz,
6750
0
                              additionalA, additionalASz) != 0) {
6751
0
        goto exit_rng_ht512;
6752
0
    }
6753
6754
    /* Second generate: this is the actual test output */
6755
0
    if (Hash512_DRBG_Generate(drbg, output, outputSz,
6756
0
                              additionalB, additionalBSz) != 0) {
6757
0
        goto exit_rng_ht512;
6758
0
    }
6759
6760
0
    ret = 0;
6761
6762
0
exit_rng_ht512:
6763
6764
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
6765
0
    if ((Hash512_DRBG_Uninstantiate(drbg) != 0) && (ret == 0)) {
6766
0
        ret = DRBG_FAILURE;
6767
0
    }
6768
0
#endif
6769
6770
0
    return ret;
6771
0
}
6772
6773
6774
/* Extended API with personalization string and additional input
6775
 * for ACVP testing */
6776
int wc_RNG_HealthTest_SHA512_ex(int reseed,
6777
                                const byte* nonce, word32 nonceSz,
6778
                                const byte* persoString, word32 persoStringSz,
6779
                                const byte* seedA, word32 seedASz,
6780
                                const byte* seedB, word32 seedBSz,
6781
                                const byte* additionalA, word32 additionalASz,
6782
                                const byte* additionalB, word32 additionalBSz,
6783
                                byte* output, word32 outputSz,
6784
                                void* heap, int devId)
6785
0
{
6786
0
    int ret = WC_NO_ERR_TRACE(WC_FAILURE);
6787
0
    DRBG_SHA512_internal* drbg;
6788
0
#ifndef WOLFSSL_SMALL_STACK
6789
0
    DRBG_SHA512_internal  drbg_var;
6790
0
#endif
6791
6792
0
    if (seedA == NULL || output == NULL) {
6793
0
        return BAD_FUNC_ARG;
6794
0
    }
6795
6796
0
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) {
6797
0
        return BAD_FUNC_ARG;
6798
0
    }
6799
6800
#ifdef WOLFSSL_SMALL_STACK
6801
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), heap,
6802
        DYNAMIC_TYPE_RNG);
6803
    if (drbg == NULL) {
6804
        return MEMORY_E;
6805
    }
6806
#else
6807
0
    drbg = &drbg_var;
6808
0
#endif
6809
6810
    /* SP 800-90A Sec 10.1.1.2: personalization string is concatenated
6811
     * with entropy during instantiation via Hash_df. */
6812
0
    ret = Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
6813
0
                                   persoString, persoStringSz, heap, devId);
6814
0
    if (ret != 0) {
6815
0
        goto exit_sha512_ex;
6816
0
    }
6817
6818
0
    if (reseed) {
6819
0
        if (seedB != NULL && seedBSz > 0) {
6820
0
            ret = Hash512_DRBG_Reseed(drbg, seedB, seedBSz, NULL, 0);
6821
0
            if (ret != 0) goto exit_sha512_ex;
6822
0
        }
6823
0
    }
6824
6825
    /* First generate (output discarded per NIST procedure) */
6826
0
    ret = Hash512_DRBG_Generate(drbg, output, outputSz,
6827
0
                                additionalA, additionalASz);
6828
0
    if (ret != 0) goto exit_sha512_ex;
6829
6830
    /* Second generate (this is the actual output) */
6831
0
    ret = Hash512_DRBG_Generate(drbg, output, outputSz,
6832
0
                                additionalB, additionalBSz);
6833
6834
0
exit_sha512_ex:
6835
0
    (void)Hash512_DRBG_Uninstantiate(drbg);
6836
6837
#ifdef WOLFSSL_SMALL_STACK
6838
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
6839
#endif
6840
6841
0
    return (ret == DRBG_SUCCESS) ? 0 : -1;
6842
0
}
6843
6844
6845
/* Simple API matching wc_RNG_HealthTest() pattern - entropy+nonce only */
6846
int wc_RNG_HealthTest_SHA512(int reseed,
6847
                             const byte* seedA, word32 seedASz,
6848
                             const byte* seedB, word32 seedBSz,
6849
                             byte* output, word32 outputSz)
6850
0
{
6851
0
    int ret = WC_NO_ERR_TRACE(WC_FAILURE);
6852
0
    DRBG_SHA512_internal* drbg;
6853
0
#ifndef WOLFSSL_SMALL_STACK
6854
0
    DRBG_SHA512_internal  drbg_var;
6855
0
#endif
6856
6857
#ifdef WOLFSSL_SMALL_STACK
6858
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), NULL,
6859
        DYNAMIC_TYPE_RNG);
6860
    if (drbg == NULL) {
6861
        return MEMORY_E;
6862
    }
6863
#else
6864
0
    drbg = &drbg_var;
6865
0
#endif
6866
6867
#ifdef WOLFSSL_SMALL_STACK_CACHE
6868
    ret = Hash512_DRBG_Instantiate(drbg,
6869
                    NULL /* seed */, 0, NULL /* nonce */, 0,
6870
                    NULL, 0, NULL, INVALID_DEVID);
6871
    if (ret == 0)
6872
#endif
6873
0
    {
6874
0
        ret = wc_RNG_HealthTest_SHA512_ex_internal(
6875
0
                drbg, reseed, NULL, 0, NULL, 0,
6876
0
                seedA, seedASz, seedB, seedBSz,
6877
0
                NULL, 0, NULL, 0,
6878
0
                output, outputSz, NULL, INVALID_DEVID);
6879
#ifdef WOLFSSL_SMALL_STACK_CACHE
6880
        Hash512_DRBG_Uninstantiate(drbg);
6881
#endif
6882
0
    }
6883
0
    WC_FREE_VAR_EX(drbg, NULL, DYNAMIC_TYPE_RNG);
6884
6885
0
    if (ret > 0) {
6886
        /* Translate protocol-domain codes at the public boundary; negative
6887
         * codes (MEMORY_E, BAD_FUNC_ARG) pass verbatim. */
6888
0
        ret = WC_FAILURE;
6889
0
    }
6890
0
    return ret;
6891
0
}
6892
6893
#endif /* WOLFSSL_DRBG_SHA512 */
6894
6895
#if !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \
6896
    (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
6897
/* Extended SHA-256 Hash_DRBG health test per SP 800-90A.
6898
 * Supports flexible output sizes, prediction resistance, personalization
6899
 * strings, and additional input.
6900
 *
6901
 * predResistance=0: Instantiate(entropyA, nonce, perso) ->
6902
 *                   Reseed(entropyB, additionalReseed) ->
6903
 *                   Gen1(additionalA, discard) -> Gen2(additionalB, keep)
6904
 * predResistance=1: Instantiate(entropyA, nonce, perso) ->
6905
 *                   Reseed(entropyB, additionalA)+Gen1(NULL, discard) ->
6906
 *                   Reseed(entropyC, additionalB)+Gen2(NULL, keep)
6907
 */
6908
int wc_RNG_HealthTest_SHA256_ex(
6909
    int predResistance,
6910
    const byte* nonce, word32 nonceSz,
6911
    const byte* persoString, word32 persoStringSz,
6912
    const byte* entropyA, word32 entropyASz,
6913
    const byte* entropyB, word32 entropyBSz,
6914
    const byte* entropyC, word32 entropyCsz,
6915
    const byte* additionalA, word32 additionalASz,
6916
    const byte* additionalB, word32 additionalBSz,
6917
    const byte* additionalReseed, word32 additionalReseedSz,
6918
    byte* output, word32 outputSz,
6919
    void* heap, int devId)
6920
0
{
6921
0
    int ret;
6922
0
    DRBG_internal* drbg;
6923
0
#ifndef WOLFSSL_SMALL_STACK
6924
0
    DRBG_internal  drbg_var;
6925
0
#endif
6926
6927
0
    if (entropyA == NULL || output == NULL || outputSz == 0) {
6928
0
        return BAD_FUNC_ARG;
6929
0
    }
6930
6931
#ifdef WOLFSSL_SMALL_STACK
6932
    drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap,
6933
        DYNAMIC_TYPE_RNG);
6934
    if (drbg == NULL) {
6935
        return MEMORY_E;
6936
    }
6937
#else
6938
0
    drbg = &drbg_var;
6939
0
#endif
6940
6941
    /* Instantiate with entropy, nonce, personalization string */
6942
0
    ret = Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
6943
0
                                persoString, persoStringSz, heap, devId);
6944
0
    if (ret != 0) goto exit_sha256_ex;
6945
6946
0
    if (predResistance) {
6947
        /* Prediction resistance mode per SP 800-90A 9.3.1:
6948
         * additional_input is passed to Reseed, Generate gets NULL */
6949
6950
        /* Reseed 1 with additionalA, then Generate 1 with NULL (discard) */
6951
0
        if (entropyB != NULL && entropyBSz > 0) {
6952
0
            ret = Hash256_DRBG_Reseed(drbg, entropyB, entropyBSz,
6953
0
                                      additionalA, additionalASz);
6954
0
            if (ret != 0) goto exit_sha256_ex;
6955
0
        }
6956
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0);
6957
0
        if (ret != 0) goto exit_sha256_ex;
6958
6959
        /* Reseed 2 with additionalB, then Generate 2 with NULL (keep) */
6960
0
        if (entropyC != NULL && entropyCsz > 0) {
6961
0
            ret = Hash256_DRBG_Reseed(drbg, entropyC, entropyCsz,
6962
0
                                      additionalB, additionalBSz);
6963
0
            if (ret != 0) goto exit_sha256_ex;
6964
0
        }
6965
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz, NULL, 0);
6966
0
    }
6967
0
    else {
6968
        /* Standard mode: explicit reseed, then two generates */
6969
0
        if (entropyB != NULL && entropyBSz > 0) {
6970
0
            ret = Hash256_DRBG_Reseed(drbg, entropyB, entropyBSz,
6971
0
                                      additionalReseed, additionalReseedSz);
6972
0
            if (ret != 0) goto exit_sha256_ex;
6973
0
        }
6974
6975
        /* Generate 1 (output discarded per NIST DRBGVS procedure) */
6976
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz,
6977
0
                                 additionalA, additionalASz);
6978
0
        if (ret != 0) goto exit_sha256_ex;
6979
6980
        /* Generate 2 (this is the actual test output) */
6981
0
        ret = Hash_DRBG_Generate(drbg, output, outputSz,
6982
0
                                 additionalB, additionalBSz);
6983
0
    }
6984
6985
0
exit_sha256_ex:
6986
0
    (void)Hash_DRBG_Uninstantiate(drbg);
6987
6988
#ifdef WOLFSSL_SMALL_STACK
6989
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
6990
#endif
6991
6992
0
    return ret;
6993
0
}
6994
#endif /* !NO_SHA256 && !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */
6995
6996
6997
#ifdef WOLFSSL_DRBG_SHA512
6998
/* Extended SHA-512 Hash_DRBG health test per SP 800-90A.
6999
 * Supports flexible output sizes and prediction resistance mode.
7000
 *
7001
 * Per SP 800-90A Section 9.3.1, when prediction resistance is requested,
7002
 * the additional_input is consumed by the Reseed step and the subsequent
7003
 * Generate uses NULL additional_input.
7004
 *
7005
 * predResistance=0: Instantiate ->
7006
 *                   Reseed(entropyB, additionalReseed) ->
7007
 *                   Gen1(additionalA, discard) -> Gen2(additionalB, keep)
7008
 * predResistance=1: Instantiate ->
7009
 *                   Reseed(entropyB, additionalA)+Gen1(NULL, discard) ->
7010
 *                   Reseed(entropyC, additionalB)+Gen2(NULL, keep)
7011
 */
7012
int wc_RNG_HealthTest_SHA512_ex2(
7013
    int predResistance,
7014
    const byte* nonce, word32 nonceSz,
7015
    const byte* persoString, word32 persoStringSz,
7016
    const byte* entropyA, word32 entropyASz,
7017
    const byte* entropyB, word32 entropyBSz,
7018
    const byte* entropyC, word32 entropyCsz,
7019
    const byte* additionalA, word32 additionalASz,
7020
    const byte* additionalB, word32 additionalBSz,
7021
    const byte* additionalReseed, word32 additionalReseedSz,
7022
    byte* output, word32 outputSz,
7023
    void* heap, int devId)
7024
0
{
7025
0
    int ret;
7026
0
    DRBG_SHA512_internal* drbg;
7027
0
#ifndef WOLFSSL_SMALL_STACK
7028
0
    DRBG_SHA512_internal  drbg_var;
7029
0
#endif
7030
7031
0
    if (entropyA == NULL || output == NULL || outputSz == 0) {
7032
0
        return BAD_FUNC_ARG;
7033
0
    }
7034
7035
#ifdef WOLFSSL_SMALL_STACK
7036
    drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), heap,
7037
        DYNAMIC_TYPE_RNG);
7038
    if (drbg == NULL) {
7039
        return MEMORY_E;
7040
    }
7041
#else
7042
0
    drbg = &drbg_var;
7043
0
#endif
7044
7045
    /* Instantiate with entropy, nonce, personalization string */
7046
0
    ret = Hash512_DRBG_Instantiate(drbg, entropyA, entropyASz, nonce, nonceSz,
7047
0
                                   persoString, persoStringSz, heap, devId);
7048
0
    if (ret != 0) goto exit_sha512_ex2;
7049
7050
0
    if (predResistance) {
7051
        /* Prediction resistance mode per SP 800-90A 9.3.1:
7052
         * additional_input is passed to Reseed, Generate gets NULL */
7053
7054
        /* Reseed 1 with additionalA, then Generate 1 with NULL (discard) */
7055
0
        if (entropyB != NULL && entropyBSz > 0) {
7056
0
            ret = Hash512_DRBG_Reseed(drbg, entropyB, entropyBSz,
7057
0
                                      additionalA, additionalASz);
7058
0
            if (ret != 0) goto exit_sha512_ex2;
7059
0
        }
7060
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz, NULL, 0);
7061
0
        if (ret != 0) goto exit_sha512_ex2;
7062
7063
        /* Reseed 2 with additionalB, then Generate 2 with NULL (keep) */
7064
0
        if (entropyC != NULL && entropyCsz > 0) {
7065
0
            ret = Hash512_DRBG_Reseed(drbg, entropyC, entropyCsz,
7066
0
                                      additionalB, additionalBSz);
7067
0
            if (ret != 0) goto exit_sha512_ex2;
7068
0
        }
7069
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz, NULL, 0);
7070
0
    }
7071
0
    else {
7072
        /* Standard mode: explicit reseed, then two generates */
7073
0
        if (entropyB != NULL && entropyBSz > 0) {
7074
0
            ret = Hash512_DRBG_Reseed(drbg, entropyB, entropyBSz,
7075
0
                                      additionalReseed, additionalReseedSz);
7076
0
            if (ret != 0) goto exit_sha512_ex2;
7077
0
        }
7078
7079
        /* Generate 1 (output discarded per NIST DRBGVS procedure) */
7080
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz,
7081
0
                                    additionalA, additionalASz);
7082
0
        if (ret != 0) goto exit_sha512_ex2;
7083
7084
        /* Generate 2 (this is the actual test output) */
7085
0
        ret = Hash512_DRBG_Generate(drbg, output, outputSz,
7086
0
                                    additionalB, additionalBSz);
7087
0
    }
7088
7089
0
exit_sha512_ex2:
7090
0
    (void)Hash512_DRBG_Uninstantiate(drbg);
7091
7092
#ifdef WOLFSSL_SMALL_STACK
7093
    XFREE(drbg, heap, DYNAMIC_TYPE_RNG);
7094
#endif
7095
7096
0
    return (ret == DRBG_SUCCESS) ? 0 : -1;
7097
0
}
7098
7099
#endif /* WOLFSSL_DRBG_SHA512 */
7100
7101
#endif /* HAVE_HASHDRBG */
7102
7103
7104
#ifdef HAVE_WNR
7105
7106
/*
7107
 * Init global Whitewood netRandom context
7108
 * Returns 0 on success, negative on error
7109
 */
7110
int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
7111
{
7112
    int ret = 0;
7113
7114
    if (configFile == NULL || timeout < 0)
7115
        return BAD_FUNC_ARG;
7116
7117
#ifndef WOLFSSL_MUTEX_INITIALIZER
7118
    ret = wc_local_InitMutexOnce(&wnr_mutex, &wnr_mutex_inited);
7119
    if (ret != 0) {
7120
        WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
7121
        return ret;
7122
    }
7123
#endif
7124
7125
    if (wnr_inited > 0) {
7126
        WOLFSSL_MSG("netRandom context already created, skipping");
7127
        return 0;
7128
    }
7129
7130
    if (wc_LockMutex(&wnr_mutex) != 0) {
7131
        WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
7132
        return BAD_MUTEX_E;
7133
    }
7134
7135
    /* store entropy timeout */
7136
    wnr_timeout = timeout;
7137
7138
    /* create global wnr_context struct */
7139
    if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
7140
        WOLFSSL_MSG("Error creating global netRandom context");
7141
        ret = RNG_FAILURE_E;
7142
        goto out;
7143
    }
7144
7145
    /* load config file */
7146
    if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
7147
        WOLFSSL_MSG("Error loading config file into netRandom context");
7148
        wnr_destroy(wnr_ctx);
7149
        wnr_ctx = NULL;
7150
        ret = RNG_FAILURE_E;
7151
        goto out;
7152
    }
7153
7154
    /* create/init polling mechanism */
7155
    if (wnr_poll_create() != WNR_ERROR_NONE) {
7156
        WOLFSSL_MSG("Error initializing netRandom polling mechanism");
7157
        wnr_destroy(wnr_ctx);
7158
        wnr_ctx = NULL;
7159
        ret = RNG_FAILURE_E;
7160
        goto out;
7161
    }
7162
7163
    /* validate config, set HMAC callback (optional) */
7164
    if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
7165
        WOLFSSL_MSG("Error setting up netRandom context");
7166
        wnr_destroy(wnr_ctx);
7167
        wnr_ctx = NULL;
7168
        wnr_poll_destroy();
7169
        ret = RNG_FAILURE_E;
7170
        goto out;
7171
    }
7172
7173
    wnr_inited = 1;
7174
7175
out:
7176
7177
    wc_UnLockMutex(&wnr_mutex);
7178
7179
    return ret;
7180
}
7181
7182
/*
7183
 * Free global Whitewood netRandom context
7184
 * Returns 0 on success, negative on error
7185
 */
7186
int wc_FreeNetRandom(void)
7187
{
7188
    if (wnr_inited > 0) {
7189
7190
        if (wc_LockMutex(&wnr_mutex) != 0) {
7191
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
7192
            return BAD_MUTEX_E;
7193
        }
7194
7195
        if (wnr_ctx != NULL) {
7196
            wnr_destroy(wnr_ctx);
7197
            wnr_ctx = NULL;
7198
        }
7199
        wnr_poll_destroy();
7200
7201
        wc_UnLockMutex(&wnr_mutex);
7202
7203
#ifndef WOLFSSL_MUTEX_INITIALIZER
7204
        wc_FreeMutex(&wnr_mutex);
7205
        WOLFSSL_ATOMIC_STORE(wnr_mutex_inited, 0);
7206
#endif
7207
7208
        wnr_inited = 0;
7209
    }
7210
7211
    return 0;
7212
}
7213
7214
#endif /* HAVE_WNR */
7215
7216
7217
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
7218
    defined(HAVE_AMD_RDSEED)
7219
7220
#ifdef WOLFSSL_ASYNC_CRYPT
7221
    /* need more retries if multiple cores */
7222
    #define INTELRD_RETRY (32 * 8)
7223
#else
7224
    #define INTELRD_RETRY 32
7225
#endif
7226
7227
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
7228
7229
#ifndef USE_INTEL_INTRINSICS
7230
7231
    /* return 0 on success */
7232
    static WC_INLINE int IntelRDseed64(word64* seed)
7233
    {
7234
        unsigned char ok;
7235
7236
        __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
7237
        return (ok) ? 0 : -1;
7238
    }
7239
7240
#else /* USE_INTEL_INTRINSICS */
7241
    /* The compiler Visual Studio uses does not allow inline assembly.
7242
     * It does allow for Intel intrinsic functions. */
7243
7244
    /* return 0 on success */
7245
# ifdef __GNUC__
7246
    __attribute__((target("rdseed")))
7247
# endif
7248
    static WC_INLINE int IntelRDseed64(word64* seed)
7249
    {
7250
        int ok;
7251
7252
        ok = _rdseed64_step((unsigned long long*) seed);
7253
        return (ok) ? 0 : -1;
7254
    }
7255
7256
#endif /* USE_INTEL_INTRINSICS */
7257
7258
/* return 0 on success */
7259
static WC_INLINE int IntelRDseed64_r(word64* rnd)
7260
{
7261
    int i;
7262
    for (i = 0; i < INTELRD_RETRY; i++) {
7263
        if (IntelRDseed64(rnd) == 0)
7264
            return 0;
7265
    }
7266
    return NOT_READY_E;
7267
}
7268
7269
/* return 0 on success */
7270
static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
7271
{
7272
    int ret = 0;
7273
    word64 rndTmp;
7274
    static int rdseed_sanity_status = 0;
7275
    word64 rndTmpLocal = 0;
7276
7277
    (void)os;
7278
7279
    if (!IS_INTEL_RDSEED(intel_flags))
7280
        return WC_HW_E;
7281
7282
    /* Note, access to rdseed_sanity_status is benignly racey on multithreaded
7283
     * targets.
7284
     */
7285
    if (rdseed_sanity_status == 0) {
7286
        word64 sanity_word1 = 0, sanity_word2 = 0;
7287
7288
        ret = IntelRDseed64_r(&sanity_word1);
7289
        if (ret != 0)
7290
            return ret;
7291
7292
        ret = IntelRDseed64_r(&sanity_word2);
7293
        if (ret != 0)
7294
            return ret;
7295
7296
        if (sanity_word1 == sanity_word2) {
7297
            ret = IntelRDseed64_r(&sanity_word1);
7298
            if (ret != 0)
7299
                return ret;
7300
7301
            if (sanity_word1 == sanity_word2) {
7302
#ifdef WC_VERBOSE_RNG
7303
                WOLFSSL_DEBUG_PRINTF(
7304
                    "WARNING: disabling RDSEED due to repeating word 0x%lx -- "
7305
                    "check CPU microcode version.", sanity_word2);
7306
#endif
7307
                rdseed_sanity_status = -1;
7308
                return WC_HW_E;
7309
            }
7310
        }
7311
7312
        rdseed_sanity_status = 1;
7313
    }
7314
    else if (rdseed_sanity_status < 0) {
7315
        return WC_HW_E;
7316
    }
7317
7318
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
7319
                                                output += sizeof(word64)) {
7320
        ret = IntelRDseed64_r(&rndTmpLocal);
7321
        if (ret != 0) {
7322
            break;
7323
        }
7324
        writeUnalignedWord64(output, rndTmpLocal);
7325
    }
7326
7327
    ForceZero(&rndTmpLocal, sizeof(rndTmpLocal));
7328
    if (ret != 0) {
7329
        return ret;
7330
    }
7331
7332
    if (sz == 0)
7333
        return 0;
7334
7335
    /* handle unaligned remainder */
7336
    ret = IntelRDseed64_r(&rndTmp);
7337
    if (ret != 0)
7338
        return ret;
7339
7340
#ifdef WOLFSSL_CHECK_MEM_ZERO
7341
    wc_MemZero_Add("wc_GenerateSeed rndTmp", &rndTmp, sizeof(rndTmp));
7342
#endif
7343
    XMEMCPY(output, &rndTmp, sz);
7344
    ForceZero(&rndTmp, sizeof(rndTmp));
7345
#ifdef WOLFSSL_CHECK_MEM_ZERO
7346
    wc_MemZero_Check(&rndTmp, sizeof(rndTmp));
7347
#endif
7348
7349
    return 0;
7350
}
7351
7352
#endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
7353
7354
#ifdef HAVE_INTEL_RDRAND
7355
7356
#ifndef USE_INTEL_INTRINSICS
7357
7358
/* return 0 on success */
7359
static WC_INLINE int IntelRDrand64(word64 *rnd)
7360
{
7361
    unsigned char ok;
7362
7363
    __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
7364
7365
    return (ok) ? 0 : -1;
7366
}
7367
7368
#else /* USE_INTEL_INTRINSICS */
7369
    /* The compiler Visual Studio uses does not allow inline assembly.
7370
     * It does allow for Intel intrinsic functions. */
7371
7372
/* return 0 on success */
7373
# ifdef __GNUC__
7374
__attribute__((target("rdrnd")))
7375
# endif
7376
static WC_INLINE int IntelRDrand64(word64 *rnd)
7377
{
7378
    int ok;
7379
7380
    ok = _rdrand64_step((unsigned long long*) rnd);
7381
7382
    return (ok) ? 0 : -1;
7383
}
7384
7385
#endif /* USE_INTEL_INTRINSICS */
7386
7387
/* return 0 on success */
7388
static WC_INLINE int IntelRDrand64_r(word64 *rnd)
7389
{
7390
    int i;
7391
    for (i = 0; i < INTELRD_RETRY; i++) {
7392
        if (IntelRDrand64(rnd) == 0)
7393
            return 0;
7394
    }
7395
    return -1;
7396
}
7397
7398
/* return 0 on success */
7399
static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
7400
{
7401
    word64 rndTmp;
7402
    int ret = 0;
7403
    word64 rndTmpLocal = 0;
7404
7405
    (void)os;
7406
7407
    if (!IS_INTEL_RDRAND(intel_flags))
7408
        return -1;
7409
7410
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
7411
                                                output += sizeof(word64)) {
7412
        ret = IntelRDrand64_r(&rndTmpLocal);
7413
        if (ret != 0) {
7414
            break;
7415
        }
7416
        writeUnalignedWord64(output, rndTmpLocal);
7417
    }
7418
7419
    ForceZero(&rndTmpLocal, sizeof(rndTmpLocal));
7420
    if (ret != 0) {
7421
        return ret;
7422
    }
7423
7424
    if (sz == 0)
7425
        return 0;
7426
7427
    /* handle unaligned remainder */
7428
    ret = IntelRDrand64_r(&rndTmp);
7429
    if (ret != 0)
7430
        return ret;
7431
7432
    XMEMCPY(output, &rndTmp, sz);
7433
    ForceZero(&rndTmp, sizeof(rndTmp));
7434
7435
    return 0;
7436
}
7437
7438
#endif /* HAVE_INTEL_RDRAND */
7439
#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
7440
7441
7442
#ifdef WOLFSSL_NOISE_SRC
7443
7444
/* Generic SP800-90B noise source.  Configuration struct and API:
7445
 * wolfssl/wolfcrypt/random.h.
7446
 *
7447
 * Entropy model.  A port supplies raw, unconditioned octets through one
7448
 * callback.  Each raw bit is credited hmin/100 bits of min-entropy, so a
7449
 * full-entropy output octet needs 8 / (hmin/100) raw bits, and margin
7450
 * oversamples on top of that; WC_NOISE_RAW_PER_SRC() turns the two into the
7451
 * raw octets gathered per conditioner chunk.  Only source 0 is budgeted - any
7452
 * further source is hashed in as defence in depth, and extra hash input can
7453
 * never subtract entropy.
7454
 *
7455
 * Every gathered octet passes the 4.4.1 Repetition Count Test and the 4.4.2
7456
 * Adaptive Proportion Test before reaching the conditioner, and _Init() runs
7457
 * the 4.3 startup test over startupOctets per source first.  A failure is
7458
 * latched: 4.3/4.4 want a persistent failure state, not a transparent retry,
7459
 * because a source that trips and then passes is exactly what continuous
7460
 * testing exists to catch.  Only _Free() clears it.
7461
 *
7462
 * Only test verdicts latch - the health tests and the _SelfTest() liveness
7463
 * checks.  An error from the sample callback propagates unlatched and stays
7464
 * retryable: it says the hardware did not answer, not that the noise is bad.
7465
 * Either way no output is produced.
7466
 *
7467
 * Latching is also limited to the credited source.  Source 0 carries the whole
7468
 * budget, so its failure fails closed.  Sources 1.. are unaccounted extra hash
7469
 * input, and the cutoffs are derived for source 0's assumed min-entropy rather
7470
 * than theirs, so one of them tripping is not evidence the seed is weak - it is
7471
 * dropped for the life of the instance (recorded in src->degraded) and stops
7472
 * contributing.  Output stays fully seeded because the budget never counted
7473
 * it, and a source the budget ignores cannot deny service.
7474
 *
7475
 * Cutoffs belong to the caller and must match the assumed hmin, or they either
7476
 * never trip or trip constantly.  For H bits of min-entropy per octet at
7477
 * alpha = 2^-30: RCT C = 1 + ceil(30/H), APT C = 1 + CRITBINOM(W, 2^-H,
7478
 * 1-alpha).
7479
 *
7480
 * No locking.  The instance is caller-owned state, so a port sharing one
7481
 * across threads provides its own mutual exclusion. */
7482
7483
#ifdef NO_SHA256
7484
    #error "WOLFSSL_NOISE_SRC conditions with SHA-256; do not set NO_SHA256"
7485
#endif
7486
#if WC_NOISE_CHUNK_SZ != WC_SHA256_DIGEST_SIZE
7487
    #error "WC_NOISE_CHUNK_SZ must match WC_SHA256_DIGEST_SIZE"
7488
#endif
7489
7490
/* len raw octets from one source.  No health testing - callers that keep the
7491
 * data run NoiseSrc_HealthTest() over it. */
7492
static int NoiseSrc_Gather(wc_NoiseSrc* src, byte* out, word32 len, int srcIdx)
7493
{
7494
    word32 i;
7495
    int ret;
7496
7497
    for (i = 0; i < len; i++) {
7498
        ret = src->sampleCb(src->ctx, srcIdx, &out[i]);
7499
        if (ret != 0) {
7500
            return ret;
7501
        }
7502
        /* The contract is raw octets, but where CHAR_BIT != 8 a callback can
7503
         * legally leave bits above 0xFF in the cell.  Mask here so the
7504
         * conditioner sees exactly what the health tests scored - they mask
7505
         * already - and no high bits leak into the hash. */
7506
        out[i] = WC_OCTET(out[i]);
7507
    }
7508
7509
    return 0;
7510
}
7511
7512
/* SP800-90B 4.4.1 RCT and 4.4.2 APT over every octet drawn from a source.
7513
 * Returns at the offending sample so the rest of the buffer cannot scrub the
7514
 * state that detected it, and latches the failure. */
7515
static int NoiseSrc_HealthTest(wc_NoiseSrc* src, const byte* buf, word32 len,
7516
                               int srcIdx)
7517
{
7518
    wc_NoiseHealth* st;
7519
    word32 i;
7520
    word16 s;
7521
7522
    if (srcIdx < 0 || srcIdx >= (int)src->numSrc) {
7523
        return BAD_FUNC_ARG;
7524
    }
7525
    st = &src->health[srcIdx];
7526
7527
    for (i = 0; i < len; i++) {
7528
        s = (word16)WC_OCTET(buf[i]);
7529
7530
        if (!st->started) {
7531
            st->started  = 1;
7532
            st->rctLast  = s;
7533
            st->rctCount = 1;
7534
            st->aptRef   = s;
7535
            st->aptCount = 1;
7536
            st->aptPos   = 1;
7537
            continue;
7538
        }
7539
7540
        if (s == st->rctLast) {
7541
            st->rctCount++;
7542
            if (st->rctCount >= src->rctCutoff) {
7543
                if (srcIdx == 0) {
7544
                    src->failed = ENTROPY_RT_E;
7545
                }
7546
                return ENTROPY_RT_E;
7547
            }
7548
        }
7549
        else {
7550
            st->rctLast  = s;
7551
            st->rctCount = 1;
7552
        }
7553
7554
        if (st->aptPos >= src->aptWindow) {
7555
            st->aptRef   = s;
7556
            st->aptCount = 1;
7557
            st->aptPos   = 1;
7558
        }
7559
        else {
7560
            if (s == st->aptRef) {
7561
                st->aptCount++;
7562
                if (st->aptCount >= src->aptCutoff) {
7563
                    if (srcIdx == 0) {
7564
                        src->failed = ENTROPY_APT_E;
7565
                    }
7566
                    return ENTROPY_APT_E;
7567
                }
7568
            }
7569
            st->aptPos++;
7570
        }
7571
    }
7572
7573
    return 0;
7574
}
7575
7576
int wc_NoiseSrc_Init(wc_NoiseSrc* src)
7577
{
7578
    word32 done;
7579
    word32 take;
7580
    word32 need;
7581
    int i;
7582
    int ret;
7583
7584
    if (src == NULL) {
7585
        return BAD_FUNC_ARG;
7586
    }
7587
    if (src->failed != 0) {
7588
        return src->failed;
7589
    }
7590
    if (src->inited) {
7591
        return 0;
7592
    }
7593
7594
    if (src->sampleCb == NULL || src->tag == NULL || src->work == NULL) {
7595
        return BAD_FUNC_ARG;
7596
    }
7597
    if (src->numSrc < 1 || src->numSrc > WC_NOISE_SRC_MAX) {
7598
        return BAD_FUNC_ARG;
7599
    }
7600
    if (src->hmin < 1 || src->hmin > 100 || src->margin < 1) {
7601
        return BAD_FUNC_ARG;
7602
    }
7603
    if (src->rctCutoff < 2 || src->aptCutoff < 2 || src->aptWindow < 2) {
7604
        return BAD_FUNC_ARG;
7605
    }
7606
    /* Below one APT window the startup pass never exercises that test. */
7607
    if (src->startupOctets < (word32)src->aptWindow) {
7608
        return BAD_FUNC_ARG;
7609
    }
7610
7611
    src->rawPerSrc = WC_NOISE_RAW_PER_SRC(src->hmin, src->margin);
7612
    need = src->rawPerSrc * (word32)src->numSrc;
7613
    if (src->rawPerSrc == 0 || src->workSz < need) {
7614
        return BUFFER_E;
7615
    }
7616
7617
    XMEMSET(src->health, 0, sizeof(src->health));
7618
    src->chunkCtr = 0;
7619
    src->degraded = 0;
7620
7621
    /* SP800-90B 4.3: push startupOctets per source through the continuous
7622
     * tests - more than one APT window - before releasing anything. */
7623
    for (i = 0; i < (int)src->numSrc; i++) {
7624
        for (done = 0; done < src->startupOctets; done += take) {
7625
            take = src->startupOctets - done;
7626
            if (take > src->rawPerSrc) {
7627
                take = src->rawPerSrc;
7628
            }
7629
            /* Sampler errors and test verdicts are handled differently, so
7630
             * keep them apart: a callback error means the hardware did not
7631
             * answer and stays retryable for every source, while only a test
7632
             * verdict drops or latches. */
7633
            ret = NoiseSrc_Gather(src, src->work, take, i);
7634
            if (ret != 0) {
7635
                ForceZero(src->work, src->workSz);
7636
                return ret;
7637
            }
7638
            ret = NoiseSrc_HealthTest(src, src->work, take, i);
7639
            if (ret != 0) {
7640
                if (i == 0) {
7641
                    ForceZero(src->work, src->workSz);
7642
                    return ret;   /* credited source: fail closed */
7643
                }
7644
                /* Uncredited: drop it and keep going - see the latch policy
7645
                 * note at the top of this module. */
7646
                src->degraded |= (word16)(1U << i);
7647
                ret = 0;
7648
                break;
7649
            }
7650
        }
7651
    }
7652
7653
    ForceZero(src->work, src->workSz);
7654
    src->inited = 1;
7655
    return 0;
7656
}
7657
7658
void wc_NoiseSrc_Free(wc_NoiseSrc* src)
7659
{
7660
    if (src == NULL) {
7661
        return;
7662
    }
7663
7664
    if (src->work != NULL && src->workSz > 0) {
7665
        ForceZero(src->work, src->workSz);
7666
    }
7667
    XMEMSET(src->health, 0, sizeof(src->health));
7668
    src->chunkCtr = 0;
7669
    src->failed   = 0;
7670
    src->degraded = 0;
7671
    src->inited   = 0;
7672
}
7673
7674
int wc_NoiseSrc_GetRaw(wc_NoiseSrc* src, byte* output, word32 len, int srcIdx)
7675
{
7676
    int ret;
7677
7678
    if (src == NULL || output == NULL) {
7679
        return BAD_FUNC_ARG;
7680
    }
7681
    /* Before _Init(): numSrc is caller configuration, so a bad index need not
7682
     * pay for the startup test or burn hardware entropy first. */
7683
    if (srcIdx < 0 || srcIdx >= (int)src->numSrc) {
7684
        return BAD_FUNC_ARG;
7685
    }
7686
    if (src->failed != 0) {
7687
        return src->failed;
7688
    }
7689
7690
    ret = wc_NoiseSrc_Init(src);
7691
    if (ret != 0) {
7692
        return ret;
7693
    }
7694
7695
    ret = NoiseSrc_Gather(src, output, len, srcIdx);
7696
    if (ret != 0) {
7697
        ForceZero(output, len);
7698
    }
7699
    return ret;
7700
}
7701
7702
int wc_NoiseSrc_GenerateSeed(wc_NoiseSrc* src, byte* output, word32 sz)
7703
{
7704
#ifdef WOLFSSL_SMALL_STACK
7705
    wc_Sha256* sha = NULL;
7706
#else
7707
    wc_Sha256 sha[1];
7708
#endif
7709
    byte digest[WC_NOISE_CHUNK_SZ];
7710
    byte ctrBuf[4];
7711
    byte* raw;
7712
    byte* outStart;
7713
    word32 outLen;
7714
    word32 take;
7715
    word16 contributed;
7716
    int i;
7717
    int ret;
7718
7719
    if (src == NULL || output == NULL) {
7720
        return BAD_FUNC_ARG;
7721
    }
7722
    if (sz == 0) {
7723
        return 0;
7724
    }
7725
    if (src->failed != 0) {
7726
        return src->failed;
7727
    }
7728
7729
    /* Kept so a mid-way failure can wipe what already landed: no caller
7730
     * should ever see a partially-filled seed buffer. */
7731
    outStart = output;
7732
    outLen   = sz;
7733
7734
    XMEMSET(digest, 0, sizeof(digest));
7735
7736
    ret = wc_NoiseSrc_Init(src);
7737
    if (ret != 0) {
7738
        return ret;
7739
    }
7740
7741
#ifdef WOLFSSL_SMALL_STACK
7742
    sha = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER);
7743
    if (sha == NULL) {
7744
        return MEMORY_E;
7745
    }
7746
#endif
7747
7748
    while (sz > 0) {
7749
        contributed = 0;
7750
        for (i = 0; i < (int)src->numSrc; i++) {
7751
            if ((src->degraded & (word16)(1U << i)) != 0) {
7752
                continue;   /* uncredited source already dropped */
7753
            }
7754
            raw = src->work + ((word32)i * src->rawPerSrc);
7755
7756
            /* A sampler error propagates for any source and is retryable;
7757
             * only a health-test verdict drops or latches. */
7758
            ret = NoiseSrc_Gather(src, raw, src->rawPerSrc, i);
7759
            if (ret != 0) {
7760
                goto out;
7761
            }
7762
            ret = NoiseSrc_HealthTest(src, raw, src->rawPerSrc, i);
7763
            if (ret != 0) {
7764
                if (i == 0) {
7765
                    goto out;  /* fail closed; HealthTest latched src->failed */
7766
                }
7767
                src->degraded |= (word16)(1U << i);
7768
                ret = 0;
7769
                continue;
7770
            }
7771
            contributed |= (word16)(1U << i);
7772
        }
7773
7774
        ret = wc_InitSha256(sha);
7775
        if (ret != 0) {
7776
            ForceZero(sha, sizeof(*sha));
7777
            goto out;
7778
        }
7779
7780
        src->chunkCtr++;
7781
        ctrBuf[0] = WC_OCTET(src->chunkCtr >> 24);
7782
        ctrBuf[1] = WC_OCTET(src->chunkCtr >> 16);
7783
        ctrBuf[2] = WC_OCTET(src->chunkCtr >> 8);
7784
        ctrBuf[3] = WC_OCTET(src->chunkCtr);
7785
7786
        ret = wc_Sha256Update(sha, (const byte*)src->tag,
7787
                              (word32)XSTRLEN(src->tag));
7788
        if (ret == 0) {
7789
            ret = wc_Sha256Update(sha, ctrBuf, (word32)sizeof(ctrBuf));
7790
        }
7791
        for (i = 0; (ret == 0) && (i < (int)src->numSrc); i++) {
7792
            if ((contributed & (word16)(1U << i)) == 0) {
7793
                continue;   /* not gathered this chunk - never hash stale data */
7794
            }
7795
            raw = src->work + ((word32)i * src->rawPerSrc);
7796
            ret = wc_Sha256Update(sha, raw, src->rawPerSrc);
7797
        }
7798
        if (ret == 0) {
7799
            ret = wc_Sha256Final(sha, digest);
7800
        }
7801
        wc_Sha256Free(sha);
7802
        ForceZero(sha, sizeof(*sha));
7803
        if (ret != 0) {
7804
            goto out;
7805
        }
7806
7807
        take = (sz < (word32)WC_NOISE_CHUNK_SZ) ? sz
7808
                                                : (word32)WC_NOISE_CHUNK_SZ;
7809
        XMEMCPY(output, digest, take);
7810
        output += take;
7811
        sz -= take;
7812
    }
7813
7814
out:
7815
    if (ret != 0) {
7816
        ForceZero(outStart, outLen);
7817
    }
7818
    ForceZero(digest, sizeof(digest));
7819
    ForceZero(src->work, src->workSz);
7820
#ifdef WOLFSSL_SMALL_STACK
7821
    XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
7822
#endif
7823
    return ret;
7824
}
7825
7826
int wc_NoiseSrc_SelfTest(wc_NoiseSrc* src)
7827
{
7828
    /* Tests RAW noise, not conditioned seeds: the hashed chunk counter makes
7829
     * two GenerateSeed() outputs differ even with every source dead. */
7830
    byte* a;
7831
    byte* b;
7832
    word32 len;
7833
    word32 i;
7834
    byte diff;
7835
    int s;
7836
    int ret;
7837
7838
    if (src == NULL) {
7839
        return BAD_FUNC_ARG;
7840
    }
7841
7842
    ret = wc_NoiseSrc_Init(src);
7843
    if (ret != 0) {
7844
        return ret;
7845
    }
7846
7847
    /* Two gathers side by side in the work buffer. */
7848
    len = src->workSz / 2U;
7849
    if (len > 64U) {
7850
        len = 64U;
7851
    }
7852
    if (len == 0U) {
7853
        return BUFFER_E;
7854
    }
7855
    a = src->work;
7856
    b = src->work + len;
7857
7858
    for (s = 0; s < (int)src->numSrc; s++) {
7859
        if ((src->degraded & (word16)(1U << s)) != 0) {
7860
            continue;   /* already dropped - no point re-testing it */
7861
        }
7862
        ret = NoiseSrc_Gather(src, a, len, s);
7863
        if (ret == 0) {
7864
            ret = NoiseSrc_Gather(src, b, len, s);
7865
        }
7866
        if (ret != 0) {
7867
            break;
7868
        }
7869
7870
        /* A source stuck at any constant - including one whose clock was
7871
         * never enabled - produces identical gathers. */
7872
        /* ConstantCompare, not XMEMCMP: raw pre-conditioning samples. */
7873
        if (ConstantCompare(a, b, (int)len) == 0) {
7874
            ret = ENTROPY_RT_E;
7875
            if (s == 0) {
7876
                src->failed = ret;
7877
                break;
7878
            }
7879
            src->degraded |= (word16)(1U << s);
7880
            ret = 0;
7881
            continue;
7882
        }
7883
7884
        /* Constant-octet check, accumulated rather than early-exit. */
7885
        diff = 0;
7886
        for (i = 1; i < len; i++) {
7887
            diff |= (byte)(a[i] ^ a[0]);
7888
        }
7889
        if (diff == 0) {
7890
            ret = ENTROPY_RT_E;
7891
            if (s == 0) {
7892
                src->failed = ret;
7893
                break;
7894
            }
7895
            src->degraded |= (word16)(1U << s);
7896
            ret = 0;
7897
            continue;
7898
        }
7899
    }
7900
7901
    /* A gather error above is deliberately not latched - see the policy note
7902
     * at the top of this module. */
7903
    ForceZero(src->work, src->workSz);
7904
7905
    return ret;
7906
}
7907
7908
#endif /* WOLFSSL_NOISE_SRC */
7909
7910
7911
/* Begin wc_GenerateSeed Implementations */
7912
#if defined(CUSTOM_RAND_GENERATE_SEED)
7913
7914
    /* Implement your own random generation function
7915
     * Return 0 to indicate success
7916
     * int rand_gen_seed(byte* output, word32 sz);
7917
     * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
7918
7919
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
7920
    {
7921
        (void)os; /* Suppress unused arg warning */
7922
        return CUSTOM_RAND_GENERATE_SEED(output, sz);
7923
    }
7924
7925
#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
7926
7927
    /* Implement your own random generation function,
7928
     *  which includes OS_Seed.
7929
     * Return 0 to indicate success
7930
     * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
7931
     * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
7932
7933
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
7934
    {
7935
        return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
7936
    }
7937
7938
#elif defined(CUSTOM_RAND_GENERATE)
7939
7940
   /* Implement your own random generation function
7941
    * word32 rand_gen(void);
7942
    * #define CUSTOM_RAND_GENERATE  rand_gen  */
7943
7944
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
7945
    {
7946
        word32 i = 0;
7947
7948
        (void)os;
7949
7950
        while (i < sz)
7951
        {
7952
            /* If not aligned or there is odd/remainder */
7953
            if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
7954
                ((wc_ptr_t)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
7955
            ) {
7956
                /* Single byte at a time */
7957
                output[i++] = (byte)CUSTOM_RAND_GENERATE();
7958
            }
7959
            else {
7960
                /* Use native 8, 16, 32 or 64 copy instruction */
7961
                *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
7962
                i += sizeof(CUSTOM_RAND_TYPE);
7963
            }
7964
        }
7965
7966
        return 0;
7967
    }
7968
7969
#elif defined(WOLFSSL_SGX)
7970
7971
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
7972
{
7973
    int ret = !SGX_SUCCESS;
7974
    int i, read_max = 10;
7975
7976
    for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
7977
        ret = sgx_read_rand(output, sz);
7978
    }
7979
7980
    (void)os;
7981
    return (ret == SGX_SUCCESS) ? 0 : 1;
7982
}
7983
7984
#elif defined(USE_WINDOWS_API)
7985
7986
#ifdef WIN_REUSE_CRYPT_HANDLE
7987
/* shared crypt handle for RNG use */
7988
static ProviderHandle gHandle = 0;
7989
7990
int wc_WinCryptHandleInit(void)
7991
{
7992
    int ret = 0;
7993
    if (gHandle == 0) {
7994
        if(!CryptAcquireContext(&gHandle, 0, 0, PROV_RSA_FULL,
7995
                                        CRYPT_VERIFYCONTEXT)) {
7996
            DWORD dw = GetLastError();
7997
            WOLFSSL_MSG("CryptAcquireContext failed!");
7998
            WOLFSSL_ERROR((int)dw);
7999
            ret = WINCRYPT_E;
8000
        }
8001
    }
8002
    return ret;
8003
}
8004
8005
void wc_WinCryptHandleCleanup(void)
8006
{
8007
    if (gHandle != 0) {
8008
        CryptReleaseContext(gHandle, 0);
8009
        gHandle = 0;
8010
    }
8011
}
8012
#endif /* WIN_REUSE_CRYPT_HANDLE */
8013
8014
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8015
{
8016
#ifdef WOLF_CRYPTO_CB
8017
    int ret;
8018
8019
    if (os != NULL
8020
    #ifndef WOLF_CRYPTO_CB_FIND
8021
        && os->devId != INVALID_DEVID)
8022
    #endif
8023
    {
8024
        ret = wc_CryptoCb_RandomSeed(os, output, sz);
8025
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
8026
            return ret;
8027
        /* fall-through when unavailable */
8028
    }
8029
#endif
8030
8031
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
8032
        if (IS_INTEL_RDSEED(intel_flags)) {
8033
             if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
8034
                 /* success, we're done */
8035
                 return 0;
8036
             }
8037
        #ifdef FORCE_FAILURE_RDSEED
8038
             /* don't fall back to CryptoAPI */
8039
             return READ_RAN_E;
8040
        #endif
8041
        }
8042
    #ifdef FORCE_FAILURE_RDSEED
8043
        else {
8044
            /* Don't fall back to system randomness */
8045
            return MISSING_RNG_E;
8046
        }
8047
    #endif
8048
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
8049
8050
#ifdef WIN_REUSE_CRYPT_HANDLE
8051
    /* Check that handle was initialized.
8052
     * Note: initialization should be done through:
8053
     * wolfSSL_Init -> wolfCrypt_Init -> wc_WinCryptHandleInit
8054
     */
8055
    if (wc_WinCryptHandleInit() != 0) {
8056
        return WINCRYPT_E;
8057
    }
8058
    if (!CryptGenRandom(gHandle, sz, output))
8059
        return CRYPTGEN_E;
8060
#else
8061
    if (!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
8062
                            CRYPT_VERIFYCONTEXT)) {
8063
        return WINCRYPT_E;
8064
    }
8065
    if (!CryptGenRandom(os->handle, sz, output)) {
8066
        return CRYPTGEN_E;
8067
    }
8068
    CryptReleaseContext(os->handle, 0);
8069
    os->handle = 0;
8070
#endif
8071
8072
    return 0;
8073
}
8074
8075
8076
#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
8077
8078
#include "rtprand.h"   /* rtp_rand () */
8079
8080
#if (defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)))
8081
#include "rtptime.h"   /* rtp_get_system_msec() */
8082
8083
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8084
{
8085
    word32 i;
8086
8087
    rtp_srand(rtp_get_system_msec());
8088
    for (i = 0; i < sz; i++ ) {
8089
        output[i] = rtp_rand() % 256;
8090
    }
8091
8092
    return 0;
8093
}
8094
#else
8095
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8096
{
8097
    word32 i;
8098
    KS_SEED(ks_get_ticks());
8099
8100
    for (i = 0; i < sz; i++ ) {
8101
        output[i] = KS_RANDOM() % 256;
8102
    }
8103
8104
    return 0;
8105
}
8106
#endif /* defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)) */
8107
8108
#elif (defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC_RNG)) && \
8109
      !defined(WOLFSSL_PIC32MZ_RNG)
8110
    /* enable ATECC RNG unless using PIC32MZ one instead */
8111
    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
8112
8113
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8114
    {
8115
        int ret = 0;
8116
8117
        (void)os;
8118
        if (output == NULL) {
8119
            return BUFFER_E;
8120
        }
8121
8122
        ret = atmel_get_random_number(sz, output);
8123
8124
        return ret;
8125
    }
8126
8127
#elif defined(MICROCHIP_PIC32) || defined(MICROCHIP_MPLAB_HARMONY)
8128
8129
    #ifdef MICROCHIP_MPLAB_HARMONY
8130
        #ifdef MICROCHIP_MPLAB_HARMONY_3
8131
            #include "system/time/sys_time.h"
8132
            #define PIC32_SEED_COUNT SYS_TIME_CounterGet
8133
        #else
8134
            #define PIC32_SEED_COUNT _CP0_GET_COUNT
8135
        #endif
8136
    #else
8137
        #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
8138
            #include <peripheral/timer.h>
8139
        #endif
8140
        extern word32 ReadCoreTimer(void);
8141
        #define PIC32_SEED_COUNT ReadCoreTimer
8142
    #endif
8143
8144
    #ifdef WOLFSSL_PIC32MZ_RNG
8145
        #include "xc.h"
8146
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8147
        {
8148
            int i;
8149
            byte rnd[8];
8150
            word32 *rnd32 = (word32 *)rnd;
8151
            word32 size = sz;
8152
            byte* op = output;
8153
8154
#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
8155
            RNGNUMGEN1 = _CP0_GET_COUNT();
8156
            RNGPOLY1 = _CP0_GET_COUNT();
8157
            RNGPOLY2 = _CP0_GET_COUNT();
8158
            RNGNUMGEN2 = _CP0_GET_COUNT();
8159
#else
8160
            /* All others can be seeded from the TRNG */
8161
            RNGCONbits.TRNGMODE = 1;
8162
            RNGCONbits.TRNGEN = 1;
8163
            while (RNGCNT < 64);
8164
            RNGCONbits.LOAD = 1;
8165
            while (RNGCONbits.LOAD == 1);
8166
            while (RNGCNT < 64);
8167
            RNGPOLY2 = RNGSEED2;
8168
            RNGPOLY1 = RNGSEED1;
8169
#endif
8170
8171
            RNGCONbits.PLEN = 0x40;
8172
            RNGCONbits.PRNGEN = 1;
8173
            for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
8174
                volatile int x, y;
8175
                x = RNGNUMGEN1;
8176
                y = RNGNUMGEN2;
8177
                (void)x;
8178
                (void)y;
8179
            }
8180
            do {
8181
                rnd32[0] = RNGNUMGEN1;
8182
                rnd32[1] = RNGNUMGEN2;
8183
8184
                for(i=0; i<8; i++, op++) {
8185
                    *op = rnd[i];
8186
                    size --;
8187
                    if(size==0)break;
8188
                }
8189
            } while(size);
8190
            return 0;
8191
        }
8192
    #else  /* WOLFSSL_PIC32MZ_RNG */
8193
        /* uses the core timer, in nanoseconds to seed srand */
8194
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8195
        {
8196
            int i;
8197
            srand(PIC32_SEED_COUNT() * 25);
8198
8199
            for (i = 0; i < sz; i++ ) {
8200
                output[i] = rand() % 256;
8201
                if ( (i % 8) == 7)
8202
                    srand(PIC32_SEED_COUNT() * 25);
8203
            }
8204
            return 0;
8205
        }
8206
    #endif /* WOLFSSL_PIC32MZ_RNG */
8207
8208
#elif defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
8209
    /*
8210
     * wc_Generates a RNG seed using the Random Number Generator Accelerator
8211
     * on the Kinetis K70. Documentation located in Chapter 37 of
8212
     * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
8213
     */
8214
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8215
    {
8216
        word32 i;
8217
8218
        /* turn on RNGA module */
8219
        #if defined(SIM_SCGC3_RNGA_MASK)
8220
            SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
8221
        #endif
8222
        #if defined(SIM_SCGC6_RNGA_MASK)
8223
            /* additionally needed for at least K64F */
8224
            SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
8225
        #endif
8226
8227
        /* set SLP bit to 0 - "RNGA is not in sleep mode" */
8228
        RNG_CR &= ~RNG_CR_SLP_MASK;
8229
8230
        /* set HA bit to 1 - "security violations masked" */
8231
        RNG_CR |= RNG_CR_HA_MASK;
8232
8233
        /* set GO bit to 1 - "output register loaded with data" */
8234
        RNG_CR |= RNG_CR_GO_MASK;
8235
8236
        for (i = 0; i < sz; i++) {
8237
8238
            /* wait for RNG FIFO to be full */
8239
            while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
8240
8241
            /* get value */
8242
            output[i] = RNG_OR;
8243
        }
8244
8245
        return 0;
8246
    }
8247
8248
#elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
8249
    /*
8250
     * wc_Generates a RNG seed using the Random Number Generator (RNGB)
8251
     * on the Kinetis K53. Documentation located in Chapter 33 of
8252
     * K53 Sub-Family Reference Manual (see note in the README for link).
8253
     */
8254
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8255
    {
8256
        int i;
8257
8258
        /* turn on RNGB module */
8259
        SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
8260
8261
        /* reset RNGB */
8262
        RNG_CMD |= RNG_CMD_SR_MASK;
8263
8264
        /* FIFO generate interrupt, return all zeros on underflow,
8265
         * set auto reseed */
8266
        RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
8267
8268
        /* gen seed, clear interrupts, clear errors */
8269
        RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
8270
8271
        /* wait for seeding to complete */
8272
        while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
8273
8274
        for (i = 0; i < sz; i++) {
8275
8276
            /* wait for a word to be available from FIFO */
8277
            while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
8278
8279
            /* get value */
8280
            output[i] = RNG_OUT;
8281
        }
8282
8283
        return 0;
8284
    }
8285
8286
#elif defined(FREESCALE_KSDK_2_0_TRNG)
8287
    #ifndef TRNG0
8288
    #define TRNG0 TRNG
8289
    #endif
8290
8291
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8292
    {
8293
        status_t status;
8294
        status = TRNG_GetRandomData(TRNG0, output, sz);
8295
        (void)os;
8296
        if (status == kStatus_Success)
8297
        {
8298
            return(0);
8299
        }
8300
        return RAN_BLOCK_E;
8301
    }
8302
8303
#elif defined(FREESCALE_KSDK_2_0_RNGA)
8304
8305
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8306
    {
8307
        status_t status;
8308
        status = RNGA_GetRandomData(RNG, output, sz);
8309
        (void)os;
8310
        if (status == kStatus_Success)
8311
        {
8312
            return(0);
8313
        }
8314
        return RAN_BLOCK_E;
8315
    }
8316
8317
8318
#elif defined(FREESCALE_RNGA)
8319
8320
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8321
    {
8322
        status_t status;
8323
        status = RNGA_GetRandomData(RNG, output, sz);
8324
        (void)os;
8325
        if (status == kStatus_Success)
8326
        {
8327
            return(0);
8328
        }
8329
        return RAN_BLOCK_E;
8330
    }
8331
#elif !defined(WOLFSSL_CAAM) && \
8332
    (defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
8333
     defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS))
8334
    /*
8335
     * Fallback to USE_TEST_GENSEED if a FREESCALE platform did not match any
8336
     * of the TRNG/RNGA/RNGB support
8337
     */
8338
    #define USE_TEST_GENSEED
8339
8340
#elif defined(WOLFSSL_SILABS_SE_ACCEL)
8341
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8342
    {
8343
        (void)os;
8344
        return silabs_GenerateRand(output, sz);
8345
    }
8346
8347
#elif defined(STM32_RNG)
8348
     /* Generate a RNG seed using the hardware random number generator
8349
      * on the STM32F2/F4/F7/L4. */
8350
    #include <wolfssl/wolfcrypt/port/st/stm32.h>
8351
        /* Pulls in WC_STM32_RNG_CLK_ENABLE for WOLFSSL_STM32_BARE builds */
8352
    #ifdef WC_STM32_RNG_DIAG
8353
        /* The WC_STM32_RNG_DIAG paths below use printf(); pull in stdio.h so the
8354
         * file compiles on strict C99+ toolchains when diagnostics are enabled. */
8355
        #include <stdio.h>
8356
    #endif
8357
8358
8359
    #ifdef WOLFSSL_STM32_CUBEMX
8360
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8361
    {
8362
        int ret;
8363
        RNG_HandleTypeDef hrng;
8364
        word32 i = 0;
8365
        (void)os;
8366
8367
        ret = wolfSSL_CryptHwMutexLock();
8368
        if (ret != 0) {
8369
            return ret;
8370
        }
8371
8372
        /* enable RNG clock source */
8373
        __HAL_RCC_RNG_CLK_ENABLE();
8374
8375
        /* enable RNG peripheral */
8376
        XMEMSET(&hrng, 0, sizeof(hrng));
8377
        hrng.Instance = RNG;
8378
        HAL_RNG_Init(&hrng);
8379
8380
        while (i < sz) {
8381
            /* If not aligned or there is odd/remainder */
8382
            if( (i + sizeof(word32)) > sz ||
8383
                ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
8384
            ) {
8385
                /* Single byte at a time */
8386
                uint32_t tmpRng = 0;
8387
                if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) {
8388
                    wolfSSL_CryptHwMutexUnLock();
8389
                    return RAN_BLOCK_E;
8390
                }
8391
                output[i++] = (byte)tmpRng;
8392
            }
8393
            else {
8394
                /* Use native 32 instruction */
8395
                if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) {
8396
                    wolfSSL_CryptHwMutexUnLock();
8397
                    return RAN_BLOCK_E;
8398
                }
8399
                i += sizeof(word32);
8400
            }
8401
        }
8402
8403
        HAL_RNG_DeInit(&hrng);
8404
8405
        wolfSSL_CryptHwMutexUnLock();
8406
8407
        return 0;
8408
    }
8409
    #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB) \
8410
        || defined(STM32_NUTTX_RNG)
8411
8412
    #ifdef STM32_NUTTX_RNG
8413
        #include "hardware/stm32_rng.h"
8414
        /* Set CONFIG_STM32U5_RNG in NuttX to enable the RCC */
8415
        #define WC_RNG_CR *((volatile uint32_t*)(STM32_RNG_CR))
8416
        #define WC_RNG_SR *((volatile uint32_t*)(STM32_RNG_SR))
8417
        #define WC_RNG_DR *((volatile uint32_t*)(STM32_RNG_DR))
8418
    #else
8419
        /* Comes from "stm32xxxx_hal.h" */
8420
        #define WC_RNG_CR RNG->CR
8421
        #define WC_RNG_SR RNG->SR
8422
        #define WC_RNG_DR RNG->DR
8423
    #endif
8424
8425
8426
    /* Bounded poll for DRDY, plus recovery from SECS / CECS. The
8427
     * unbounded `while (DRDY == 0)` loop in the original code spins
8428
     * forever on chips where the RNG kernel clock is unstable
8429
     * (e.g. WL55 with RNGSEL = MSI under sustained ECDSA-key-gen
8430
     * load), because once the IP latches a Seed-error or Clock-
8431
     * error condition it stops asserting DRDY. Per the STM32 RM
8432
     * recovery sequence: clear SEIS/CEIS, toggle RNGEN, discard the
8433
     * stale words sitting in the RNG output, then retry. */
8434
    #ifndef STM32_BARE_RNG_BYTE_TIMEOUT
8435
        #define STM32_BARE_RNG_BYTE_TIMEOUT 0x40000
8436
    #endif
8437
    #ifndef STM32_BARE_RNG_MAX_RETRIES
8438
        #define STM32_BARE_RNG_MAX_RETRIES 8
8439
    #endif
8440
8441
    /* Bring the direct-register RNG to a producing state: clock enable, the
8442
     * new-gen (C5) NIST conditioning under CONDRST on the first call, and
8443
     * RNGEN. Mutex-free -- the caller must already hold the crypto HW mutex.
8444
     * Shared by wc_GenerateSeed (below) and the SAES self-init path
8445
     * (Stm32SaesEnsureRng), so a cold DHUK/SAES operation no longer requires a
8446
     * prior wc_InitRng. Returns 0, or RNG_FAILURE_E if the conditioning
8447
     * soft-reset never clears. */
8448
    WOLFSSL_LOCAL int wc_stm32_rng_ensure_ready(void)
8449
    {
8450
        word32 t = 0;
8451
        (void)t;
8452
8453
    #ifndef STM32_NUTTX_RNG
8454
        /* enable RNG peripheral clock */
8455
        #ifdef WC_STM32_RNG_CLK_ENABLE
8456
            WC_STM32_RNG_CLK_ENABLE();
8457
        #else
8458
            /* Default for F4/F7/L4/L5/U5/H5/H7 -- RNG on AHB2 */
8459
            RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
8460
        #endif
8461
    #endif
8462
8463
        /* On the new-gen STM32C5 RNG IP the CR register is locked at
8464
         * reset (CONFIGLOCK clear, but the IP refuses to produce data
8465
         * until a NIST-compliant CONFIG1/2/3 + NSCR + HTCR sequence
8466
         * has been written under CONDRST). The HAL ships canonical
8467
         * candidate values in the device header (RNG_CAND_NIST_*).
8468
         * Detect the family by presence of that symbol -- on chips
8469
         * without it (F4/F7/L4/U5/H7/H5/WL/etc.) skip. Do this only
8470
         * on the first call (RNGEN clear) so subsequent calls don't
8471
         * disturb a running peripheral. */
8472
    #if defined(RNG_CAND_NIST_CR_VALUE) && defined(RNG_CR_CONDRST) && \
8473
        !defined(WC_STM32_RNG_NO_NIST_INIT)
8474
        if ((WC_RNG_CR & RNG_CR_RNGEN) == 0U) {
8475
        #ifdef RNG_SR_BUSY
8476
            /* HAL flow: drain BUSY before writing CR. */
8477
            t = 0;
8478
            while ((WC_RNG_SR & RNG_SR_BUSY) != 0U) {
8479
                if (++t >= STM32_BARE_RNG_BYTE_TIMEOUT) {
8480
                    break;
8481
                }
8482
            }
8483
        #endif
8484
            WC_RNG_CR = (uint32_t)RNG_CAND_NIST_CR_VALUE |
8485
                        (uint32_t)RNG_CR_CONDRST;
8486
        #ifdef RNG_CAND_NIST_NSCR_VALUE
8487
            RNG->NSCR = (uint32_t)RNG_CAND_NIST_NSCR_VALUE;
8488
        #endif
8489
        #ifdef RNG_CAND_NIST_HTCR_VALUE
8490
            RNG->HTCR[0] = (uint32_t)RNG_CAND_NIST_HTCR_VALUE;
8491
        #endif
8492
            /* Clear CONDRST and wait for the IP to mirror it back. The
8493
             * STM32 HAL polls RNG_CR.CONDRST (not SR.BUSY) for completion
8494
             * of the conditioning soft-reset; SR.BUSY drops earlier in
8495
             * the seed-pull pipeline on at least the C5 IP and reading
8496
             * it as "conditioning done" trips a SECS=1 a few microseconds
8497
             * later when RNGEN goes high. Bounded so a misconfigured
8498
             * kernel clock returns a clean error instead of hanging. */
8499
            WC_RNG_CR &= ~(uint32_t)RNG_CR_CONDRST;
8500
            t = 0;
8501
            while ((WC_RNG_CR & RNG_CR_CONDRST) != 0U) {
8502
                if (++t >= STM32_BARE_RNG_BYTE_TIMEOUT) {
8503
#ifdef WC_STM32_RNG_DIAG
8504
                    printf("[RNG] CONDRST stuck CR=%08lx SR=%08lx\n",
8505
                           (unsigned long)WC_RNG_CR,
8506
                           (unsigned long)WC_RNG_SR);
8507
#endif
8508
                    return RNG_FAILURE_E;
8509
                }
8510
            }
8511
#ifdef WC_STM32_RNG_DIAG
8512
            printf("[RNG] post-NIST CR=%08lx SR=%08lx t=%lu\n",
8513
                   (unsigned long)WC_RNG_CR,
8514
                   (unsigned long)WC_RNG_SR,
8515
                   (unsigned long)t);
8516
#endif
8517
        }
8518
    #endif
8519
8520
        /* enable RNG interrupt, set IE bit in RNG->CR register */
8521
        WC_RNG_CR |= RNG_CR_IE;
8522
8523
        /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
8524
         * RNG_LFSR, and error detector. WC_STM32_RNG_CED_DISABLE
8525
         * additionally sets CR.CED=1 to suppress the clock-error
8526
         * detection -- the Linux STM32 RNG driver does this and on
8527
         * the C5 silicon the CED detector trips on a (perfectly fine)
8528
         * 48 MHz kernel clock for reasons unclear in the RM. */
8529
#ifdef WC_STM32_RNG_CED_DISABLE
8530
        WC_RNG_CR |= RNG_CR_RNGEN | RNG_CR_CED;
8531
#else
8532
        WC_RNG_CR |= RNG_CR_RNGEN;
8533
#endif
8534
8535
        return 0;
8536
    }
8537
8538
    /* Generate a RNG seed using the hardware RNG on the STM32F427
8539
     * directly, following steps outlined in STM32F4 Reference
8540
     * Manual (Chapter 24) for STM32F4xx family. */
8541
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8542
    {
8543
        int ret;
8544
        word32 i;
8545
        word32 t;
8546
        word32 guard;
8547
        word32 retries;
8548
        word32 sr;
8549
        (void)os;
8550
8551
        ret = wolfSSL_CryptHwMutexLock();
8552
        if (ret != 0) {
8553
            return ret;
8554
        }
8555
8556
        /* Clock enable + (C5) NIST conditioning + RNGEN, shared with the SAES
8557
         * self-init path. Mutex-free helper; we hold the mutex. */
8558
        ret = wc_stm32_rng_ensure_ready();
8559
        if (ret != 0) {
8560
            wolfSSL_CryptHwMutexUnLock();
8561
            return ret;
8562
        }
8563
8564
        /* (No early SECS/CECS bail here.) The HAL doesn't check error
8565
         * status immediately after RNGEN -- the IP needs a few cycles
8566
         * after enable for the first seed pull, and a transient SEIS/SECS
8567
         * can latch and resolve itself through the auto-reset that the
8568
         * retry loop below already handles. Bailing here returned
8569
         * RNG_FAILURE_E (-199) on first-init on the STM32C5 silicon.
8570
         * NOTE: this branch serves all direct-register STM32 RNG users
8571
         * (WOLFSSL_STM32F427_RNG / WOLFSSL_STM32_RNG_NOLIB / STM32_NUTTX_RNG),
8572
         * not only the BARE/C5 port, so this bounded-retry + recovery applies
8573
         * to every NOLIB family. It is strictly more robust than the old early
8574
         * fast-fail: it still returns RNG_FAILURE_E after the retry budget. */
8575
8576
        for (i = 0; i < sz; i++) {
8577
            retries = 0;
8578
            for (;;) {
8579
                t = 0;
8580
                /* Sample SR once before the loop so the post-loop
8581
                 * happy-path / error checks have a defined value even
8582
                 * if STM32_BARE_RNG_BYTE_TIMEOUT is configured to 0. */
8583
                sr = WC_RNG_SR;
8584
                /* Bounded DRDY poll -- breaks on either DRDY or any
8585
                 * error indication (SECS/CECS). */
8586
                while (t < STM32_BARE_RNG_BYTE_TIMEOUT) {
8587
                    sr = WC_RNG_SR;
8588
                    if ((sr & (RNG_SR_DRDY | RNG_SR_SECS |
8589
                               RNG_SR_CECS)) != 0U) {
8590
                        break;
8591
                    }
8592
                    t++;
8593
                }
8594
8595
                /* Happy path: data ready and no error. */
8596
                if ((sr & RNG_SR_DRDY) != 0U &&
8597
                    (sr & (RNG_SR_SECS | RNG_SR_CECS)) == 0U) {
8598
                    output[i] = WC_RNG_DR;
8599
                    break;
8600
                }
8601
8602
                /* Either timed out or an error latched. Recover. */
8603
                if (++retries > STM32_BARE_RNG_MAX_RETRIES) {
8604
#ifdef WC_STM32_RNG_DIAG
8605
                    printf("[RNG] retry max byte=%lu sr=%08lx CR=%08lx\n",
8606
                           (unsigned long)i,
8607
                           (unsigned long)sr,
8608
                           (unsigned long)WC_RNG_CR);
8609
#endif
8610
                    wolfSSL_CryptHwMutexUnLock();
8611
                    return RNG_FAILURE_E;
8612
                }
8613
#ifdef WC_STM32_RNG_DIAG
8614
                printf("[RNG] retry byte=%lu retries=%lu sr=%08lx\n",
8615
                       (unsigned long)i,
8616
                       (unsigned long)retries,
8617
                       (unsigned long)sr);
8618
#endif
8619
8620
                /* Recovery sequence (per STM32 RM RNG chapter):
8621
                 *   1. Clear SEIS / CEIS interrupt status by writing 0
8622
                 *      to those bits. All other SR bits are read-only
8623
                 *      status indicators (DRDY / BUSY / SECS / CECS);
8624
                 *      writing 0 to them has no effect per the RM, so
8625
                 *      a plain 0 write is safe and avoids the
8626
                 *      read-modify-write hitting any reserved bits the
8627
                 *      IP revision may add later.
8628
                 *   2. Toggle RNGEN off then on to drop any stale
8629
                 *      LFSR state that may be tainted by the error.
8630
                 *   3. Discard four DR reads to flush the pipeline
8631
                 *      (only meaningful when DRDY is set; otherwise
8632
                 *      the reads are harmless and bounded). The 'guard'
8633
                 *      counter bounds the loop independently of 't' so a
8634
                 *      marginal kernel clock (DRDY stays 0, no error
8635
                 *      latched) cannot spin forever -- it falls through
8636
                 *      to the outer retry/backoff instead of hanging. */
8637
                WC_RNG_SR = 0;
8638
                WC_RNG_CR &= ~RNG_CR_RNGEN;
8639
                WC_RNG_CR |= RNG_CR_RNGEN;
8640
                t = 0;
8641
                guard = 0;
8642
                while (t < 4U && guard < STM32_BARE_RNG_BYTE_TIMEOUT) {
8643
                    guard++;
8644
                    if ((WC_RNG_SR & RNG_SR_DRDY) != 0U) {
8645
                        (void)WC_RNG_DR;
8646
                        t++;
8647
                    }
8648
                    else if ((WC_RNG_SR &
8649
                              (RNG_SR_SECS | RNG_SR_CECS)) != 0U) {
8650
                        /* Clock-error during recovery -- bail and
8651
                         * let the outer retry handle it. */
8652
                        break;
8653
                    }
8654
                }
8655
            }
8656
        }
8657
8658
        wolfSSL_CryptHwMutexUnLock();
8659
8660
        return 0;
8661
    }
8662
8663
    #else
8664
8665
    /* Generate a RNG seed using the STM32 Standard Peripheral Library */
8666
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8667
    {
8668
        int ret;
8669
        word32 i;
8670
        (void)os;
8671
8672
        ret = wolfSSL_CryptHwMutexLock();
8673
        if (ret != 0) {
8674
            return ret;
8675
        }
8676
8677
        /* enable RNG clock source */
8678
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
8679
8680
        /* reset RNG */
8681
        RNG_DeInit();
8682
8683
        /* enable RNG peripheral */
8684
        RNG_Cmd(ENABLE);
8685
8686
        /* verify no errors with RNG_CLK or Seed */
8687
        if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) {
8688
            wolfSSL_CryptHwMutexUnLock();
8689
            return RNG_FAILURE_E;
8690
        }
8691
8692
        for (i = 0; i < sz; i++) {
8693
            /* wait until RNG number is ready */
8694
            while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
8695
8696
            /* get value */
8697
            output[i] = RNG_GetRandomNumber();
8698
        }
8699
8700
        wolfSSL_CryptHwMutexUnLock();
8701
8702
        return 0;
8703
    }
8704
    #endif /* WOLFSSL_STM32_CUBEMX */
8705
8706
#elif defined(WOLFSSL_TIRTOS)
8707
    #warning "potential for not enough entropy, currently being used for testing"
8708
    #include <xdc/runtime/Timestamp.h>
8709
    #include <stdlib.h>
8710
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8711
    {
8712
        int i;
8713
        srand(xdc_runtime_Timestamp_get32());
8714
8715
        for (i = 0; i < sz; i++ ) {
8716
            output[i] = rand() % 256;
8717
            if ((i % 8) == 7) {
8718
                srand(xdc_runtime_Timestamp_get32());
8719
            }
8720
        }
8721
8722
        return 0;
8723
    }
8724
8725
#elif defined(WOLFSSL_PB)
8726
8727
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8728
    {
8729
        word32 i;
8730
        for (i = 0; i < sz; i++)
8731
            output[i] = UTL_Rand();
8732
8733
        (void)os;
8734
8735
        return 0;
8736
    }
8737
8738
#elif defined(WOLFSSL_NUCLEUS)
8739
#include "nucleus.h"
8740
#include "kernel/plus_common.h"
8741
8742
#warning "potential for not enough entropy, currently being used for testing"
8743
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8744
{
8745
    int i;
8746
    srand(NU_Get_Time_Stamp());
8747
8748
    for (i = 0; i < sz; i++ ) {
8749
        output[i] = rand() % 256;
8750
        if ((i % 8) == 7) {
8751
            srand(NU_Get_Time_Stamp());
8752
        }
8753
    }
8754
8755
    return 0;
8756
}
8757
#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE)
8758
    #include "stdlib.h"
8759
8760
    #warning "potential for not enough entropy, currently being used for testing Deos"
8761
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8762
    {
8763
        int i;
8764
        int seed = XTIME(0);
8765
        (void)os;
8766
8767
        for (i = 0; i < sz; i++ ) {
8768
            output[i] = rand_r(&seed) % 256;
8769
            if ((i % 8) == 7) {
8770
                seed = XTIME(0);
8771
                rand_r(&seed);
8772
            }
8773
        }
8774
8775
        return 0;
8776
    }
8777
#elif defined(WOLFSSL_VXWORKS)
8778
    #ifdef WOLFSSL_VXWORKS_6_x
8779
        #include "stdlib.h"
8780
        #warning "potential for not enough entropy, currently being used for testing"
8781
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8782
        {
8783
            int i;
8784
            unsigned int seed = (unsigned int)XTIME(0);
8785
            (void)os;
8786
8787
            for (i = 0; i < sz; i++ ) {
8788
                output[i] = rand_r(&seed) % 256;
8789
                if ((i % 8) == 7) {
8790
                    seed = (unsigned int)XTIME(0);
8791
                    rand_r(&seed);
8792
                }
8793
            }
8794
8795
            return 0;
8796
        }
8797
    #else
8798
        #include <randomNumGen.h>
8799
        #include <tickLib.h>
8800
8801
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
8802
            STATUS                status   = ERROR;
8803
            RANDOM_NUM_GEN_STATUS r_status = RANDOM_NUM_GEN_ERROR;
8804
            _Vx_ticks_t           seed = 0;
8805
8806
            #ifdef VXWORKS_SIM
8807
                /* cannot generate true entropy with VxWorks simulator */
8808
                #warning "not enough entropy, simulator for testing only"
8809
                int i = 0;
8810
8811
                for (i = 0; i < 1000; i++) {
8812
                    randomAddTimeStamp();
8813
                }
8814
            #endif
8815
8816
            /*
8817
              wolfSSL can request 52 Bytes of random bytes. We need to add
8818
              buffer to the entropy pool to ensure we can get more than 32 Bytes.
8819
              Because VxWorks has entropy limits (ENTROPY_MIN and ENTROPY_MAX)
8820
              defined as 256 and 1024 bits, see randomSWNumGenLib.c.
8821
8822
              randStatus() can return the following status:
8823
              RANDOM_NUM_GEN_NO_ENTROPY when entropy is 0
8824
              RANDOM_NUM_GEN_ERROR, entropy is not initialized
8825
              RANDOM_NUM_GEN_NOT_ENOUGH_ENTROPY if entropy < 32 Bytes
8826
              RANDOM_NUM_GEN_ENOUGH_ENTROPY if entropy is between 32 and 128 Bytes
8827
              RANDOM_NUM_GEN_MAX_ENTROPY if entropy is greater than 128 Bytes
8828
            */
8829
8830
            do {
8831
                seed = tickGet();
8832
                status = randAdd(&seed, sizeof(_Vx_ticks_t), 2);
8833
                if (status == OK)
8834
                    r_status = randStatus();
8835
8836
            } while (r_status != RANDOM_NUM_GEN_MAX_ENTROPY &&
8837
                     r_status != RANDOM_NUM_GEN_ERROR && status == OK);
8838
8839
            if (r_status == RANDOM_NUM_GEN_ERROR)
8840
                return RNG_FAILURE_E;
8841
8842
            status = randBytes (output, sz);
8843
8844
            if (status == ERROR) {
8845
                return RNG_FAILURE_E;
8846
            }
8847
8848
            return 0;
8849
        }
8850
    #endif
8851
#elif defined(WOLFSSL_NRF51) || defined(WOLFSSL_NRF5x)
8852
    #include "app_error.h"
8853
    #include "nrf_drv_rng.h"
8854
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8855
    {
8856
        int remaining = sz, pos = 0;
8857
        word32 err_code;
8858
        byte available;
8859
        static byte initialized = 0;
8860
8861
        (void)os;
8862
8863
        /* Make sure RNG is running */
8864
        if (!initialized) {
8865
            err_code = nrf_drv_rng_init(NULL);
8866
            if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE
8867
            #ifdef NRF_ERROR_MODULE_ALREADY_INITIALIZED
8868
                && err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED
8869
            #endif
8870
            ) {
8871
                return -1;
8872
            }
8873
            initialized = 1;
8874
        }
8875
8876
        while (remaining > 0) {
8877
            int length;
8878
            available = 0;
8879
            nrf_drv_rng_bytes_available(&available); /* void func */
8880
            length = (remaining < available) ? remaining : available;
8881
            if (length > 0) {
8882
                err_code = nrf_drv_rng_rand(&output[pos], length);
8883
                if (err_code != NRF_SUCCESS) {
8884
                    break;
8885
                }
8886
                remaining -= length;
8887
                pos += length;
8888
            }
8889
        }
8890
8891
        return (err_code == NRF_SUCCESS) ? 0 : -1;
8892
    }
8893
8894
#elif defined(HAVE_WNR)
8895
8896
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8897
    {
8898
        if (os == NULL || output == NULL || wnr_ctx == NULL ||
8899
                wnr_timeout < 0) {
8900
            return BAD_FUNC_ARG;
8901
        }
8902
8903
    #ifndef WOLFSSL_MUTEX_INITIALIZER
8904
        if (WOLFSSL_ATOMIC_LOAD(wnr_mutex_inited) != 2) {
8905
            WOLFSSL_MSG("netRandom context must be created before use");
8906
            return RNG_FAILURE_E;
8907
        }
8908
    #endif
8909
8910
        if (wc_LockMutex(&wnr_mutex) != 0) {
8911
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
8912
            return BAD_MUTEX_E;
8913
        }
8914
8915
        if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
8916
                WNR_ERROR_NONE)
8917
            return RNG_FAILURE_E;
8918
8919
        wc_UnLockMutex(&wnr_mutex);
8920
8921
        return 0;
8922
    }
8923
8924
#elif defined(INTIME_RTOS)
8925
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8926
    {
8927
        uint32_t randval;
8928
        word32 len;
8929
8930
        if (output == NULL) {
8931
            return BUFFER_E;
8932
        }
8933
8934
    #ifdef INTIMEVER
8935
        /* If INTIMEVER exists then it is INTIME RTOS v6 or later */
8936
        #define INTIME_RAND_FUNC arc4random
8937
        len = 4;
8938
    #else
8939
        /* v5 and older */
8940
        #define INTIME_RAND_FUNC rand
8941
        srand(time(0));
8942
        len = 2; /* don't use all 31 returned bits */
8943
    #endif
8944
8945
        while (sz > 0) {
8946
            if (sz < len)
8947
                len = sz;
8948
            randval = INTIME_RAND_FUNC();
8949
            XMEMCPY(output, &randval, len);
8950
            output += len;
8951
            sz -= len;
8952
        }
8953
        (void)os;
8954
8955
        return 0;
8956
    }
8957
8958
#elif defined(WOLFSSL_WICED)
8959
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8960
    {
8961
        int ret;
8962
        (void)os;
8963
8964
        if (output == NULL || UINT16_MAX < sz) {
8965
            return BUFFER_E;
8966
        }
8967
8968
        if ((ret = wiced_crypto_get_random((void*) output, sz) )
8969
                         != WICED_SUCCESS) {
8970
            return ret;
8971
        }
8972
8973
        return ret;
8974
    }
8975
8976
#elif defined(WOLFSSL_NETBURNER)
8977
    #warning using NetBurner pseudo random GetRandomByte for seed
8978
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
8979
    {
8980
        word32 i;
8981
        (void)os;
8982
8983
        if (output == NULL) {
8984
            return BUFFER_E;
8985
        }
8986
8987
        for (i = 0; i < sz; i++) {
8988
            output[i] = GetRandomByte();
8989
8990
            /* check if was a valid random number */
8991
            if (!RandomValid())
8992
                return RNG_FAILURE_E;
8993
        }
8994
8995
        return 0;
8996
    }
8997
#elif defined(IDIRECT_DEV_RANDOM)
8998
8999
    extern int getRandom( int sz, unsigned char *output );
9000
9001
    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9002
    {
9003
        int num_bytes_returned = 0;
9004
9005
        num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
9006
9007
        return 0;
9008
    }
9009
9010
#elif defined(WOLFSSL_CAAM)
9011
9012
    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
9013
9014
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9015
    {
9016
        unsigned int args[4] = {0};
9017
        CAAM_BUFFER buf[1];
9018
        int ret    = 0;
9019
        int times  = 1000, i; /* 1000 is an arbitrary number chosen */
9020
        word32 idx = 0;
9021
9022
        (void)os;
9023
9024
        if (output == NULL) {
9025
            return BUFFER_E;
9026
        }
9027
9028
        /* Check Waiting to make sure entropy is ready */
9029
        for (i = 0; i < times; i++) {
9030
            buf[0].BufferType = DataBuffer | LastBuffer;
9031
            buf[0].TheAddress = (CAAM_ADDRESS)(output + idx);
9032
            buf[0].Length     = ((sz - idx) < WC_CAAM_MAX_ENTROPY)?
9033
                                sz - idx : WC_CAAM_MAX_ENTROPY;
9034
9035
            args[0] = buf[0].Length;
9036
            ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY);
9037
            if (ret == 0) {
9038
                idx += buf[0].Length;
9039
                if (idx == sz)
9040
                    break;
9041
            }
9042
9043
            /* driver could be waiting for entropy */
9044
            if (ret != WC_NO_ERR_TRACE(RAN_BLOCK_E) && ret != 0) {
9045
                return ret;
9046
            }
9047
#ifndef WOLFSSL_IMXRT1170_CAAM
9048
            usleep(100);
9049
#endif
9050
        }
9051
9052
        if (i == times && ret != 0) {
9053
             return RNG_FAILURE_E;
9054
        }
9055
        else { /* Success case */
9056
            ret = 0;
9057
        }
9058
9059
        return ret;
9060
    }
9061
9062
#elif defined(WOLFSSL_APACHE_MYNEWT)
9063
9064
    #include <stdlib.h>
9065
    #include "os/os_time.h"
9066
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9067
    {
9068
        int i;
9069
        srand(os_time_get());
9070
9071
        for (i = 0; i < sz; i++ ) {
9072
            output[i] = rand() % 256;
9073
            if ((i % 8) == 7) {
9074
                srand(os_time_get());
9075
            }
9076
        }
9077
9078
        return 0;
9079
    }
9080
9081
#elif defined(ARDUINO)
9082
9083
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9084
    {
9085
        int ret = 0;
9086
        word32 rand;
9087
        while (sz > 0) {
9088
            word32 len = sizeof(rand);
9089
            if (sz < len)
9090
                len = sz;
9091
        /* Get an Arduino framework random number */
9092
        #if defined(ARDUINO_SAMD_NANO_33_IOT) || \
9093
            defined(ARDUINO_ARCH_RP2040)
9094
            /* Known, tested boards working with random() */
9095
            rand = random();
9096
        #elif defined(ARDUINO_SAM_DUE)
9097
            /* See: https://github.com/avrxml/asf/tree/master/sam/utils/cmsis/sam3x/include */
9098
            #if defined(__SAM3A4C__)
9099
                #ifndef TRNG
9100
                    #define TRNG (0x400BC000U)
9101
                #endif
9102
            #elif defined(__SAM3A8C__)
9103
                #ifndef TRNG
9104
                    #define TRNG (0x400BC000U)
9105
                #endif
9106
            #elif defined(__SAM3X4C__)
9107
                #ifndef TRNG
9108
                    #define TRNG (0x400BC000U)
9109
                #endif
9110
            #elif defined(__SAM3X4E__)
9111
                #ifndef TRNG
9112
                    #define TRNG (0x400BC000U)
9113
                #endif
9114
            #elif defined(__SAM3X8C__)
9115
                #ifndef TRNG
9116
                    #define TRNG (0x400BC000U)
9117
                #endif
9118
            #elif defined(__SAM3X8E__)
9119
                /* This is the Arduino Due */
9120
                #ifndef TRNG
9121
                    #define TRNG (0x400BC000U)
9122
                #endif
9123
            #elif  defined(__SAM3A8H__)
9124
                #ifndef TRNG
9125
                    #define TRNG (0x400BC000U)
9126
                #endif
9127
            #else
9128
                #ifndef TRNG
9129
                    #error "Unknown TRNG for this device"
9130
                #endif
9131
            #endif
9132
9133
            srand(analogRead(0));
9134
            rand = trng_read_output_data(TRNG);
9135
        #elif defined(__STM32__)
9136
            /* TODO: confirm this is proper random number on Arduino STM32 */
9137
            #warning "Not yet tested on STM32 targets"
9138
            rand = random();
9139
        #else
9140
            /* TODO: Pull requests appreciated for new targets.
9141
             * Do *all* other Arduino boards support random()?
9142
             * Probably not 100%, but most will likely work: */
9143
            rand = random();
9144
        #endif
9145
9146
            XMEMCPY(output, &rand, len);
9147
            output += len;
9148
            sz -= len;
9149
        }
9150
9151
        return ret;
9152
    }
9153
9154
#elif defined(WOLFSSL_ESPIDF)
9155
9156
    /* Espressif */
9157
    #if defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE)
9158
9159
        /* Espressif ESP32 */
9160
        #include <esp_system.h>
9161
        #if defined(CONFIG_IDF_TARGET_ESP32S2) || \
9162
            defined(CONFIG_IDF_TARGET_ESP32S3)
9163
            #include <esp_random.h>
9164
        #endif
9165
9166
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9167
        {
9168
            word32 rand;
9169
            while (sz > 0) {
9170
                word32 len = sizeof(rand);
9171
                if (sz < len)
9172
                    len = sz;
9173
                /* Get one random 32-bit word from hw RNG */
9174
                rand = esp_random( );
9175
                XMEMCPY(output, &rand, len);
9176
                output += len;
9177
                sz -= len;
9178
            }
9179
9180
            return 0;
9181
        }
9182
9183
    #elif defined(WOLFSSL_ESP8266)
9184
9185
        /* Espressif ESP8266 */
9186
        #include <esp_system.h>
9187
9188
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9189
        {
9190
    #if defined(DEBUG_WOLFSSL)
9191
            WOLFSSL_ENTER("ESP8266 Random");
9192
    #endif
9193
            word32 rand;
9194
            while (sz > 0) {
9195
                word32 len = sizeof(rand);
9196
                if (sz < len)
9197
                    len = sz;
9198
                /* Get one random 32-bit word from hw RNG */
9199
                rand = esp_random( );
9200
                XMEMCPY(output, &rand, len);
9201
                output += len;
9202
                sz -= len;
9203
            }
9204
9205
            return 0;
9206
        }
9207
    #endif /* end WOLFSSL_ESPIDF */
9208
9209
#elif defined(WOLFSSL_LINUXKM)
9210
9211
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9212
    {
9213
        (void)os;
9214
        int ret = WC_NO_ERR_TRACE(RNG_FAILURE_E);
9215
9216
    #ifdef HAVE_ENTROPY_MEMUSE
9217
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
9218
        if (ret == 0)
9219
            return 0;
9220
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
9221
        return ret;
9222
        #endif
9223
    #endif
9224
9225
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
9226
        if (IS_INTEL_RDSEED(intel_flags)) {
9227
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
9228
            if (ret == 0)
9229
                return 0;
9230
            #ifdef FORCE_FAILURE_RDSEED
9231
            return ret;
9232
            #endif
9233
        }
9234
    #ifdef FORCE_FAILURE_RDSEED
9235
        else {
9236
            /* Don't fall back to get_random_bytes() */
9237
            return MISSING_RNG_E;
9238
        }
9239
    #endif
9240
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
9241
9242
    #ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
9243
        #if !defined(HAVE_ENTROPY_MEMUSE) && \
9244
            !defined(HAVE_INTEL_RDSEED) && \
9245
            !defined(HAVE_AMD_RDSEED)
9246
            #error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires an intrinsic entropy source.
9247
        #else
9248
            return ret;
9249
        #endif
9250
    #else
9251
        (void)ret;
9252
9253
        get_random_bytes(output, sz);
9254
        return 0;
9255
    #endif
9256
    }
9257
9258
#elif defined(WOLFSSL_BSDKM)
9259
    #include <sys/random.h>
9260
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9261
    {
9262
        (void)os;
9263
        int ret = WC_NO_ERR_TRACE(RNG_FAILURE_E);
9264
9265
    #ifdef HAVE_ENTROPY_MEMUSE
9266
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
9267
        if (ret == 0) {
9268
            return 0;
9269
        }
9270
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
9271
        /* Don't fallback to /dev/urandom. */
9272
        return ret;
9273
        #endif
9274
    #endif
9275
9276
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
9277
        if (IS_INTEL_RDSEED(intel_flags)) {
9278
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
9279
        #ifndef FORCE_FAILURE_RDSEED
9280
            if (ret == 0)
9281
        #endif
9282
            {
9283
                return ret;
9284
            }
9285
        }
9286
    #ifdef FORCE_FAILURE_RDSEED
9287
        else {
9288
            /* Don't fall back to arc4random_buf() */
9289
            return MISSING_RNG_E;
9290
        }
9291
    #endif
9292
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
9293
9294
        (void)ret;
9295
9296
        arc4random_buf(output, sz);
9297
        return 0;
9298
    }
9299
#elif defined(WOLFSSL_RENESAS_TSIP)
9300
9301
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9302
    {
9303
        (void)os;
9304
        return wc_tsip_GenerateRandBlock(output, sz);
9305
    }
9306
9307
9308
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
9309
    #include "hal_data.h"
9310
9311
    #ifndef WOLFSSL_SCE_TRNG_HANDLE
9312
        #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng
9313
    #endif
9314
9315
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9316
    {
9317
        word32 ret;
9318
        word32 blocks;
9319
        word32 len = sz;
9320
9321
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
9322
                                                  WOLFSSL_SCE_TRNG_HANDLE.p_cfg);
9323
        if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) {
9324
            /* error opening TRNG driver */
9325
            return -1;
9326
        }
9327
9328
        blocks = sz / sizeof(word32);
9329
        if (blocks > 0) {
9330
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
9331
                                                       (word32*)output, blocks);
9332
            if (ret != SSP_SUCCESS) {
9333
                return -1;
9334
            }
9335
        }
9336
9337
        len = len - (blocks * sizeof(word32));
9338
        if (len > 0) {
9339
            word32 tmp;
9340
9341
            if (len > sizeof(word32)) {
9342
                return -1;
9343
            }
9344
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
9345
                                                      (word32*)&tmp, 1);
9346
            if (ret != SSP_SUCCESS) {
9347
                return -1;
9348
            }
9349
            XMEMCPY(output + (blocks * sizeof(word32)), (byte*)&tmp, len);
9350
        }
9351
9352
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl);
9353
        if (ret != SSP_SUCCESS) {
9354
            /* error opening TRNG driver */
9355
            return -1;
9356
        }
9357
        return 0;
9358
    }
9359
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
9360
    /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
9361
     * extern int myRngFunc(byte* output, word32 sz);
9362
     */
9363
9364
#elif defined(__MICROBLAZE__)
9365
    #warning weak source of entropy
9366
    #define LPD_SCNTR_BASE_ADDRESS 0xFF250000
9367
9368
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9369
    {
9370
        word32* cnt;
9371
        word32 i;
9372
9373
        /* using current time with srand */
9374
        cnt = (word32*)LPD_SCNTR_BASE_ADDRESS;
9375
        srand(*cnt | *(cnt+1));
9376
9377
        for (i = 0; i < sz; i++)
9378
            output[i] = rand();
9379
9380
        (void)os;
9381
        return 0;
9382
    }
9383
9384
#elif defined(WOLFSSL_ZEPHYR)
9385
9386
    #ifdef __has_include
9387
        #if __has_include(<zephyr/version.h>)
9388
            #include <zephyr/version.h>
9389
        #else
9390
            #include <version.h>
9391
        #endif
9392
    #else
9393
        #include <version.h>
9394
    #endif
9395
9396
    #include <sys/types.h>
9397
9398
    #if KERNEL_VERSION_NUMBER >= 0x30500
9399
        #include <zephyr/random/random.h>
9400
    #else
9401
        #if KERNEL_VERSION_NUMBER >= 0x30100
9402
            #include <zephyr/random/rand32.h>
9403
        #else
9404
            #include <random/rand32.h>
9405
        #endif
9406
    #endif
9407
9408
    #if KERNEL_VERSION_NUMBER >= 0x40300
9409
        #include <time.h>
9410
    #elif KERNEL_VERSION_NUMBER >= 0x30100
9411
        #include <zephyr/posix/time.h>
9412
    #else
9413
        #include <posix/time.h>
9414
    #endif
9415
9416
    #if KERNEL_VERSION_NUMBER >= 0x30100
9417
        #include <zephyr/devicetree.h>
9418
    #else
9419
        #include <devicetree.h>
9420
    #endif
9421
9422
    #if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy)
9423
        #if KERNEL_VERSION_NUMBER >= 0x30100
9424
            #include <zephyr/device.h>
9425
            #include <zephyr/drivers/entropy.h>
9426
        #else
9427
            #include <device.h>
9428
            #include <drivers/entropy.h>
9429
        #endif
9430
    #endif
9431
9432
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9433
    {
9434
    /* Seed the DRBG straight from the hardware entropy driver when the platform
9435
     * exposes one (a zephyr,entropy chosen node), so wolfCrypt gets
9436
     * cryptographic-quality seed material instead of the general-purpose
9437
     * sys_rand_get(). A dead source returns an error, which makes wc_InitRng()
9438
     * fail (RNG_FAILURE_E) rather than yield weak output. Boards that set
9439
     * CONFIG_ENTROPY_HAS_DRIVER without a chosen entropy node fall back to
9440
     * sys_rand_get() rather than failing the build. */
9441
    #if defined(CONFIG_ENTROPY_HAS_DRIVER) && DT_HAS_CHOSEN(zephyr_entropy)
9442
        const struct device *dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
9443
        word32 off = 0;
9444
        word32 rem;
9445
        uint16_t chunk;
9446
9447
        (void)os;
9448
        if (!device_is_ready(dev)) {
9449
            return RNG_FAILURE_E;
9450
        }
9451
        /* entropy_get_entropy() takes a uint16_t length; chunk the request so
9452
         * any word32 seed size is honored without silent truncation. */
9453
        while (off < sz) {
9454
            rem = sz - off;
9455
            chunk = (rem > 0xFFFFU) ? (uint16_t)0xFFFFU : (uint16_t)rem;
9456
            if (entropy_get_entropy(dev, (uint8_t *)output + off, chunk) != 0) {
9457
                return RNG_FAILURE_E;
9458
            }
9459
            off += chunk;
9460
        }
9461
        return 0;
9462
    #else
9463
        (void)os;
9464
        sys_rand_get(output, sz);
9465
        return 0;
9466
    #endif
9467
    }
9468
9469
#elif defined(WOLFSSL_TELIT_M2MB)
9470
9471
        #include "stdlib.h"
9472
        static long get_timestamp(void) {
9473
            long myTime = 0;
9474
            INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
9475
            if (fd >= 0) {
9476
                M2MB_RTC_TIMEVAL_T timeval;
9477
                m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
9478
                myTime = timeval.msec;
9479
                m2mb_rtc_close(fd);
9480
            }
9481
            return myTime;
9482
        }
9483
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9484
        {
9485
            int i;
9486
            srand(get_timestamp());
9487
            for (i = 0; i < sz; i++ ) {
9488
                output[i] = rand() % 256;
9489
                if ((i % 8) == 7) {
9490
                    srand(get_timestamp());
9491
                }
9492
            }
9493
            return 0;
9494
        }
9495
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_TRNG)
9496
     #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
9497
9498
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz){
9499
        (void)os;
9500
9501
        if (output == NULL) {
9502
            return BUFFER_E;
9503
        }
9504
        return se050_get_random_number(sz, output);
9505
    }
9506
9507
#elif defined(WOLFSSL_NXP_RNG_1)
9508
    #include "fsl_rng.h"
9509
9510
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
9511
        (void)os;
9512
9513
        if (output == NULL) {
9514
            return BUFFER_E;
9515
        }
9516
9517
        if (RNG_GetRandomData(RNG, output, sz) != kStatus_Success)
9518
            return RNG_FAILURE_E;
9519
9520
        return 0;
9521
    }
9522
9523
#elif defined(WOLFSSL_VA416X0_TRNG)
9524
    /* Vorago VA416x0 hardware TRNG (an Arm CryptoCell-style entropy block).
9525
     * Used to seed the SP800-90A Hash-DRBG (keep HAVE_HASHDRBG enabled); the
9526
     * TRNG yields only ~1.25 kb/s of entropy, so the DRBG expands it.
9527
     *
9528
     * Build: define WOLFSSL_VA416X0_TRNG, and have the VA416xx SDK header
9529
     * "va416xx.h" on the include path (provides VOR_SYSCONFIG / VOR_TRNG and
9530
     * the register field macros). There is no SDK HAL driver for the TRNG, so
9531
     * it is accessed at the register level below. The tuning macros
9532
     * WOLFSSL_VA416X0_TRNG_SAMPLE_CNT, WOLFSSL_VA416X0_TRNG_MAX_RETRY and
9533
     * WOLFSSL_VA416X0_TRNG_TIMEOUT have overridable defaults defined below.
9534
     *
9535
     * Note: the TRNG PERIPHERAL_RESET bit is active low and must be released
9536
     * or every TRNG register write is silently ignored. */
9537
    #include "va416xx.h"
9538
9539
    /* Ring-oscillator sample count (must be non-zero). May need tuning on
9540
     * hardware: too low results in repeated autocorrelation/CRNGT errors. */
9541
    #ifndef WOLFSSL_VA416X0_TRNG_SAMPLE_CNT
9542
        #define WOLFSSL_VA416X0_TRNG_SAMPLE_CNT 1000
9543
    #endif
9544
    #ifndef WOLFSSL_VA416X0_TRNG_MAX_RETRY
9545
        #define WOLFSSL_VA416X0_TRNG_MAX_RETRY 10
9546
    #endif
9547
    /* Max poll iterations waiting for one 192-bit entropy block before
9548
     * giving up (guards against a non-responsive TRNG). */
9549
    #ifndef WOLFSSL_VA416X0_TRNG_TIMEOUT
9550
        #define WOLFSSL_VA416X0_TRNG_TIMEOUT 1000000
9551
    #endif
9552
    #if WOLFSSL_VA416X0_TRNG_SAMPLE_CNT == 0
9553
        #error "WOLFSSL_VA416X0_TRNG_SAMPLE_CNT must be non-zero"
9554
    #endif
9555
    #if WOLFSSL_VA416X0_TRNG_TIMEOUT == 0
9556
        #error "WOLFSSL_VA416X0_TRNG_TIMEOUT must be non-zero"
9557
    #endif
9558
9559
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9560
    {
9561
        word32 i;
9562
        word32 reg;
9563
        word32 chunk;
9564
        word32 timeout;
9565
        word32 entropy[6]; /* 192-bit entropy holding register */
9566
        int retry;
9567
        int ret;
9568
9569
        (void)os;
9570
9571
        if (output == NULL) {
9572
            return BUFFER_E;
9573
        }
9574
9575
        /* serialize access to the shared TRNG hardware */
9576
        ret = wolfSSL_CryptHwMutexLock();
9577
        if (ret != 0) {
9578
            return ret;
9579
        }
9580
9581
        /* enable the TRNG peripheral clock and release it from reset (the
9582
         * reset bit is active low: 0 = held in reset, 1 = released) */
9583
        VOR_SYSCONFIG->PERIPHERAL_CLK_ENABLE |=
9584
            SYSCONFIG_PERIPHERAL_CLK_ENABLE_TRNG_Msk;
9585
        VOR_SYSCONFIG->PERIPHERAL_RESET |=
9586
            SYSCONFIG_PERIPHERAL_RESET_TRNG_Msk;
9587
9588
        /* mask all interrupts (poll instead) and clear any stale status */
9589
        VOR_TRNG->IMR = TRNG_IMR_EHR_VALID_INT_MASK_Msk |
9590
                        TRNG_IMR_AUTOCORR_ERR_INT_MASK_Msk |
9591
                        TRNG_IMR_CRNGT_ERR_INT_MASK_Msk |
9592
                        TRNG_IMR_VN_ERR_INT_MASK_Msk;
9593
        VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk | TRNG_ICR_AUTOCORR_ERR_Msk |
9594
                        TRNG_ICR_CRNGT_ERR_Msk | TRNG_ICR_VN_ERR_Msk;
9595
9596
        /* CONFIG = 0 sets RND_SRC_SEL = 0, which selects the ring-oscillator
9597
         * entropy source (per the VA416x0 reference manual) and clears the
9598
         * rest of the register; set the sample rate and keep the health tests
9599
         * enabled (no DEBUG_CONTROL bypass) */
9600
        VOR_TRNG->CONFIG = 0;
9601
        VOR_TRNG->SAMPLE_CNT1 = WOLFSSL_VA416X0_TRNG_SAMPLE_CNT;
9602
        VOR_TRNG->DEBUG_CONTROL = 0;
9603
9604
        for (i = 0; i < sz; ) {
9605
            retry = 0;
9606
            timeout = WOLFSSL_VA416X0_TRNG_TIMEOUT;
9607
9608
            /* start entropy collection */
9609
            VOR_TRNG->RND_SOURCE_ENABLE =
9610
                TRNG_RND_SOURCE_ENABLE_RND_SRC_EN_Msk;
9611
9612
            for (;;) {
9613
                reg = VOR_TRNG->ISR;
9614
                if ((reg & (TRNG_ISR_AUTOCORR_ERR_Msk |
9615
                            TRNG_ISR_CRNGT_ERR_Msk |
9616
                            TRNG_ISR_VN_ERR_Msk)) != 0) {
9617
                    /* health-test failure: stop, then clear the error flags
9618
                     * and any latched EHR_VALID so a stale/invalid block is
9619
                     * not consumed on the next iteration, then re-collect */
9620
                    VOR_TRNG->RND_SOURCE_ENABLE = 0;
9621
                    VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk |
9622
                                    TRNG_ICR_AUTOCORR_ERR_Msk |
9623
                                    TRNG_ICR_CRNGT_ERR_Msk |
9624
                                    TRNG_ICR_VN_ERR_Msk;
9625
                    if (++retry > WOLFSSL_VA416X0_TRNG_MAX_RETRY) {
9626
                        ForceZero(entropy, sizeof(entropy));
9627
                        wolfSSL_CryptHwMutexUnLock();
9628
                        return RNG_FAILURE_E;
9629
                    }
9630
                    timeout = WOLFSSL_VA416X0_TRNG_TIMEOUT;
9631
                    VOR_TRNG->RND_SOURCE_ENABLE =
9632
                        TRNG_RND_SOURCE_ENABLE_RND_SRC_EN_Msk;
9633
                    continue;
9634
                }
9635
                if ((VOR_TRNG->VALID & TRNG_VALID_EHR_VALID_Msk) != 0) {
9636
                    break;
9637
                }
9638
                if (--timeout == 0) {
9639
                    VOR_TRNG->RND_SOURCE_ENABLE = 0;
9640
                    ForceZero(entropy, sizeof(entropy));
9641
                    wolfSSL_CryptHwMutexUnLock();
9642
                    return RNG_FAILURE_E;
9643
                }
9644
            }
9645
9646
            /* read 192 bits of entropy (6 x 32-bit words) */
9647
            entropy[0] = VOR_TRNG->EHR_DATA0;
9648
            entropy[1] = VOR_TRNG->EHR_DATA1;
9649
            entropy[2] = VOR_TRNG->EHR_DATA2;
9650
            entropy[3] = VOR_TRNG->EHR_DATA3;
9651
            entropy[4] = VOR_TRNG->EHR_DATA4;
9652
            entropy[5] = VOR_TRNG->EHR_DATA5;
9653
9654
            /* reading EHR_DATA clears EHR_VALID; stop the source and ack */
9655
            VOR_TRNG->RND_SOURCE_ENABLE = 0;
9656
            VOR_TRNG->ICR = TRNG_ICR_EHR_VALID_Msk;
9657
9658
            chunk = sz - i;
9659
            if (chunk > sizeof(entropy)) {
9660
                chunk = sizeof(entropy);
9661
            }
9662
            XMEMCPY(&output[i], (byte*)entropy, chunk);
9663
            i += chunk;
9664
        }
9665
9666
        ForceZero(entropy, sizeof(entropy)); /* scrub seed material from stack */
9667
        wolfSSL_CryptHwMutexUnLock();
9668
        return 0;
9669
    }
9670
9671
#elif defined(WOLFSSL_C2000_ENTROPY)
9672
    /* TI C2000 (C28x) oscillator-jitter entropy source.  The part has no
9673
     * TRNG; the noise bit is the LSB of a Dual-Clock Comparator measurement,
9674
     * oversampled past its measured min-entropy, health-tested per SP800-90B
9675
     * 4.4 and SHA-256 conditioned before feeding the Hash-DRBG.
9676
     *
9677
     * Build: define WOLFSSL_C2000_ENTROPY and add
9678
     * wolfcrypt/src/port/ti/ti-c2000-entropy.c with the C2000Ware driverlib
9679
     * headers on the include path.  Tuning macros, hardware overrides and the
9680
     * characterization: wolfssl/wolfcrypt/port/ti/ti-c2000-entropy.h and
9681
     * IDE/C2000/README.md.
9682
     *
9683
     * Blocking by design: ~26 ms per 32-octet chunk per source at the default
9684
     * window, ~100 ms for a typical seed, ~420 ms for the one-time startup
9685
     * test.  Fine at boot, not for a control loop. */
9686
    #if !defined(HAVE_HASHDRBG)
9687
        #error "WOLFSSL_C2000_ENTROPY expects HAVE_HASHDRBG to expand the seed"
9688
    #endif
9689
9690
    #include <wolfssl/wolfcrypt/port/ti/ti-c2000-entropy.h>
9691
9692
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9693
    {
9694
        (void)os;
9695
9696
        if (output == NULL) {
9697
            return BUFFER_E;
9698
        }
9699
9700
        return wc_c2000_GenerateSeed(output, sz);
9701
    }
9702
9703
#elif defined(DOLPHIN_EMULATOR) || defined (WOLFSSL_NDS)
9704
9705
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9706
        {
9707
            word32 i;
9708
            (void)os;
9709
            srand(time(NULL));
9710
            for (i = 0; i < sz; i++)
9711
                output[i] = (byte)rand();
9712
            return 0;
9713
        }
9714
#elif defined(WOLFSSL_MAXQ108X) || defined(WOLFSSL_MAXQ1065)
9715
9716
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9717
    {
9718
        (void)os;
9719
9720
        return maxq10xx_random(output, sz);
9721
    }
9722
#elif defined(MAX3266X_RNG)
9723
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9724
    {
9725
        int status;
9726
        static int initDone = 0;
9727
        (void)os;
9728
        if (initDone == 0) {
9729
            status = wolfSSL_HwRngMutexLock();
9730
            if (status != 0) {
9731
                return status;
9732
            }
9733
            if(MXC_TRNG_HealthTest() != 0) {
9734
                #ifdef DEBUG_WOLFSSL
9735
                WOLFSSL_MSG("TRNG HW Health Test Failed");
9736
                #endif /* DEBUG_WOLFSSL */
9737
                wolfSSL_HwRngMutexUnLock();
9738
                return WC_HW_E;
9739
            }
9740
            wolfSSL_HwRngMutexUnLock();
9741
            initDone = 1;
9742
        }
9743
        return wc_MXC_TRNG_Random(output, sz);
9744
    }
9745
9746
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
9747
9748
    /* Infineon/Cypress HAL RNG implementation */
9749
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9750
    {
9751
        cyhal_trng_t obj;
9752
        cy_rslt_t result;
9753
        uint32_t val;
9754
        word32 i = 0;
9755
9756
        (void)os;
9757
9758
        result = cyhal_trng_init(&obj);
9759
        if (result == CY_RSLT_SUCCESS) {
9760
            while (i < sz) {
9761
                /* If not aligned or there is odd/remainder add single byte */
9762
                if( (i + sizeof(word32)) > sz ||
9763
                    ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
9764
                ) {
9765
                    val = cyhal_trng_generate(&obj);
9766
                    output[i++] = (byte)val;
9767
                }
9768
                else {
9769
                    /* Use native 32 instruction */
9770
                    val = cyhal_trng_generate(&obj);
9771
                    *((uint32_t*)&output[i]) = val;
9772
                    i += sizeof(word32);
9773
                }
9774
            }
9775
            cyhal_trng_free(&obj);
9776
        }
9777
        return 0;
9778
    }
9779
9780
#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
9781
      defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
9782
      defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
9783
      defined(WOLFSSL_LPC43xx)  || defined(NO_STM32_RNG) || \
9784
      defined(MBED)             || defined(WOLFSSL_EMBOS) || \
9785
      defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
9786
      defined(WOLFSSL_CONTIKI)  || defined(WOLFSSL_AZSPHERE)
9787
9788
    /* these platforms do not have a default random seed and
9789
       you'll need to implement your own wc_GenerateSeed or define via
9790
       CUSTOM_RAND_GENERATE_BLOCK */
9791
9792
    #define USE_TEST_GENSEED
9793
9794
#elif defined(NO_DEV_RANDOM)
9795
9796
    /* Allow bare-metal targets to use cryptoCb as seed provider */
9797
    #if defined(WOLF_CRYPTO_CB)
9798
9799
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9800
    {
9801
        int ret = WC_NO_ERR_TRACE(WC_HW_E);
9802
9803
        #ifndef WOLF_CRYPTO_CB_FIND
9804
        if (os->devId != INVALID_DEVID)
9805
        #endif
9806
        {
9807
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
9808
            if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
9809
                ret = WC_HW_E;
9810
            }
9811
        }
9812
9813
        return ret;
9814
    }
9815
9816
    #else /* defined(WOLF_CRYPTO_CB)*/
9817
9818
    #error "you need to write an os specific wc_GenerateSeed() here"
9819
9820
    /*
9821
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9822
    {
9823
        return 0;
9824
    }
9825
    */
9826
9827
   #endif  /* !defined(WOLF_CRYPTO_CB) */
9828
9829
#else
9830
9831
    /* may block */
9832
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
9833
0
    {
9834
0
        int ret = 0;
9835
    /* Same condition as the seed-device block below: with
9836
     * ENTROPY_MEMUSE_FORCE_FAILURE the code that uses these is compiled out,
9837
     * and declaring them anyway is an unused-variable error under -Werror. */
9838
    #if defined(WC_RNG_SEED_DEVICE) && (!defined(HAVE_ENTROPY_MEMUSE) || \
9839
        !defined(ENTROPY_MEMUSE_FORCE_FAILURE))
9840
        byte*  devOut;
9841
        word32 devSz;
9842
        int    devFd;
9843
        int    devLen;
9844
    #endif
9845
9846
        /* Validate output before any entropy backend dereferences it: some
9847
         * (e.g. glibc's vDSO getrandom()) fault on a NULL buffer rather than
9848
         * returning an error. Mirrors wc_RNG_GenerateBlock's NULL check. */
9849
0
        if (os == NULL || output == NULL) {
9850
0
            return BAD_FUNC_ARG;
9851
0
        }
9852
9853
    #ifdef WOLF_CRYPTO_CB
9854
        #ifndef WOLF_CRYPTO_CB_FIND
9855
        if (os->devId != INVALID_DEVID)
9856
        #endif
9857
        {
9858
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
9859
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
9860
                return ret;
9861
            /* fall-through when unavailable */
9862
            ret = 0; /* reset error code */
9863
        }
9864
    #endif
9865
9866
    #ifdef HAVE_ENTROPY_MEMUSE
9867
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
9868
        if (ret == 0) {
9869
            /* success, we're done */
9870
            return ret;
9871
        }
9872
    #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
9873
        /* Don't fall back to /dev/urandom. */
9874
        return ret;
9875
    #else
9876
        /* Reset error and fall back to using /dev/urandom. */
9877
        ret = 0;
9878
    #endif
9879
    #endif
9880
9881
0
    #if !defined(HAVE_ENTROPY_MEMUSE) || !defined(ENTROPY_MEMUSE_FORCE_FAILURE)
9882
9883
    #ifdef WC_RNG_SEED_DEVICE
9884
        /* Nominated entropy source, usually a hardware RNG. Best effort: on
9885
         * any failure fall through to the default sources below. Those refill
9886
         * the whole request from the start, so bytes a partial read left in
9887
         * output are overwritten rather than mixed in. */
9888
        devOut = output;
9889
        devSz  = sz;
9890
        devFd  = wc_open_cloexec(WC_RNG_SEED_DEVICE, O_RDONLY);
9891
        if (devFd != XBADFD) {
9892
            while (devSz > 0) {
9893
                errno = 0;
9894
                devLen = (int)read(devFd, devOut, devSz);
9895
                if (devLen < 0) {
9896
                    if (errno == EINTR)
9897
                        continue; /* interrupted, read again */
9898
                    break;
9899
                }
9900
                if (devLen == 0)
9901
                    break;        /* at EOF, will never fill the request */
9902
9903
                devSz  -= (word32)devLen;
9904
                devOut += devLen;
9905
            }
9906
            close(devFd);
9907
        }
9908
        #if defined(DEBUG_WOLFSSL)
9909
            if (devSz == 0)
9910
                WOLFSSL_MSG("seeded from WC_RNG_SEED_DEVICE.");
9911
            else
9912
                WOLFSSL_MSG("WC_RNG_SEED_DEVICE unusable, using default.");
9913
        #endif /* DEBUG_WOLFSSL */
9914
        if (devSz == 0) {
9915
            /* success, we're done */
9916
            return 0;
9917
        }
9918
    #endif /* WC_RNG_SEED_DEVICE */
9919
9920
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
9921
        if (IS_INTEL_RDSEED(intel_flags)) {
9922
             ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
9923
             if (ret == 0) {
9924
                 /* success, we're done */
9925
                 return ret;
9926
             }
9927
        #ifdef FORCE_FAILURE_RDSEED
9928
             /* Don't fall back to /dev/urandom. */
9929
             return ret;
9930
        #else
9931
             /* Reset error and fall back to using /dev/urandom. */
9932
             ret = 0;
9933
        #endif
9934
        }
9935
    #ifdef FORCE_FAILURE_RDSEED
9936
        else {
9937
            /* Don't fall back to /dev/urandom */
9938
            return MISSING_RNG_E;
9939
        }
9940
    #endif
9941
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
9942
9943
0
    #if (!defined(HAVE_INTEL_RDSEED) && !defined(HAVE_AMD_RDSEED)) || \
9944
0
        !defined(FORCE_FAILURE_RDSEED)
9945
9946
0
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
9947
0
        {
9948
0
            word32 grSz = sz;
9949
0
            byte* grOutput = output;
9950
9951
0
            while (grSz) {
9952
0
                ssize_t len;
9953
9954
0
                errno = 0;
9955
0
                len = getrandom(grOutput, grSz, 0);
9956
0
                if (len == -1) {
9957
0
                    if (errno == EINTR) {
9958
                        /* interrupted, call getrandom again */
9959
0
                        continue;
9960
0
                    }
9961
0
                    else {
9962
0
                        ret = READ_RAN_E;
9963
0
                    }
9964
0
                    break;
9965
0
                }
9966
9967
0
                grSz     -= (word32)len;
9968
0
                grOutput += len;
9969
0
            }
9970
0
            if (ret == 0)
9971
0
                return ret;
9972
        #ifdef FORCE_FAILURE_GETRANDOM
9973
            /* don't fall back to /dev/urandom */
9974
            return ret;
9975
        #elif !defined(NO_FILESYSTEM)
9976
            /* reset error and fall back to using /dev/urandom if filesystem
9977
             * support is compiled in */
9978
0
            ret = 0;
9979
0
        #endif
9980
0
        }
9981
0
    #endif
9982
9983
0
#ifndef NO_FILESYSTEM
9984
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
9985
        if (!os->seedFdOpen)
9986
        {
9987
            os->fd = XBADFD;
9988
        #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
9989
            if (os->fd == XBADFD) {
9990
                os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
9991
            #if defined(DEBUG_WOLFSSL)
9992
                if (os->fd != XBADFD)
9993
                    WOLFSSL_MSG("opened /dev/urandom.");
9994
            #endif /* DEBUG_WOLFSSL */
9995
            }
9996
        #endif /* NO_DEV_URANDOM */
9997
            if (os->fd == XBADFD) {
9998
                /* may still have /dev/random */
9999
                os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
10000
            #if defined(DEBUG_WOLFSSL)
10001
                if (os->fd != XBADFD)
10002
                    WOLFSSL_MSG("opened /dev/random.");
10003
            #endif /* DEBUG_WOLFSSL */
10004
                if (os->fd == XBADFD)
10005
                    return OPEN_RAN_E;
10006
                os->keepSeedFdOpen = 0;
10007
                os->seedFdOpen = 1;
10008
            }
10009
            else {
10010
                os->keepSeedFdOpen = 1;
10011
                os->seedFdOpen = 1;
10012
            }
10013
        }
10014
    #else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
10015
0
        os->fd = XBADFD;
10016
0
    #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
10017
0
        if (os->fd == XBADFD) {
10018
0
            os->fd = wc_open_cloexec("/dev/urandom", O_RDONLY);
10019
        #if defined(DEBUG_WOLFSSL)
10020
            if (os->fd != XBADFD)
10021
                WOLFSSL_MSG("opened /dev/urandom.");
10022
        #endif /* DEBUG_WOLFSSL */
10023
0
        }
10024
0
    #endif /* !NO_DEV_URANDOM */
10025
0
        if (os->fd == XBADFD) {
10026
            /* may still have /dev/random */
10027
0
            os->fd = wc_open_cloexec("/dev/random", O_RDONLY);
10028
        #if defined(DEBUG_WOLFSSL)
10029
            if (os->fd != XBADFD)
10030
                WOLFSSL_MSG("opened /dev/random.");
10031
        #endif /* DEBUG_WOLFSSL */
10032
0
            if (os->fd == XBADFD)
10033
0
                return OPEN_RAN_E;
10034
0
        }
10035
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
10036
    #if defined(DEBUG_WOLFSSL)
10037
        WOLFSSL_MSG("rnd read...");
10038
    #endif /* DEBUG_WOLFSSL */
10039
0
        while (sz) {
10040
0
            int len = (int)read(os->fd, output, sz);
10041
            /* EOF never fills the request, don't retry forever */
10042
0
            if (len <= 0) {
10043
0
                ret = READ_RAN_E;
10044
0
                break;
10045
0
            }
10046
10047
0
            sz     -= (word32)len;
10048
0
            output += len;
10049
10050
0
            if (sz) {
10051
    #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
10052
                sleep(0);             /* context switch */
10053
    #else
10054
0
                ret = RAN_BLOCK_E;
10055
0
                break;
10056
0
    #endif /* BLOCKING || WC_RNG_BLOCKING */
10057
0
            }
10058
0
        }
10059
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
10060
        if (!os->keepSeedFdOpen && os->seedFdOpen)
10061
        {
10062
            close(os->fd);
10063
            os->fd = -1;
10064
            os->seedFdOpen = 0;
10065
        }
10066
    #else
10067
0
        close(os->fd);
10068
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
10069
#else /* NO_FILESYSTEM */
10070
        (void)output;
10071
        (void)sz;
10072
        ret = NOT_COMPILED_IN;
10073
#endif /* NO_FILESYSTEM */
10074
10075
0
        return ret;
10076
10077
0
    #endif /* (!HAVE_INTEL_RDSEED && !HAVE_AMD_RDSEED) || !FORCE_FAILURE_RDSEED */
10078
10079
0
    #endif /*!HAVE_ENTROPY_MEMUSE || !ENTROPY_MEMUSE_FORCE_FAILURE */
10080
10081
0
    }
10082
10083
#endif
10084
10085
#ifdef USE_TEST_GENSEED
10086
    #if !defined(_MSC_VER) && !defined(__TASKING__)
10087
        #warning "write a real random seed!!!!, just for testing now"
10088
    #else
10089
        #pragma message("Warning: write a real random seed!!!!, just for testing now")
10090
    #endif
10091
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
10092
    {
10093
        word32 i;
10094
        /* WC_OCTET, not (byte): the cast does not truncate where
10095
         * CHAR_BIT != 8, so sz > 256 would emit values above 0xFF. */
10096
        for (i = 0; i < sz; i++ )
10097
            output[i] = WC_OCTET(i);
10098
10099
        (void)os;
10100
10101
        return 0;
10102
    }
10103
#endif
10104
/* End wc_GenerateSeed */
10105
10106
#if defined(CUSTOM_RAND_GENERATE_BLOCK) && defined(WOLFSSL_KCAPI)
10107
#include <fcntl.h>
10108
int wc_hwrng_generate_block(byte *output, word32 sz)
10109
{
10110
    int fd;
10111
    int ret = 0;
10112
    fd = wc_open_cloexec("/dev/hwrng", O_RDONLY);
10113
    if (fd == -1)
10114
        return OPEN_RAN_E;
10115
    while(sz)
10116
    {
10117
        int len = (int)read(fd, output, sz);
10118
        if (len == -1)
10119
        {
10120
            ret = READ_RAN_E;
10121
            break;
10122
        }
10123
        sz -= len;
10124
        output += len;
10125
    }
10126
    close(fd);
10127
    return ret;
10128
}
10129
#endif
10130
10131
#ifdef WC_RNG_DEBUG_STATS
10132
10133
/* Note on WC_RNG_DEBUG_STATS collection points:
10134
 *
10135
 * Placement doctrine: each counter is maintained at the single funnel that
10136
 * owns the distinction it records --
10137
 *
10138
 *   - reseed counts in Hash_DRBG_Reseed() (every reseed flavor routes
10139
 *     through it: interval backstop, Reseed_Now, RBGC, banked redemption);
10140
 *   - request/byte counts in the DRBG arm of wc_RNG_GenerateBlock()
10141
 *     (hardware-offload arms -- RDRAND, Silabs, async, cryptocb, custom --
10142
 *     are deliberately uncounted: these are DRBG-facility statistics);
10143
 *   - banked-seed redemption provenance in wc_RNG_DRBG_NextSeedNow_Nonce();
10144
 *   - seed health failures at the two sites that observe them per-instance
10145
 *     (PollAndReSeed(), NextSeedGenerate);
10146
 *   - chain-provenance bytes (RBGC_bytes_produced: output generated while
10147
 *     the instance's own RBGCStratum > 0) in the same generate funnel;
10148
 *   - pool byte accounting in wc_RNG_Pool_Extract(), under the consumer's
10149
 *     instance lock: bytes produced by reading from the pool, and bytes
10150
 *     requested but not fulfilled (empty-pool and partial-serve shortfall),
10151
 *     so requested == produced + missed on the capacity paths.  The
10152
 *     failed-DRBG burn path deliberately counts nothing: it is a failure
10153
 *     event (visible via rng->status), not a capacity signal.
10154
 *
10155
 * Counters are plain (non-atomic) adds/increments, and update under the owner's
10156
 * exclusive access (the lock contract shared by all WC_RNG operations) except
10157
 * where labeled racy: those are unreliable under concurrency, by design.  Every
10158
 * site carries its own #ifdef WC_RNG_DEBUG_STATS gate so the facility is
10159
 * removable outright with unifdef.
10160
 */
10161
10162
WOLFSSL_API int wc_rng_debug_stats_snap(struct wc_rng_debug_stats_snapshot *s,
10163
                                        const WC_RNG *rng)
10164
{
10165
    if ((s == NULL) || (rng == NULL))
10166
        return BAD_FUNC_ARG;
10167
10168
    s->_stats_total_bytes_requested = rng->_stats_total_bytes_requested;
10169
    s->_stats_total_bytes_produced  = rng->_stats_total_bytes_produced;
10170
    s->_stats_total_requests        = rng->_stats_total_requests;
10171
    s->_stats_reseeds               = rng->_stats_reseeds;
10172
    s->_stats_stirs                 = rng->_stats_stirs;
10173
    s->_stats_seed_failures         = rng->_stats_seed_failures;
10174
    s->_stats_locks_taken           = rng->_stats_locks_taken;
10175
    s->_stats_locks_released        = rng->_stats_locks_released;
10176
    s->_stats_locks_refused         = rng->_stats_locks_refused;
10177
#ifdef WC_RNG_HAVE_RBGC
10178
    s->_stats_RBGC_bytes_produced   = rng->_stats_RBGC_bytes_produced;
10179
    s->_stats_RBGC_reseeds          = rng->_stats_RBGC_reseeds;
10180
#endif
10181
#ifdef WC_RNG_HAVE_POOL
10182
    s->_stats_pool_bytes_produced   = rng->_stats_pool_bytes_produced;
10183
    s->_stats_pool_bytes_missed     = rng->_stats_pool_bytes_missed;
10184
#endif
10185
#ifdef WC_RNG_HAVE_NEXT_SEED
10186
    s->_stats_nextseedsprimary_redeemed = rng->_stats_nextseedsprimary_redeemed;
10187
    s->_stats_nextseedsRBGC_redeemed = rng->_stats_nextseedsRBGC_redeemed;
10188
    s->_stats_nextstirs_redeemed    = rng->_stats_nextstirs_redeemed;
10189
    s->_stats_nextseedsbanked       = rng->_stats_nextseedsbanked;
10190
    s->_stats_nextstirs_banked      = rng->_stats_nextstirs_banked;
10191
#endif
10192
10193
    return 0;
10194
}
10195
10196
WOLFSSL_API int wc_rng_debug_stats_restore(
10197
    const struct wc_rng_debug_stats_snapshot *s,
10198
    WC_RNG *rng)
10199
{
10200
    if ((s == NULL) || (rng == NULL))
10201
        return BAD_FUNC_ARG;
10202
10203
    rng->_stats_total_bytes_requested = s->_stats_total_bytes_requested;
10204
    rng->_stats_total_bytes_produced  = s->_stats_total_bytes_produced;
10205
    rng->_stats_total_requests        = s->_stats_total_requests;
10206
    rng->_stats_reseeds               = s->_stats_reseeds;
10207
    rng->_stats_stirs                 = s->_stats_stirs;
10208
    rng->_stats_seed_failures         = s->_stats_seed_failures;
10209
    rng->_stats_locks_taken           = s->_stats_locks_taken;
10210
    rng->_stats_locks_released        = s->_stats_locks_released;
10211
    rng->_stats_locks_refused         = s->_stats_locks_refused;
10212
#ifdef WC_RNG_HAVE_RBGC
10213
    rng->_stats_RBGC_bytes_produced   = s->_stats_RBGC_bytes_produced;
10214
    rng->_stats_RBGC_reseeds          = s->_stats_RBGC_reseeds;
10215
#endif
10216
#ifdef WC_RNG_HAVE_POOL
10217
    rng->_stats_pool_bytes_produced   = s->_stats_pool_bytes_produced;
10218
    rng->_stats_pool_bytes_missed     = s->_stats_pool_bytes_missed;
10219
#endif
10220
#ifdef WC_RNG_HAVE_NEXT_SEED
10221
    rng->_stats_nextseedsprimary_redeemed = s->_stats_nextseedsprimary_redeemed;
10222
    rng->_stats_nextseedsRBGC_redeemed = s->_stats_nextseedsRBGC_redeemed;
10223
    rng->_stats_nextstirs_redeemed    = s->_stats_nextstirs_redeemed;
10224
    rng->_stats_nextseedsbanked       = s->_stats_nextseedsbanked;
10225
    rng->_stats_nextstirs_banked      = s->_stats_nextstirs_banked;
10226
#endif
10227
10228
    return 0;
10229
}
10230
10231
WOLFSSL_API int wc_rng_debug_stats_sum(struct wc_rng_debug_stats_snapshot *s,
10232
                                        const WC_RNG *rng)
10233
{
10234
    if ((s == NULL) || (rng == NULL))
10235
        return BAD_FUNC_ARG;
10236
10237
    s->_stats_total_bytes_requested += rng->_stats_total_bytes_requested;
10238
    s->_stats_total_bytes_produced  += rng->_stats_total_bytes_produced;
10239
    s->_stats_total_requests        += rng->_stats_total_requests;
10240
    s->_stats_reseeds               += rng->_stats_reseeds;
10241
    s->_stats_stirs                 += rng->_stats_stirs;
10242
    s->_stats_seed_failures         += rng->_stats_seed_failures;
10243
    s->_stats_locks_taken           += rng->_stats_locks_taken;
10244
    s->_stats_locks_released        += rng->_stats_locks_released;
10245
    s->_stats_locks_refused         += rng->_stats_locks_refused;
10246
#ifdef WC_RNG_HAVE_RBGC
10247
    s->_stats_RBGC_bytes_produced   += rng->_stats_RBGC_bytes_produced;
10248
    s->_stats_RBGC_reseeds          += rng->_stats_RBGC_reseeds;
10249
#endif
10250
#ifdef WC_RNG_HAVE_POOL
10251
    s->_stats_pool_bytes_produced   += rng->_stats_pool_bytes_produced;
10252
    s->_stats_pool_bytes_missed     += rng->_stats_pool_bytes_missed;
10253
#endif
10254
#ifdef WC_RNG_HAVE_NEXT_SEED
10255
    s->_stats_nextseedsprimary_redeemed += rng->_stats_nextseedsprimary_redeemed;
10256
    s->_stats_nextseedsRBGC_redeemed += rng->_stats_nextseedsRBGC_redeemed;
10257
    s->_stats_nextstirs_redeemed    += rng->_stats_nextstirs_redeemed;
10258
    s->_stats_nextseedsbanked       += rng->_stats_nextseedsbanked;
10259
    s->_stats_nextstirs_banked      += rng->_stats_nextstirs_banked;
10260
#endif
10261
10262
    return 0;
10263
}
10264
10265
#endif /* WC_RNG_DEBUG_STATS */
10266
10267
10268
#endif /* WC_NO_RNG */