Coverage Report

Created: 2026-11-12 06:38

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