Coverage Report

Created: 2026-04-01 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-fastmath/wolfcrypt/src/random.c
Line
Count
Source
1
/* random.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
/*
23
24
DESCRIPTION
25
This library contains implementation for the random number generator.
26
27
*/
28
29
/*
30
 * Random Number Generator Build Options:
31
 *
32
 * Core RNG:
33
 * WC_NO_RNG:               Disable RNG support entirely         default: off
34
 * HAVE_HASHDRBG:            Enable Hash-based DRBG (SP 800-90A) default: on
35
 * WC_RNG_BLOCKING:          Make RNG operations blocking         default: off
36
 * WC_VERBOSE_RNG:           Enable verbose RNG debug output      default: off
37
 * WC_RNG_SEED_CB:           Use custom seed callback function    default: off
38
 * WC_RNG_BANK_SUPPORT:      Enable RNG bank (pre-generated)     default: off
39
 *                            random data support
40
 * WOLFSSL_RNG_USE_FULL_SEED: Use full-length seed for DRBG      default: off
41
 * WOLFSSL_GENSEED_FORTEST:  Use deterministic seed for testing   default: off
42
 *                            WARNING: not for production use
43
 * WOLFSSL_KEEP_RNG_SEED_FD_OPEN: Keep /dev/random fd open       default: off
44
 *                            between seed operations
45
 *
46
 * Custom RNG Sources:
47
 * CUSTOM_RAND_GENERATE:     Custom random word generator func    default: off
48
 * CUSTOM_RAND_GENERATE_BLOCK: Custom block random generator      default: off
49
 * CUSTOM_RAND_GENERATE_SEED: Custom seed generator function      default: off
50
 * CUSTOM_RAND_GENERATE_SEED_OS: Custom OS-level seed generator   default: off
51
 *
52
 * Entropy Sources:
53
 * HAVE_ENTROPY_MEMUSE:      Enable memory-use based entropy      default: off
54
 *                            source for DRBG seeding
55
 * ENTROPY_MEMUSE_FORCE_FAILURE: Force entropy failure (testing)  default: off
56
 * HAVE_GETRANDOM:           Use Linux getrandom() syscall        default: auto
57
 * WOLFSSL_GETRANDOM:        Use getrandom() for seed source      default: auto
58
 * FORCE_FAILURE_GETRANDOM:  Force getrandom failure (testing)    default: off
59
 * NO_DEV_RANDOM:            Don't use /dev/random for seeding    default: off
60
 * NO_DEV_URANDOM:           Don't use /dev/urandom for seeding   default: off
61
 * HAVE_INTEL_RDRAND:        Use Intel RDRAND instruction         default: off
62
 * HAVE_INTEL_RDSEED:        Use Intel RDSEED instruction         default: off
63
 * HAVE_AMD_RDSEED:          Use AMD RDSEED instruction           default: off
64
 * IDIRECT_DEV_RANDOM:       iDirect custom /dev/random path      default: off
65
 * WIN_REUSE_CRYPT_HANDLE:   Reuse Windows CryptContext handle    default: off
66
 *
67
 * Entropy Tuning (for HAVE_ENTROPY_MEMUSE):
68
 * ENTROPY_NUM_UPDATE:       Number of updates per sample         default: 18
69
 *                            More updates = better entropy but slower
70
 * ENTROPY_NUM_UPDATES_BITS: Bits to represent ENTROPY_NUM_UPDATE default: 5
71
 *                            = upper(log2(ENTROPY_NUM_UPDATE))
72
 * ENTROPY_NUM_WORDS_BITS:   State size as 2^N entries            default: 14
73
 *                            Range: 8-30. Base on cache sizes.
74
 *                            Larger = more cache misses = better entropy
75
 *                            but more static memory usage.
76
 *
77
 * DRBG Health Tests:
78
 * WC_RNG_SEED_APT_CUTOFF:  Adaptive proportion test cutoff      default: auto
79
 * WC_RNG_SEED_APT_WINDOW:  Adaptive proportion test window size  default: auto
80
 * WC_RNG_SEED_RCT_CUTOFF:  Repetition count test cutoff         default: auto
81
 *
82
 * Hardware RNG:
83
 * STM32_RNG:                STM32 hardware RNG                   default: off
84
 * STM32_NUTTX_RNG:          STM32 RNG via NuttX                  default: off
85
 * WOLFSSL_STM32F427_RNG:    STM32F427 hardware RNG               default: off
86
 * WOLFSSL_STM32_RNG_NOLIB:  STM32 RNG without HAL library        default: off
87
 * WOLFSSL_PIC32MZ_RNG:      PIC32MZ hardware RNG                 default: off
88
 * FREESCALE_RNGA:           Freescale RNGA                       default: off
89
 * FREESCALE_K70_RNGA:       Freescale K70 RNGA                   default: off
90
 * FREESCALE_RNGB:           Freescale RNGB                       default: off
91
 * FREESCALE_KSDK_2_0_RNGA:  Freescale KSDK 2.0 RNGA             default: off
92
 * FREESCALE_KSDK_2_0_TRNG:  Freescale KSDK 2.0 TRNG             default: off
93
 * MAX3266X_RNG:             MAX3266X hardware RNG                 default: off
94
 * QAT_ENABLE_RNG:           Intel QAT hardware RNG               default: off
95
 * WOLFSSL_ATECC_RNG:        ATECC508/608 hardware RNG             default: off
96
 * WOLFSSL_SILABS_TRNG:      Silicon Labs TRNG                    default: off
97
 * WOLFSSL_SCE_NO_TRNG:      Disable Renesas SCE TRNG             default: off
98
 * WOLFSSL_SCE_TRNG_HANDLE:  Renesas SCE TRNG handle              default: off
99
 * WOLFSSL_SE050_NO_TRNG:    Disable SE050 TRNG                   default: off
100
 * WOLFSSL_PSA_NO_RNG:       Disable PSA RNG                      default: off
101
 * HAVE_IOTSAFE_HWRNG:       IoT-Safe hardware RNG                default: off
102
 * WOLFSSL_XILINX_CRYPT_VERSAL: Xilinx Versal crypto RNG          default: off
103
 */
104
105
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
106
107
/* on HPUX 11 you may need to install /dev/random see
108
   http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I
109
110
*/
111
#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
112
    #include <esp_random.h>
113
#endif
114
115
#if defined(HAVE_FIPS) && \
116
    defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
117
118
    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
119
    #define FIPS_NO_WRAPPERS
120
121
    #ifdef USE_WINDOWS_API
122
        #pragma code_seg(".fipsA$i")
123
        #pragma const_seg(".fipsB$i")
124
    #endif
125
#endif
126
127
128
#include <wolfssl/wolfcrypt/random.h>
129
#ifdef WC_RNG_BANK_SUPPORT
130
    #include <wolfssl/wolfcrypt/rng_bank.h>
131
#endif
132
#include <wolfssl/wolfcrypt/cpuid.h>
133
134
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
135
136
#include <wolfssl/wolfcrypt/sha256.h>
137
138
#ifdef WOLF_CRYPTO_CB
139
    #include <wolfssl/wolfcrypt/cryptocb.h>
140
#endif
141
142
#ifdef NO_INLINE
143
    #include <wolfssl/wolfcrypt/misc.h>
144
#else
145
    #define WOLFSSL_MISC_INCLUDED
146
    #include <wolfcrypt/src/misc.c>
147
#endif
148
149
#if defined(WOLFSSL_SGX)
150
    #include <sgx_trts.h>
151
#elif defined(USE_WINDOWS_API)
152
    #ifndef _WIN32_WINNT
153
        #define _WIN32_WINNT 0x0400
154
    #endif
155
    #define _WINSOCKAPI_ /* block inclusion of winsock.h header file */
156
    #include <windows.h>
157
    #include <wincrypt.h>
158
    #undef _WINSOCKAPI_ /* undefine it for MINGW winsock2.h header file */
159
#elif defined(HAVE_WNR)
160
    #include <wnr.h>
161
    wolfSSL_Mutex wnr_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(wnr_mutex);    /* global netRandom mutex */
162
    int wnr_timeout     = 0;    /* entropy timeout, milliseconds */
163
    #ifndef WOLFSSL_MUTEX_INITIALIZER
164
    int wnr_mutex_inited = 0;   /* flag for mutex init */
165
    #endif
166
    int wnr_inited = 0;    /* flag for whether wc_InitNetRandom() has been called */
167
    wnr_context*  wnr_ctx;      /* global netRandom context */
168
#elif defined(FREESCALE_KSDK_2_0_TRNG)
169
    #include "fsl_trng.h"
170
#elif defined(FREESCALE_KSDK_2_0_RNGA)
171
    #include "fsl_rnga.h"
172
#elif defined(WOLFSSL_WICED)
173
    #include "wiced_crypto.h"
174
#elif defined(WOLFSSL_NETBURNER)
175
    #include <predef.h>
176
    #include <basictypes.h>
177
    #include <random.h>
178
#elif defined(WOLFSSL_XILINX_CRYPT_VERSAL)
179
    #include "wolfssl/wolfcrypt/port/xilinx/xil-versal-trng.h"
180
#elif defined(WOLFSSL_RPIPICO)
181
    #include "wolfssl/wolfcrypt/port/rpi_pico/pico.h"
182
#elif defined(NO_DEV_RANDOM)
183
#elif defined(CUSTOM_RAND_GENERATE)
184
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
185
#elif defined(CUSTOM_RAND_GENERATE_SEED)
186
#elif defined(WOLFSSL_GENSEED_FORTEST)
187
#elif defined(WOLFSSL_MDK_ARM)
188
#elif defined(WOLFSSL_IAR_ARM)
189
#elif defined(WOLFSSL_ROWLEY_ARM)
190
#elif defined(WOLFSSL_EMBOS)
191
#elif defined(WOLFSSL_DEOS)
192
#elif defined(MICRIUM)
193
#elif defined(WOLFSSL_NUCLEUS)
194
#elif defined(WOLFSSL_PB)
195
#elif defined(WOLFSSL_ZEPHYR)
196
#elif defined(WOLFSSL_TELIT_M2MB)
197
#elif defined(WOLFSSL_RENESAS_TSIP)
198
    /* for wc_tsip_GenerateRandBlock */
199
    #include "wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h"
200
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
201
#elif defined(WOLFSSL_IMXRT1170_CAAM)
202
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
203
    #include "cyhal_trng.h" /* Infineon/Cypress HAL RNG implementation */
204
#elif defined(WOLFSSL_MAX3266X) || defined(WOLFSSL_MAX3266X_OLD)
205
    #include "wolfssl/wolfcrypt/port/maxim/max3266x.h"
206
#else
207
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
208
        #include <errno.h>
209
        #include <sys/random.h>
210
    #endif
211
    /* include headers that may be needed to get good seed */
212
    #include <fcntl.h>
213
    #ifndef EBSNET
214
        #include <unistd.h>
215
    #endif
216
#endif
217
218
#if defined(WOLFSSL_SILABS_SE_ACCEL)
219
#include <wolfssl/wolfcrypt/port/silabs/silabs_random.h>
220
#endif
221
222
#if defined(WOLFSSL_IOTSAFE) && defined(HAVE_IOTSAFE_HWRNG)
223
#include <wolfssl/wolfcrypt/port/iotsafe/iotsafe.h>
224
#endif
225
226
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_RNG)
227
#include <wolfssl/wolfcrypt/port/psa/psa.h>
228
#endif
229
230
#if FIPS_VERSION3_GE(6,0,0)
231
    const unsigned int wolfCrypt_FIPS_drbg_ro_sanity[2] =
232
                                                     { 0x1a2b3c4d, 0x00000011 };
233
    int wolfCrypt_FIPS_DRBG_sanity(void)
234
    {
235
        return 0;
236
    }
237
#endif
238
239
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
240
    defined(HAVE_AMD_RDSEED)
241
    static cpuid_flags_t intel_flags = WC_CPUID_INITIALIZER;
242
    static void wc_InitRng_IntelRD(void)
243
    {
244
        cpuid_get_flags_ex(&intel_flags);
245
    }
246
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
247
    static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz);
248
    #endif
249
    #ifdef HAVE_INTEL_RDRAND
250
    static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz);
251
    #endif
252
253
#ifdef USE_WINDOWS_API
254
    #define USE_INTEL_INTRINSICS
255
#elif !defined __GNUC__ || defined __clang__ || __GNUC__ > 4
256
    #define USE_INTEL_INTRINSICS
257
#else
258
    #undef USE_INTEL_INTRINSICS
259
#endif
260
261
#ifdef USE_INTEL_INTRINSICS
262
    #include <immintrin.h>
263
    /* Before clang 7 or GCC 9, immintrin.h did not define _rdseed64_step() */
264
    #ifndef HAVE_INTEL_RDSEED
265
    #elif defined __clang__ && __clang_major__ > 6
266
    #elif !defined __GNUC__
267
    #elif __GNUC__ > 8
268
    #else
269
        #ifndef __clang__
270
            #pragma GCC push_options
271
            #pragma GCC target("rdseed")
272
        #else
273
            #define __RDSEED__
274
        #endif
275
        #include <x86intrin.h>
276
        #ifndef __clang__
277
            #pragma GCC pop_options
278
        #endif
279
    #endif
280
#endif /* USE_WINDOWS_API */
281
#endif
282
283
/* Start NIST DRBG code */
284
#ifdef HAVE_HASHDRBG
285
286
11.7M
#define OUTPUT_BLOCK_LEN  (WC_SHA256_DIGEST_SIZE)
287
#define MAX_REQUEST_LEN   (0x10000)
288
289
#ifdef WC_RNG_SEED_CB
290
291
#ifndef HAVE_FIPS
292
static wc_RngSeed_Cb seedCb = wc_GenerateSeed;
293
#else
294
static wc_RngSeed_Cb seedCb = NULL;
295
#endif
296
297
int wc_SetSeed_Cb(wc_RngSeed_Cb cb)
298
{
299
    seedCb = cb;
300
    return 0;
301
}
302
303
#endif
304
305
306
/* Internal return codes */
307
6.59M
#define DRBG_SUCCESS      0
308
1.84M
#define DRBG_FAILURE      1
309
407k
#define DRBG_NEED_RESEED  2
310
15.9k
#define DRBG_CONT_FAILURE 3
311
#define DRBG_NO_SEED_CB   4
312
313
/* RNG health states */
314
232k
#define DRBG_NOT_INIT     WC_DRBG_NOT_INIT
315
514k
#define DRBG_OK           WC_DRBG_OK
316
18.6k
#define DRBG_FAILED       WC_DRBG_FAILED
317
1.44k
#define DRBG_CONT_FAILED  WC_DRBG_CONT_FAILED
318
319
113k
#define SEED_SZ           WC_DRBG_SEED_SZ
320
113k
#define MAX_SEED_SZ       WC_DRBG_MAX_SEED_SZ
321
322
/* Verify max gen block len */
323
#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN
324
    #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length
325
#endif
326
327
enum {
328
    drbgInitC     = 0,
329
    drbgReseed    = 1,
330
    drbgGenerateW = 2,
331
    drbgGenerateH = 3,
332
    drbgInitV     = 4
333
};
334
335
typedef struct DRBG_internal DRBG_internal;
336
337
static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap,
338
                                  int devId);
339
340
/* Hash Derivation Function */
341
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
342
static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
343
                                                  const byte* inA, word32 inASz,
344
                                                  const byte* inB, word32 inBSz)
345
638k
{
346
638k
    int ret = DRBG_FAILURE;
347
638k
    byte ctr;
348
638k
    word32 i;
349
638k
    word32 len;
350
638k
    word32 bits = (outSz * 8); /* reverse byte order */
351
#ifdef WOLFSSL_SMALL_STACK_CACHE
352
    wc_Sha256* sha = &drbg->sha256;
353
#else
354
638k
    wc_Sha256 sha[1];
355
638k
#endif
356
#if defined(WOLFSSL_SMALL_STACK_CACHE)
357
    byte* digest = drbg->digest_scratch;
358
#elif defined(WOLFSSL_SMALL_STACK)
359
    byte* digest;
360
#else
361
    byte digest[WC_SHA256_DIGEST_SIZE];
362
#endif
363
364
638k
    if (drbg == NULL) {
365
0
        return DRBG_FAILURE;
366
0
    }
367
368
638k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
369
638k
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
370
638k
        DYNAMIC_TYPE_DIGEST);
371
638k
    if (digest == NULL)
372
214
        return DRBG_FAILURE;
373
638k
#endif
374
375
638k
#ifdef LITTLE_ENDIAN_ORDER
376
638k
    bits = ByteReverseWord32(bits);
377
638k
#endif
378
638k
    len = (outSz / OUTPUT_BLOCK_LEN)
379
638k
        + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
380
381
638k
    ctr = 1;
382
1.91M
    for (i = 0; i < len; i++) {
383
1.27M
#ifndef WOLFSSL_SMALL_STACK_CACHE
384
1.27M
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
385
1.27M
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
386
    #else
387
        ret = wc_InitSha256(sha);
388
    #endif
389
1.27M
        if (ret != 0)
390
0
            break;
391
1.27M
#endif
392
1.27M
        ret = wc_Sha256Update(sha, &ctr, sizeof(ctr));
393
1.27M
        if (ret == 0) {
394
1.27M
            ctr++;
395
1.27M
            ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits));
396
1.27M
        }
397
398
1.27M
        if (ret == 0) {
399
            /* churning V is the only string that doesn't have the type added */
400
1.27M
            if (type != drbgInitV)
401
637k
                ret = wc_Sha256Update(sha, &type, sizeof(type));
402
1.27M
        }
403
1.27M
        if (ret == 0)
404
1.27M
            ret = wc_Sha256Update(sha, inA, inASz);
405
1.27M
        if (ret == 0) {
406
1.27M
            if (inB != NULL && inBSz > 0)
407
212k
                ret = wc_Sha256Update(sha, inB, inBSz);
408
1.27M
        }
409
1.27M
        if (ret == 0)
410
1.27M
            ret = wc_Sha256Final(sha, digest);
411
412
1.27M
#ifndef WOLFSSL_SMALL_STACK_CACHE
413
1.27M
        wc_Sha256Free(sha);
414
1.27M
#endif
415
1.27M
        if (ret == 0) {
416
1.24M
            if (outSz > OUTPUT_BLOCK_LEN) {
417
637k
                XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
418
637k
                outSz -= OUTPUT_BLOCK_LEN;
419
637k
                out += OUTPUT_BLOCK_LEN;
420
637k
            }
421
608k
            else {
422
608k
                XMEMCPY(out, digest, outSz);
423
608k
            }
424
1.24M
        }
425
1.27M
    }
426
427
638k
    ForceZero(digest, WC_SHA256_DIGEST_SIZE);
428
429
638k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
430
638k
    XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
431
638k
#endif
432
433
#ifdef WC_VERBOSE_RNG
434
    if (ret != 0)
435
        WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __FUNCTION__,
436
                             ret);
437
#endif
438
439
638k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
440
638k
}
441
442
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
443
static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz)
444
0
{
445
0
    int ret;
446
0
    WC_DECLARE_VAR(newV, byte, DRBG_SEED_LEN, 0);
447
448
0
    if (drbg == NULL) {
449
0
        return DRBG_FAILURE;
450
0
    }
451
452
#ifdef WOLFSSL_SMALL_STACK_CACHE
453
    newV = drbg->seed_scratch;
454
#else
455
0
    WC_ALLOC_VAR_EX(newV, byte, DRBG_SEED_LEN, drbg->heap,
456
0
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
457
0
#endif
458
0
    XMEMSET(newV, 0, DRBG_SEED_LEN);
459
460
0
    ret = Hash_df(drbg, newV, DRBG_SEED_LEN, drbgReseed,
461
0
                drbg->V, sizeof(drbg->V), seed, seedSz);
462
0
    if (ret == DRBG_SUCCESS) {
463
0
        XMEMCPY(drbg->V, newV, sizeof(drbg->V));
464
0
        ForceZero(newV, DRBG_SEED_LEN);
465
466
0
        ret = Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
467
0
                                    sizeof(drbg->V), NULL, 0);
468
0
    }
469
0
    if (ret == DRBG_SUCCESS) {
470
0
        drbg->reseedCtr = 1;
471
0
    }
472
473
0
#ifndef WOLFSSL_SMALL_STACK_CACHE
474
0
    WC_FREE_VAR_EX(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
475
0
#endif
476
477
    #ifdef WC_VERBOSE_RNG
478
    if (ret != 0)
479
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Reseed failed with err %d.",
480
                             ret);
481
    #endif
482
483
0
    return ret;
484
0
}
485
486
/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */
487
int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz)
488
0
{
489
0
    if (rng == NULL || seed == NULL) {
490
0
        return BAD_FUNC_ARG;
491
0
    }
492
493
0
    if (rng->drbg == NULL) {
494
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND)
495
        if (IS_INTEL_RDRAND(intel_flags)) {
496
            /* using RDRAND not DRBG, so return success */
497
            return 0;
498
        }
499
        return BAD_FUNC_ARG;
500
    #endif
501
0
    }
502
503
0
    return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz);
504
0
}
505
506
static WC_INLINE void array_add_one(byte* data, word32 dataSz)
507
2.20M
{
508
2.20M
    int i;
509
2.20M
    for (i = (int)dataSz - 1; i >= 0; i--) {
510
2.20M
        data[i]++;
511
2.20M
        if (data[i] != 0) break;
512
2.20M
    }
513
2.20M
}
514
515
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
516
static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V)
517
829k
{
518
829k
    int ret = DRBG_FAILURE;
519
829k
    word32 i;
520
829k
    word32 len;
521
#if defined(WOLFSSL_SMALL_STACK_CACHE)
522
    wc_Sha256* sha = &drbg->sha256;
523
    byte* data = drbg->seed_scratch;
524
    byte* digest = drbg->digest_scratch;
525
#elif defined(WOLFSSL_SMALL_STACK)
526
    wc_Sha256 sha[1];
527
829k
    byte* data = NULL;
528
829k
    byte* digest = NULL;
529
#else
530
    wc_Sha256 sha[1];
531
    byte data[DRBG_SEED_LEN];
532
    byte digest[WC_SHA256_DIGEST_SIZE];
533
#endif
534
535
829k
    if (drbg == NULL) {
536
0
        return DRBG_FAILURE;
537
0
    }
538
539
829k
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
540
829k
    data = (byte*)XMALLOC(DRBG_SEED_LEN, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
541
829k
    digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
542
829k
        DYNAMIC_TYPE_DIGEST);
543
829k
    if (data == NULL || digest == NULL) {
544
2.70k
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
545
2.70k
        XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
546
2.70k
        return DRBG_FAILURE;
547
2.70k
    }
548
827k
#endif
549
550
    /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
551
     * the continuous test. */
552
553
827k
    if (outSz == 0) {
554
0
        outSz = 1;
555
0
    }
556
557
827k
    len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0);
558
559
827k
    XMEMCPY(data, V, DRBG_SEED_LEN);
560
3.12M
    for (i = 0; i < len; i++) {
561
2.30M
#ifndef WOLFSSL_SMALL_STACK_CACHE
562
2.30M
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
563
2.30M
        ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
564
    #else
565
        ret = wc_InitSha256(sha);
566
    #endif
567
2.30M
        if (ret == 0)
568
2.30M
#endif
569
2.30M
            ret = wc_Sha256Update(sha, data, DRBG_SEED_LEN);
570
2.30M
        if (ret == 0)
571
2.30M
            ret = wc_Sha256Final(sha, digest);
572
2.30M
#ifndef WOLFSSL_SMALL_STACK_CACHE
573
2.30M
        wc_Sha256Free(sha);
574
2.30M
#endif
575
576
2.30M
        if (ret == 0) {
577
2.29M
            if (out != NULL && outSz != 0) {
578
2.29M
                if (outSz >= OUTPUT_BLOCK_LEN) {
579
1.99M
                    XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
580
1.99M
                    outSz -= OUTPUT_BLOCK_LEN;
581
1.99M
                    out += OUTPUT_BLOCK_LEN;
582
1.99M
                    array_add_one(data, DRBG_SEED_LEN);
583
1.99M
                }
584
307k
                else {
585
307k
                    XMEMCPY(out, digest, outSz);
586
307k
                    outSz = 0;
587
307k
                }
588
2.29M
            }
589
2.29M
        }
590
842
        else {
591
            /* wc_Sha256Update or wc_Sha256Final returned error */
592
842
            break;
593
842
        }
594
2.30M
    }
595
827k
    ForceZero(data, DRBG_SEED_LEN);
596
597
827k
#ifndef WOLFSSL_SMALL_STACK_CACHE
598
827k
    WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
599
827k
    WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
600
827k
#endif
601
602
    #ifdef WC_VERBOSE_RNG
603
    if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
604
        /* Note, if we're just going to return DRBG_FAILURE to the caller, then
605
         * there's no point printing it out here because (1) the lower-level
606
         * code that was remapped to DRBG_FAILURE already got printed before the
607
         * remapping, so a DRBG_FAILURE message would just be spamming the log,
608
         * and (2) the caller will actually see the DRBG_FAILURE code, and is
609
         * free to (and probably will) log it itself.
610
         */
611
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_gen failed with err %d.", ret);
612
    }
613
    #endif
614
615
827k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
616
829k
}
617
618
static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
619
2.68M
{
620
2.68M
    if (dLen > 0 && sLen > 0 && dLen >= sLen) {
621
2.68M
        int sIdx, dIdx;
622
2.68M
        word16 carry = 0;
623
624
2.68M
        dIdx = (int)dLen - 1;
625
87.8M
        for (sIdx = (int)sLen - 1; sIdx >= 0; sIdx--) {
626
85.1M
            carry = (word16)(carry + d[dIdx] + s[sIdx]);
627
85.1M
            d[dIdx] = (byte)carry;
628
85.1M
            carry >>= 8;
629
85.1M
            dIdx--;
630
85.1M
        }
631
632
65.4M
        for (; dIdx >= 0; dIdx--) {
633
62.7M
            carry = (word16)(carry + d[dIdx]);
634
62.7M
            d[dIdx] = (byte)carry;
635
62.7M
            carry >>= 8;
636
62.7M
        }
637
2.68M
    }
638
2.68M
}
639
640
/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */
641
static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz)
642
833k
{
643
833k
    int ret;
644
#ifdef WOLFSSL_SMALL_STACK_CACHE
645
    wc_Sha256* sha = &drbg->sha256;
646
#else
647
833k
    wc_Sha256 sha[1];
648
833k
#endif
649
833k
    byte type;
650
833k
#ifdef WORD64_AVAILABLE
651
833k
    word64 reseedCtr;
652
#else
653
    word32 reseedCtr;
654
#endif
655
656
833k
    if (drbg == NULL) {
657
0
        return DRBG_FAILURE;
658
0
    }
659
660
833k
    if (drbg->reseedCtr >= WC_RESEED_INTERVAL) {
661
    #if (defined(DEBUG_WOLFSSL) || defined(DEBUG_DRBG_RESEEDS)) && \
662
        defined(WOLFSSL_DEBUG_PRINTF)
663
        WOLFSSL_DEBUG_PRINTF("DRBG reseed triggered, reseedCtr == %lu",
664
                (unsigned long)drbg->reseedCtr);
665
    #endif
666
0
        return DRBG_NEED_RESEED;
667
0
    }
668
833k
    else {
669
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
670
        byte* digest = drbg->digest_scratch;
671
    #elif defined(WOLFSSL_SMALL_STACK)
672
833k
        byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap,
673
833k
            DYNAMIC_TYPE_DIGEST);
674
833k
        if (digest == NULL)
675
3.39k
            return DRBG_FAILURE;
676
    #else
677
        byte digest[WC_SHA256_DIGEST_SIZE];
678
    #endif
679
680
829k
        type = drbgGenerateH;
681
829k
        reseedCtr = drbg->reseedCtr;
682
683
829k
        ret = Hash_gen(drbg, out, outSz, drbg->V);
684
829k
        if (ret == DRBG_SUCCESS) {
685
826k
#ifndef WOLFSSL_SMALL_STACK_CACHE
686
826k
        #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
687
826k
            ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId);
688
        #else
689
            ret = wc_InitSha256(sha);
690
        #endif
691
826k
            if (ret == 0)
692
826k
#endif
693
826k
                ret = wc_Sha256Update(sha, &type, sizeof(type));
694
826k
            if (ret == 0)
695
826k
                ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V));
696
826k
            if (ret == 0)
697
826k
                ret = wc_Sha256Final(sha, digest);
698
699
826k
#ifndef WOLFSSL_SMALL_STACK_CACHE
700
826k
            wc_Sha256Free(sha);
701
826k
#endif
702
703
826k
            if (ret == 0) {
704
825k
                array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE);
705
825k
                array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
706
825k
            #ifdef LITTLE_ENDIAN_ORDER
707
825k
                #ifdef WORD64_AVAILABLE
708
825k
                reseedCtr = ByteReverseWord64(reseedCtr);
709
                #else
710
                reseedCtr = ByteReverseWord32(reseedCtr);
711
                #endif
712
825k
            #endif
713
825k
                array_add(drbg->V, sizeof(drbg->V),
714
825k
                                          (byte*)&reseedCtr, sizeof(reseedCtr));
715
825k
                ret = DRBG_SUCCESS;
716
825k
            }
717
826k
            drbg->reseedCtr++;
718
826k
        }
719
829k
        ForceZero(digest, WC_SHA256_DIGEST_SIZE);
720
829k
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
721
829k
        XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
722
829k
    #endif
723
829k
    }
724
725
    #ifdef WC_VERBOSE_RNG
726
    if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
727
        /* see note above regarding log spam reduction */
728
        WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Generate failed with err %d.",
729
                             ret);
730
    }
731
    #endif
732
733
829k
    return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
734
833k
}
735
736
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
737
static int Hash_DRBG_Init(DRBG_internal* drbg, const byte* seed, word32 seedSz,
738
                                             const byte* nonce, word32 nonceSz)
739
357k
{
740
357k
    if (seed == NULL)
741
0
        return DRBG_FAILURE;
742
743
357k
    if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz,
744
357k
                                              nonce, nonceSz) == DRBG_SUCCESS &&
745
357k
        Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V,
746
357k
                                    sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) {
747
748
357k
        drbg->reseedCtr = 1;
749
357k
        return DRBG_SUCCESS;
750
357k
    }
751
425
    else {
752
425
        return DRBG_FAILURE;
753
425
    }
754
357k
}
755
756
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
757
static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 seedSz,
758
                                             const byte* nonce, word32 nonceSz,
759
                                             void* heap, int devId)
760
357k
{
761
357k
    int ret = DRBG_FAILURE;
762
763
357k
    XMEMSET(drbg, 0, sizeof(DRBG_internal));
764
357k
    drbg->heap = heap;
765
357k
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
766
357k
    drbg->devId = devId;
767
#else
768
    (void)devId;
769
#endif
770
771
#ifdef WOLFSSL_SMALL_STACK_CACHE
772
    #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
773
        ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId);
774
    #else
775
        ret = wc_InitSha256(&drbg->sha256);
776
    #endif
777
    if (ret != 0)
778
        return ret;
779
#endif
780
781
357k
    if (seed != NULL)
782
357k
        ret = Hash_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz);
783
357k
    return ret;
784
357k
}
785
786
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */
787
static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg)
788
357k
{
789
357k
    word32 i;
790
357k
    int    compareSum = 0;
791
357k
    byte*  compareDrbg = (byte*)drbg;
792
793
#ifdef WOLFSSL_SMALL_STACK_CACHE
794
    wc_Sha256Free(&drbg->sha256);
795
#endif
796
797
357k
    ForceZero(drbg, sizeof(DRBG_internal));
798
799
48.6M
    for (i = 0; i < sizeof(DRBG_internal); i++) {
800
48.3M
        compareSum |= compareDrbg[i] ^ 0;
801
48.3M
    }
802
803
357k
    return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
804
357k
}
805
806
807
/* FIPS 140-3 IG 10.3.A / SP800-90B Health Tests for Seed Data
808
 *
809
 * These tests replace the older FIPS 140-2 Continuous Random Number Generator
810
 * Test (CRNGT) with more mathematically robust statistical tests per
811
 * ISO 19790 / SP800-90B requirements.
812
 *
813
 * When HAVE_ENTROPY_MEMUSE is defined, the wolfentropy.c jitter-based TRNG
814
 * performs another set of these health tests, but those are on the noise not
815
 * the conditioned output so we still need to retest here even in that case
816
 * to evaluate the conditioned output for the same behavior. These tests ensure
817
 * the seed data meets basic entropy requirements regardless of the source.
818
 */
819
820
/* SP800-90B 4.4.1 - Repetition Count Test
821
 * Detects if the noise source becomes "stuck" producing repeated output.
822
 *
823
 * C = 1 + ceil(-log2(alpha) / H)
824
 * For alpha = 2^-30 (false positive probability) and H = 1 (min entropy):
825
 * C = 1 + ceil(30 / 1) = 31
826
 */
827
#ifndef WC_RNG_SEED_RCT_CUTOFF
828
6.06M
    #define WC_RNG_SEED_RCT_CUTOFF 31
829
#endif
830
831
/* SP800-90B 4.4.2 - Adaptive Proportion Test
832
 * Monitors if a particular sample value appears too frequently within a
833
 * window of samples, indicating loss of entropy.
834
 *
835
 * Window size W = 512 for non-binary alphabet (byte values 0-255)
836
 * C = 1 + CRITBINOM(W, 2^(-H), 1-alpha)
837
 * For alpha = 2^-30 and H = 1, W = 512:
838
 * C = 1 + CRITBINOM(512, 0.5, 1-2^-30) = 325
839
 */
840
#ifndef WC_RNG_SEED_APT_WINDOW
841
118k
    #define WC_RNG_SEED_APT_WINDOW 512
842
#endif
843
#ifndef WC_RNG_SEED_APT_CUTOFF
844
30.4M
    #define WC_RNG_SEED_APT_CUTOFF 325
845
#endif
846
847
int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
848
118k
{
849
118k
    int ret = 0;
850
851
118k
    word32 i;
852
118k
    int rctFailed = 0;
853
118k
    int aptFailed = 0;
854
855
118k
    if (seed == NULL || seedSz < SEED_BLOCK_SZ) {
856
0
        return BAD_FUNC_ARG;
857
0
    }
858
859
    /* SP800-90B 4.4.1 - Repetition Count Test (RCT)
860
     * Check for consecutive identical bytes that would indicate a stuck
861
     * entropy source. Fail if we see WC_RNG_SEED_RCT_CUTOFF or more
862
     * consecutive identical values.
863
     *
864
     * Constant-time implementation: always process full seed, accumulate
865
     * failure status without early exit to prevent timing side-channels.
866
     */
867
118k
    {
868
118k
        int repCount = 1;
869
118k
        byte prevByte = seed[0];
870
871
6.18M
        for (i = 1; i < seedSz; i++) {
872
            /* Constant-time: always evaluate both branches effects */
873
6.06M
            int match = (seed[i] == prevByte);
874
            /* If match, increment count, if not, reset to 1 */
875
6.06M
            repCount = (match * (repCount + 1)) + (!match * 1);
876
            /* Update prevByte only when not matching (new value) */
877
6.06M
            prevByte = (byte) ((match * prevByte) + (!match * seed[i]));
878
            /* Accumulate failure flag - once set, stays set */
879
6.06M
            rctFailed |= (repCount >= WC_RNG_SEED_RCT_CUTOFF);
880
6.06M
        }
881
118k
    }
882
883
    /* SP800-90B 4.4.2 - Adaptive Proportion Test (APT)
884
     * Check that no single byte value appears too frequently within
885
     * a sliding window. This detects bias in the entropy source.
886
     *
887
     * For seeds smaller than the window size, we test the entire seed.
888
     * For larger seeds, we use a sliding window approach.
889
     *
890
     * Constant-time implementation: always process full seed and check
891
     * all counts to prevent timing side-channels.
892
     */
893
118k
    {
894
118k
        word16 byteCounts[MAX_ENTROPY_BITS];
895
118k
        word32 windowSize = min(seedSz, (word32)WC_RNG_SEED_APT_WINDOW);
896
118k
        word32 windowStart = 0;
897
118k
        word32 newIdx;
898
899
118k
        XMEMSET(byteCounts, 0, sizeof(byteCounts));
900
901
        /* Initialize counts for first window */
902
6.30M
        for (i = 0; i < windowSize; i++) {
903
6.18M
            byteCounts[seed[i]]++;
904
6.18M
        }
905
906
        /* Check first window - scan all 256 counts */
907
30.5M
        for (i = 0; i < MAX_ENTROPY_BITS; i++) {
908
30.4M
            aptFailed |= (byteCounts[i] >= WC_RNG_SEED_APT_CUTOFF);
909
30.4M
        }
910
911
        /* Slide window through remaining seed data */
912
118k
        while ((windowStart + windowSize) < seedSz) {
913
            /* Remove byte leaving the window */
914
0
            byteCounts[seed[windowStart]]--;
915
0
            windowStart++;
916
917
            /* Add byte entering the window */
918
0
            newIdx = windowStart + windowSize - 1;
919
0
            byteCounts[seed[newIdx]]++;
920
921
            /* Accumulate failure flag for new byte's count */
922
0
            aptFailed |= (byteCounts[seed[newIdx]] >= WC_RNG_SEED_APT_CUTOFF);
923
0
        }
924
118k
    }
925
926
    /* Set return code based on accumulated failure flags */
927
118k
    if (rctFailed) {
928
0
        ret = ENTROPY_RT_E;
929
0
    }
930
118k
    else if (aptFailed) {
931
0
        ret = ENTROPY_APT_E;
932
0
    }
933
934
118k
    return ret;
935
118k
}
936
#endif /* HAVE_HASHDRBG */
937
/* End NIST DRBG Code */
938
939
940
static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
941
                    void* heap, int devId)
942
113k
{
943
113k
    int ret = 0;
944
113k
#ifdef HAVE_HASHDRBG
945
#if !defined(HAVE_FIPS) && defined(WOLFSSL_RNG_USE_FULL_SEED)
946
    word32 seedSz = SEED_SZ;
947
#else
948
113k
    word32 seedSz = SEED_SZ + SEED_BLOCK_SZ;
949
113k
    WC_DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap);
950
#ifdef WOLFSSL_SMALL_STACK_CACHE
951
    int drbg_scratch_instantiated = 0;
952
#endif
953
113k
#endif
954
113k
#endif
955
956
113k
    (void)nonce;
957
113k
    (void)nonceSz;
958
959
113k
    if (rng == NULL)
960
0
        return BAD_FUNC_ARG;
961
113k
    if (nonce == NULL && nonceSz != 0)
962
0
        return BAD_FUNC_ARG;
963
964
113k
    XMEMSET(rng, 0, sizeof(*rng));
965
966
#ifdef WOLFSSL_HEAP_TEST
967
    rng->heap = (void*)WOLFSSL_HEAP_TEST;
968
    (void)heap;
969
#else
970
113k
    rng->heap = heap;
971
113k
#endif
972
113k
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
973
113k
    rng->pid = getpid();
974
113k
#endif
975
113k
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
976
113k
    rng->devId = devId;
977
113k
    #if defined(WOLF_CRYPTO_CB)
978
113k
        rng->seed.devId = devId;
979
113k
    #endif
980
#else
981
    (void)devId;
982
#endif
983
984
113k
#ifdef HAVE_HASHDRBG
985
    /* init the DBRG to known values */
986
113k
    rng->drbg = NULL;
987
    #ifdef WOLFSSL_SMALL_STACK_CACHE
988
    rng->drbg_scratch = NULL;
989
    #endif
990
113k
    rng->status = DRBG_NOT_INIT;
991
113k
#endif
992
993
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) || \
994
    defined(HAVE_AMD_RDSEED)
995
    /* init the intel RD seed and/or rand */
996
    wc_InitRng_IntelRD();
997
#endif
998
999
    /* configure async RNG source if available */
1000
#ifdef WOLFSSL_ASYNC_CRYPT
1001
    ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG,
1002
                                                        rng->heap, rng->devId);
1003
    if (ret != 0) {
1004
    #ifdef HAVE_HASHDRBG
1005
        rng->status = DRBG_OK;
1006
    #endif
1007
        return ret;
1008
    }
1009
#endif
1010
1011
#ifdef HAVE_INTEL_RDRAND
1012
    /* if CPU supports RDRAND, use it directly and by-pass DRBG init */
1013
    if (IS_INTEL_RDRAND(intel_flags)) {
1014
    #ifdef HAVE_HASHDRBG
1015
        rng->status = DRBG_OK;
1016
    #endif
1017
        return 0;
1018
    }
1019
#endif
1020
1021
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
1022
    ret = wc_VersalTrngInit(nonce, nonceSz);
1023
    if (ret) {
1024
    #ifdef HAVE_HASHDRBG
1025
        rng->status = DRBG_OK;
1026
    #endif
1027
        return ret;
1028
    }
1029
#endif
1030
1031
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && !defined(USE_WINDOWS_API)
1032
    if (!rng->seed.seedFdOpen)
1033
        rng->seed.fd = XBADFD;
1034
#endif
1035
1036
#ifdef CUSTOM_RAND_GENERATE_BLOCK
1037
    ret = 0; /* success */
1038
#else
1039
1040
 /* not CUSTOM_RAND_GENERATE_BLOCK follows */
1041
113k
#ifdef HAVE_HASHDRBG
1042
113k
    if (nonceSz == 0) {
1043
113k
        seedSz = MAX_SEED_SZ;
1044
113k
    }
1045
1046
113k
#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1047
113k
    rng->drbg =
1048
113k
        (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap,
1049
113k
                              DYNAMIC_TYPE_RNG);
1050
113k
    if (rng->drbg == NULL) {
1051
    #if defined(DEBUG_WOLFSSL)
1052
        WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
1053
                       sizeof(DRBG_internal));
1054
    #endif
1055
5.55k
        ret = MEMORY_E;
1056
5.55k
        rng->status = DRBG_FAILED;
1057
5.55k
    }
1058
#else
1059
    rng->drbg = (struct DRBG*)&rng->drbg_data;
1060
#endif /* WOLFSSL_NO_MALLOC or WOLFSSL_STATIC_MEMORY */
1061
1062
#ifdef WOLFSSL_SMALL_STACK_CACHE
1063
    if (ret == 0) {
1064
        rng->drbg_scratch =
1065
            (DRBG_internal *)XMALLOC(sizeof(DRBG_internal), rng->heap,
1066
                                     DYNAMIC_TYPE_RNG);
1067
        if (rng->drbg_scratch == NULL) {
1068
#if defined(DEBUG_WOLFSSL)
1069
            WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes",
1070
                           sizeof(DRBG_internal));
1071
#endif
1072
            ret = MEMORY_E;
1073
            rng->status = DRBG_FAILED;
1074
        }
1075
    }
1076
1077
    if (ret == 0) {
1078
        ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch,
1079
                    NULL /* seed */, 0, NULL /* nonce */, 0, rng->heap, devId);
1080
        if (ret == 0)
1081
            drbg_scratch_instantiated = 1;
1082
    }
1083
1084
    if (ret == 0) {
1085
        rng->health_check_scratch =
1086
            (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, rng->heap,
1087
                            DYNAMIC_TYPE_TMP_BUFFER);
1088
        if (rng->health_check_scratch == NULL) {
1089
            ret = MEMORY_E;
1090
            rng->status = DRBG_FAILED;
1091
        }
1092
    }
1093
1094
    if (ret == 0) {
1095
        rng->newSeed_buf = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
1096
                           DYNAMIC_TYPE_SEED);
1097
        if (rng->newSeed_buf == NULL) {
1098
            ret = MEMORY_E;
1099
            rng->status = DRBG_FAILED;
1100
        }
1101
    }
1102
#endif /* WOLFSSL_SMALL_STACK_CACHE */
1103
1104
113k
    if (ret == 0) {
1105
107k
        ret = wc_RNG_HealthTestLocal(rng, 0, rng->heap, devId);
1106
107k
        if (ret != 0) {
1107
        #if defined(DEBUG_WOLFSSL)
1108
            WOLFSSL_MSG_EX("wc_RNG_HealthTestLocal failed err = %d", ret);
1109
        #endif
1110
1.44k
            ret = DRBG_CONT_FAILURE;
1111
1.44k
        }
1112
107k
    }
1113
1114
113k
    #ifdef WOLFSSL_SMALL_STACK
1115
113k
    if (ret == 0) {
1116
106k
        WC_ALLOC_VAR_EX(seed, byte, MAX_SEED_SZ, rng->heap, DYNAMIC_TYPE_SEED, WC_DO_NOTHING);
1117
106k
        if (seed == NULL) {
1118
20
            ret = MEMORY_E;
1119
20
            rng->status = DRBG_FAILED;
1120
20
        }
1121
106k
    }
1122
113k
    #endif
1123
1124
113k
    if (ret != 0) {
1125
#if defined(DEBUG_WOLFSSL)
1126
        WOLFSSL_MSG_EX("_InitRng failed. err = %d", ret);
1127
#endif
1128
7.02k
    }
1129
106k
    else {
1130
#ifdef WC_RNG_SEED_CB
1131
            if (seedCb == NULL) {
1132
                ret = DRBG_NO_SEED_CB;
1133
            }
1134
            else {
1135
                ret = seedCb(&rng->seed, seed, seedSz);
1136
                if (ret != 0) {
1137
#ifdef WC_VERBOSE_RNG
1138
                    WOLFSSL_DEBUG_PRINTF(
1139
                        "ERROR: seedCb in _InitRng() failed with err = %d",
1140
                        ret);
1141
#endif
1142
                    ret = DRBG_FAILURE;
1143
                }
1144
            }
1145
#else
1146
106k
            ret = wc_GenerateSeed(&rng->seed, seed, seedSz);
1147
106k
#endif /* WC_RNG_SEED_CB */
1148
106k
            if (ret != 0) {
1149
    #if defined(DEBUG_WOLFSSL)
1150
                WOLFSSL_MSG_EX("Seed generation failed... %d", ret);
1151
    #elif defined(WC_VERBOSE_RNG)
1152
                WOLFSSL_DEBUG_PRINTF(
1153
                    "ERROR: wc_GenerateSeed() in _InitRng() failed with err %d",
1154
                    ret);
1155
    #endif
1156
0
                ret = DRBG_FAILURE;
1157
0
                rng->status = DRBG_FAILED;
1158
0
            }
1159
1160
106k
            if (ret == 0)
1161
106k
                ret = wc_RNG_TestSeed(seed, seedSz);
1162
    #if defined(DEBUG_WOLFSSL)
1163
            if (ret != 0) {
1164
                WOLFSSL_MSG_EX("wc_RNG_TestSeed failed... %d", ret);
1165
            }
1166
    #elif defined(WC_VERBOSE_RNG)
1167
            if (ret != DRBG_SUCCESS) {
1168
                WOLFSSL_DEBUG_PRINTF(
1169
                    "ERROR: wc_RNG_TestSeed() in _InitRng() returned err %d.",
1170
                    ret);
1171
            }
1172
    #endif
1173
1174
106k
            if (ret == DRBG_SUCCESS)
1175
106k
                ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg,
1176
106k
            #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED)
1177
106k
                            seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
1178
            #else
1179
                            seed, seedSz,
1180
            #endif
1181
106k
                            nonce, nonceSz, rng->heap, devId);
1182
106k
    } /* ret == 0 */
1183
1184
113k
    #ifdef WOLFSSL_SMALL_STACK
1185
113k
    if (seed)
1186
106k
    #endif
1187
106k
    {
1188
106k
        ForceZero(seed, seedSz);
1189
106k
    }
1190
113k
    WC_FREE_VAR_EX(seed, rng->heap, DYNAMIC_TYPE_SEED);
1191
1192
113k
    if (ret != DRBG_SUCCESS) {
1193
7.08k
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1194
7.08k
        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
1195
7.08k
    #endif
1196
7.08k
        rng->drbg = NULL;
1197
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1198
        XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_TMP_BUFFER);
1199
        rng->health_check_scratch = NULL;
1200
        XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_TMP_BUFFER);
1201
        rng->newSeed_buf = NULL;
1202
        if (drbg_scratch_instantiated)
1203
            (void)Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch);
1204
        XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
1205
        rng->drbg_scratch = NULL;
1206
    #endif
1207
7.08k
    }
1208
    /* else wc_RNG_HealthTestLocal was successful */
1209
1210
113k
    if (ret == DRBG_SUCCESS) {
1211
#ifdef WOLFSSL_CHECK_MEM_ZERO
1212
    #ifdef HAVE_HASHDRBG
1213
        struct DRBG_internal* drbg = (struct DRBG_internal*)rng->drbg;
1214
        wc_MemZero_Add("DRBG V", &drbg->V, sizeof(drbg->V));
1215
        wc_MemZero_Add("DRBG C", &drbg->C, sizeof(drbg->C));
1216
    #endif
1217
#endif
1218
1219
106k
        rng->status = DRBG_OK;
1220
106k
        ret = 0;
1221
106k
    }
1222
7.08k
    else if (ret == DRBG_CONT_FAILURE) {
1223
1.44k
        rng->status = DRBG_CONT_FAILED;
1224
1.44k
        ret = DRBG_CONT_FIPS_E;
1225
1.44k
    }
1226
5.63k
    else if (ret == DRBG_FAILURE) {
1227
62
        rng->status = DRBG_FAILED;
1228
62
        ret = RNG_FAILURE_E;
1229
62
    }
1230
5.57k
    else {
1231
5.57k
        rng->status = DRBG_FAILED;
1232
5.57k
    }
1233
113k
#endif /* HAVE_HASHDRBG */
1234
113k
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
1235
1236
113k
    return ret;
1237
113k
}
1238
1239
1240
WOLFSSL_ABI
1241
WC_RNG* wc_rng_new(byte* nonce, word32 nonceSz, void* heap)
1242
0
{
1243
0
    int ret = 0;
1244
0
    WC_RNG* rng = NULL;
1245
1246
    /* Assume if WC_USE_DEVID it is intended for default usage */
1247
#ifdef WC_USE_DEVID
1248
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, WC_USE_DEVID);
1249
#else
1250
0
    ret = wc_rng_new_ex(&rng, nonce, nonceSz, heap, INVALID_DEVID);
1251
0
#endif
1252
1253
0
    if (ret != 0) {
1254
0
        return NULL;
1255
0
    }
1256
1257
0
    return rng;
1258
0
}
1259
1260
1261
int wc_rng_new_ex(WC_RNG **rng, byte* nonce, word32 nonceSz,
1262
                  void* heap, int devId)
1263
0
{
1264
0
    int ret;
1265
1266
0
    *rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), heap, DYNAMIC_TYPE_RNG);
1267
0
    if (*rng == NULL) {
1268
0
        return MEMORY_E;
1269
0
    }
1270
1271
0
    ret = _InitRng(*rng, nonce, nonceSz, heap, devId);
1272
0
    if (ret != 0) {
1273
0
        XFREE(*rng, heap, DYNAMIC_TYPE_RNG);
1274
0
        *rng = NULL;
1275
0
    }
1276
1277
0
    return ret;
1278
0
}
1279
1280
1281
WOLFSSL_ABI
1282
void wc_rng_free(WC_RNG* rng)
1283
0
{
1284
0
    if (rng) {
1285
0
        void* heap = rng->heap;
1286
1287
0
        wc_FreeRng(rng);
1288
0
        ForceZero(rng, sizeof(WC_RNG));
1289
0
        XFREE(rng, heap, DYNAMIC_TYPE_RNG);
1290
0
        (void)heap;
1291
0
    }
1292
0
}
1293
1294
WOLFSSL_ABI
1295
int wc_InitRng(WC_RNG* rng)
1296
2.70k
{
1297
2.70k
    return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID);
1298
2.70k
}
1299
1300
1301
int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId)
1302
123k
{
1303
123k
    return _InitRng(rng, NULL, 0, heap, devId);
1304
123k
}
1305
1306
1307
int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz)
1308
0
{
1309
0
    return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID);
1310
0
}
1311
1312
1313
int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz,
1314
                       void* heap, int devId)
1315
0
{
1316
0
    return _InitRng(rng, nonce, nonceSz, heap, devId);
1317
0
}
1318
1319
#ifdef HAVE_HASHDRBG
1320
static int PollAndReSeed(WC_RNG* rng)
1321
0
{
1322
0
    int ret   = DRBG_NEED_RESEED;
1323
0
    int devId = INVALID_DEVID;
1324
0
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
1325
0
    devId = rng->devId;
1326
0
#endif
1327
0
    if (wc_RNG_HealthTestLocal(rng, 1, rng->heap, devId) == 0) {
1328
    #if defined(WOLFSSL_SMALL_STACK_CACHE)
1329
        byte* newSeed = rng->newSeed_buf;
1330
        ret = DRBG_SUCCESS;
1331
    #elif defined(WOLFSSL_SMALL_STACK)
1332
0
        byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap,
1333
0
            DYNAMIC_TYPE_SEED);
1334
0
        ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS;
1335
    #else
1336
        byte newSeed[SEED_SZ + SEED_BLOCK_SZ];
1337
        ret = DRBG_SUCCESS;
1338
    #endif
1339
0
        if (ret == DRBG_SUCCESS) {
1340
        #ifdef WC_RNG_SEED_CB
1341
            if (seedCb == NULL) {
1342
                ret = DRBG_NO_SEED_CB;
1343
            }
1344
            else {
1345
                ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
1346
                if (ret != 0) {
1347
    #ifdef WC_VERBOSE_RNG
1348
                    WOLFSSL_DEBUG_PRINTF("ERROR: seedCb() in PollAndReSeed() "
1349
                                         "failed with err %d", ret);
1350
    #endif
1351
                    ret = DRBG_FAILURE;
1352
                }
1353
            }
1354
        #else
1355
0
            ret = wc_GenerateSeed(&rng->seed, newSeed,
1356
0
                              SEED_SZ + SEED_BLOCK_SZ);
1357
0
            if (ret != 0) {
1358
    #ifdef WC_VERBOSE_RNG
1359
                WOLFSSL_DEBUG_PRINTF(
1360
                    "ERROR: wc_GenerateSeed() in PollAndReSeed() failed with "
1361
                    "err %d", ret);
1362
    #endif
1363
0
                ret = DRBG_FAILURE;
1364
0
            }
1365
0
        #endif
1366
0
        }
1367
0
        if (ret == DRBG_SUCCESS) {
1368
0
            ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
1369
    #ifdef WC_VERBOSE_RNG
1370
            if (ret != DRBG_SUCCESS)
1371
                WOLFSSL_DEBUG_PRINTF(
1372
                    "ERROR: wc_RNG_TestSeed() in PollAndReSeed() returned "
1373
                    "err %d.", ret);
1374
    #endif
1375
0
        }
1376
0
        if (ret == DRBG_SUCCESS)
1377
0
            ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg,
1378
0
                                   newSeed + SEED_BLOCK_SZ, SEED_SZ);
1379
0
    #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
1380
0
        if (newSeed != NULL) {
1381
0
            ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ);
1382
0
        }
1383
0
        XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED);
1384
    #else
1385
        ForceZero(newSeed, sizeof(newSeed));
1386
    #endif
1387
0
    }
1388
0
    else {
1389
0
        ret = DRBG_CONT_FAILURE;
1390
0
    }
1391
1392
0
    return ret;
1393
0
}
1394
#endif
1395
1396
/* place a generated block in output */
1397
#ifdef WC_RNG_BANK_SUPPORT
1398
static int wc_local_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
1399
#else
1400
WOLFSSL_ABI
1401
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
1402
#endif
1403
432k
{
1404
432k
    int ret;
1405
1406
432k
    if (rng == NULL || output == NULL)
1407
0
        return BAD_FUNC_ARG;
1408
1409
432k
    if (sz == 0)
1410
572
        return 0;
1411
1412
432k
#ifdef WOLF_CRYPTO_CB
1413
432k
    #ifndef WOLF_CRYPTO_CB_FIND
1414
432k
    if (rng->devId != INVALID_DEVID)
1415
24.3k
    #endif
1416
24.3k
    {
1417
24.3k
        ret = wc_CryptoCb_RandomBlock(rng, output, sz);
1418
24.3k
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
1419
24.3k
            return ret;
1420
        /* fall-through when unavailable */
1421
24.3k
    }
1422
407k
#endif
1423
1424
#ifdef HAVE_INTEL_RDRAND
1425
    if (IS_INTEL_RDRAND(intel_flags))
1426
        return wc_GenerateRand_IntelRD(NULL, output, sz);
1427
#endif
1428
1429
#if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_TRNG)
1430
    return silabs_GenerateRand(output, sz);
1431
#endif
1432
1433
#if defined(WOLFSSL_ASYNC_CRYPT)
1434
    if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) {
1435
        /* these are blocking */
1436
    #ifdef HAVE_CAVIUM
1437
        return NitroxRngGenerateBlock(rng, output, sz);
1438
    #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG)
1439
        return IntelQaDrbg(&rng->asyncDev, output, sz);
1440
    #else
1441
        /* simulator not supported */
1442
    #endif
1443
    }
1444
#endif
1445
1446
#ifdef CUSTOM_RAND_GENERATE_BLOCK
1447
    XMEMSET(output, 0, sz);
1448
    ret = (int)CUSTOM_RAND_GENERATE_BLOCK(output, sz);
1449
    #ifdef WC_VERBOSE_RNG
1450
    if (ret != 0)
1451
        WOLFSSL_DEBUG_PRINTF(
1452
            "ERROR: CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
1453
    #endif
1454
#else
1455
1456
407k
#ifdef HAVE_HASHDRBG
1457
407k
    if (sz > RNG_MAX_BLOCK_LEN)
1458
0
        return BAD_FUNC_ARG;
1459
1460
407k
    if (rng->status != DRBG_OK)
1461
19
        return RNG_FAILURE_E;
1462
1463
407k
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
1464
407k
    if (rng->pid != getpid()) {
1465
0
        rng->pid = getpid();
1466
0
        ret = PollAndReSeed(rng);
1467
0
        if (ret != DRBG_SUCCESS) {
1468
0
            rng->status = DRBG_FAILED;
1469
0
            return RNG_FAILURE_E;
1470
0
        }
1471
0
    }
1472
407k
#endif
1473
1474
407k
    ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz);
1475
407k
    if (ret == DRBG_NEED_RESEED) {
1476
0
        ret = PollAndReSeed(rng);
1477
0
        if (ret == DRBG_SUCCESS)
1478
0
            ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz);
1479
0
    }
1480
1481
407k
    if (ret == DRBG_SUCCESS) {
1482
400k
        ret = 0;
1483
400k
    }
1484
7.39k
    else if (ret == DRBG_CONT_FAILURE) {
1485
0
        ret = DRBG_CONT_FIPS_E;
1486
0
        rng->status = DRBG_CONT_FAILED;
1487
0
    }
1488
7.39k
    else {
1489
7.39k
        ret = RNG_FAILURE_E;
1490
7.39k
        rng->status = DRBG_FAILED;
1491
7.39k
    }
1492
#else
1493
1494
    /* if we get here then there is an RNG configuration error */
1495
    ret = RNG_FAILURE_E;
1496
1497
#endif /* HAVE_HASHDRBG */
1498
407k
#endif /* CUSTOM_RAND_GENERATE_BLOCK */
1499
1500
407k
    return ret;
1501
407k
}
1502
1503
#ifdef WC_RNG_BANK_SUPPORT
1504
WOLFSSL_ABI
1505
int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
1506
{
1507
    if (rng == NULL)
1508
        return BAD_FUNC_ARG;
1509
1510
    if (rng->status == WC_DRBG_BANKREF) {
1511
        int ret;
1512
        struct wc_rng_bank_inst *bank_inst = NULL;
1513
1514
        ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst);
1515
        if (ret != 0)
1516
            return ret;
1517
        if (bank_inst == NULL)
1518
            return BAD_STATE_E;
1519
        ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst),
1520
                                         output, sz);
1521
        {
1522
            int checkin_ret = wc_rng_bank_checkin(rng->bankref, &bank_inst);
1523
            if (checkin_ret != 0) {
1524
#ifdef WC_VERBOSE_RNG
1525
                WOLFSSL_DEBUG_PRINTF(
1526
                    "ERROR: wc_RNG_GenerateBlock() wc_rng_bank_checkin() "
1527
                    "failed with err %d.", checkin_ret);
1528
#endif
1529
                if (ret == 0)
1530
                    ret = checkin_ret;
1531
            }
1532
        }
1533
        return ret;
1534
    }
1535
    else
1536
        return wc_local_RNG_GenerateBlock(rng, output, sz);
1537
}
1538
#endif
1539
1540
int wc_RNG_GenerateByte(WC_RNG* rng, byte* b)
1541
0
{
1542
0
    return wc_RNG_GenerateBlock(rng, b, 1);
1543
0
}
1544
1545
1546
int wc_FreeRng(WC_RNG* rng)
1547
119k
{
1548
119k
    int ret = 0;
1549
1550
119k
    if (rng == NULL)
1551
0
        return BAD_FUNC_ARG;
1552
1553
#ifdef WC_RNG_BANK_SUPPORT
1554
    if (rng->status == WC_DRBG_BANKREF)
1555
        return wc_BankRef_Release(rng);
1556
#endif /* WC_RNG_BANK_SUPPORT */
1557
1558
#if defined(WOLFSSL_ASYNC_CRYPT)
1559
    wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG);
1560
#endif
1561
1562
119k
#ifdef HAVE_HASHDRBG
1563
119k
    if (rng->drbg != NULL) {
1564
118k
      if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg) != DRBG_SUCCESS)
1565
0
            ret = RNG_FAILURE_E;
1566
1567
118k
    #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY)
1568
118k
        XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG);
1569
    #elif defined(WOLFSSL_CHECK_MEM_ZERO)
1570
        wc_MemZero_Check(rng->drbg, sizeof(DRBG_internal));
1571
    #endif
1572
118k
        rng->drbg = NULL;
1573
118k
    }
1574
1575
    #ifdef WOLFSSL_SMALL_STACK_CACHE
1576
    if (rng->drbg_scratch != NULL) {
1577
        if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch) != DRBG_SUCCESS)
1578
            ret = RNG_FAILURE_E;
1579
        XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG);
1580
        rng->drbg_scratch = NULL;
1581
    }
1582
    XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_RNG);
1583
    rng->health_check_scratch = NULL;
1584
    XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_RNG);
1585
    rng->newSeed_buf = NULL;
1586
    #endif
1587
1588
119k
    rng->status = DRBG_NOT_INIT;
1589
119k
#endif /* HAVE_HASHDRBG */
1590
1591
#ifdef WOLFSSL_XILINX_CRYPT_VERSAL
1592
    /* don't overwrite previously set error */
1593
    if (wc_VersalTrngReset() && !ret)
1594
        ret = WC_HW_E;
1595
#endif
1596
1597
#if defined(WOLFSSL_KEEP_RNG_SEED_FD_OPEN) && defined(XCLOSE) && \
1598
    !defined(USE_WINDOWS_API)
1599
    if(rng->seed.seedFdOpen && rng->seed.fd != XBADFD) {
1600
        XCLOSE(rng->seed.fd);
1601
        rng->seed.fd = XBADFD;
1602
        rng->seed.seedFdOpen = 0;
1603
    }
1604
#endif
1605
1606
119k
    return ret;
1607
119k
}
1608
1609
#ifdef HAVE_HASHDRBG
1610
int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz,
1611
                                  const byte* seedB, word32 seedBSz,
1612
                                  byte* output, word32 outputSz)
1613
0
{
1614
0
    return wc_RNG_HealthTest_ex(reseed, NULL, 0,
1615
0
                                seedA, seedASz, seedB, seedBSz,
1616
0
                                output, outputSz,
1617
0
                                NULL, INVALID_DEVID);
1618
0
}
1619
1620
1621
static int wc_RNG_HealthTest_ex_internal(DRBG_internal* drbg,
1622
                                  int reseed, const byte* nonce, word32 nonceSz,
1623
                                  const byte* seedA, word32 seedASz,
1624
                                  const byte* seedB, word32 seedBSz,
1625
                                  byte* output, word32 outputSz,
1626
                                  void* heap, int devId)
1627
238k
{
1628
238k
    int ret = -1;
1629
1630
238k
    if (seedA == NULL || output == NULL) {
1631
0
        return BAD_FUNC_ARG;
1632
0
    }
1633
1634
238k
    if (reseed != 0 && seedB == NULL) {
1635
0
        return BAD_FUNC_ARG;
1636
0
    }
1637
1638
238k
    if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) {
1639
0
        return ret;
1640
0
    }
1641
1642
#ifdef WOLFSSL_SMALL_STACK_CACHE
1643
    (void)heap;
1644
    (void)devId;
1645
1646
    if (Hash_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz) != 0) {
1647
        goto exit_rng_ht;
1648
    }
1649
#else
1650
238k
    if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz,
1651
238k
                              heap, devId) != 0) {
1652
363
        goto exit_rng_ht;
1653
363
    }
1654
238k
#endif
1655
1656
238k
    if (reseed) {
1657
0
        if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) {
1658
0
            goto exit_rng_ht;
1659
0
        }
1660
0
    }
1661
1662
    /* This call to generate is prescribed by the NIST DRBGVS
1663
     * procedure. The results are thrown away. The known
1664
     * answer test checks the second block of DRBG out of
1665
     * the generator to ensure the internal state is updated
1666
     * as expected. */
1667
238k
    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
1668
141
        goto exit_rng_ht;
1669
141
    }
1670
1671
238k
    if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) {
1672
90
        goto exit_rng_ht;
1673
90
    }
1674
1675
    /* Mark success */
1676
238k
    ret = 0;
1677
1678
238k
exit_rng_ht:
1679
1680
238k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1681
    /* This is safe to call even if Hash_DRBG_Instantiate fails */
1682
238k
    if (Hash_DRBG_Uninstantiate(drbg) != 0) {
1683
0
        ret = -1;
1684
0
    }
1685
238k
#endif
1686
1687
238k
    return ret;
1688
238k
}
1689
1690
int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz,
1691
                                  const byte* seedA, word32 seedASz,
1692
                                  const byte* seedB, word32 seedBSz,
1693
                                  byte* output, word32 outputSz,
1694
                                  void* heap, int devId)
1695
0
{
1696
0
    int ret = -1;
1697
0
    DRBG_internal* drbg;
1698
#ifndef WOLFSSL_SMALL_STACK
1699
    DRBG_internal  drbg_var;
1700
#endif
1701
1702
0
#ifdef WOLFSSL_SMALL_STACK
1703
0
    drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap,
1704
0
        DYNAMIC_TYPE_RNG);
1705
0
    if (drbg == NULL) {
1706
0
        return MEMORY_E;
1707
0
    }
1708
#else
1709
    drbg = &drbg_var;
1710
#endif
1711
1712
#ifdef WOLFSSL_SMALL_STACK_CACHE
1713
    ret = Hash_DRBG_Instantiate(drbg,
1714
                    NULL /* seed */, 0, NULL /* nonce */, 0, heap, devId);
1715
    if (ret == 0)
1716
#endif
1717
0
    {
1718
0
        ret = wc_RNG_HealthTest_ex_internal(
1719
0
                drbg, reseed, nonce, nonceSz, seedA, seedASz,
1720
0
                seedB, seedBSz, output, outputSz, heap, devId);
1721
#ifdef WOLFSSL_SMALL_STACK_CACHE
1722
        Hash_DRBG_Uninstantiate(drbg);
1723
#endif
1724
0
    }
1725
0
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_RNG);
1726
1727
0
    return ret;
1728
0
}
1729
1730
1731
const FLASH_QUALIFIER byte seedA_data[] = {
1732
    0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4,
1733
    0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00,
1734
    0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f,
1735
    0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68
1736
};
1737
1738
const FLASH_QUALIFIER byte reseedSeedA_data[] = {
1739
    0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3,
1740
    0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22,
1741
    0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3
1742
};
1743
1744
const FLASH_QUALIFIER byte outputA_data[] = {
1745
    0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb,
1746
    0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79,
1747
    0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc,
1748
    0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac,
1749
    0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71,
1750
    0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0,
1751
    0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8,
1752
    0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d,
1753
    0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22,
1754
    0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07,
1755
    0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17
1756
};
1757
1758
const FLASH_QUALIFIER byte seedB_data[] = {
1759
    0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3,
1760
    0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19,
1761
    0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */
1762
    0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d,
1763
    0xdb, 0xcb, 0xcc, 0x2e
1764
};
1765
1766
const FLASH_QUALIFIER byte outputB_data[] = {
1767
    0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64,
1768
    0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5,
1769
    0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3,
1770
    0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11,
1771
    0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81,
1772
    0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63,
1773
    0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7,
1774
    0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c,
1775
    0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91,
1776
    0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d,
1777
    0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf
1778
};
1779
1780
1781
static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap,
1782
                                  int devId)
1783
107k
{
1784
107k
    int ret = 0;
1785
#ifdef WOLFSSL_SMALL_STACK_CACHE
1786
    byte *check = rng->health_check_scratch;
1787
    DRBG_internal* drbg = (DRBG_internal *)rng->drbg_scratch;
1788
#else
1789
107k
    WC_DECLARE_VAR(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, 0);
1790
107k
    WC_DECLARE_VAR(drbg, DRBG_internal, 1, 0);
1791
1792
107k
    (void)rng;
1793
1794
107k
    WC_ALLOC_VAR_EX(check, byte, RNG_HEALTH_TEST_CHECK_SIZE, heap,
1795
107k
        DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
1796
106k
    WC_ALLOC_VAR_EX(drbg, DRBG_internal, 1, heap,
1797
106k
        DYNAMIC_TYPE_TMP_BUFFER, WC_DO_NOTHING);
1798
106k
    #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
1799
106k
    if (drbg == NULL) {
1800
149
        WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
1801
149
        return MEMORY_E;
1802
149
    }
1803
106k
    #endif
1804
106k
#endif
1805
1806
106k
    if (reseed) {
1807
#ifdef WOLFSSL_USE_FLASHMEM
1808
        byte* seedA = (byte*)XMALLOC(sizeof(seedA_data), heap,
1809
                             DYNAMIC_TYPE_TMP_BUFFER);
1810
        byte* reseedSeedA = (byte*)XMALLOC(sizeof(reseedSeedA_data), heap,
1811
                             DYNAMIC_TYPE_TMP_BUFFER);
1812
        byte* outputA = (byte*)XMALLOC(sizeof(outputA_data), heap,
1813
                             DYNAMIC_TYPE_TMP_BUFFER);
1814
1815
        if (!seedA || !reseedSeedA || !outputA) {
1816
            XFREE(seedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
1817
            XFREE(reseedSeedA, heap, DYNAMIC_TYPE_TMP_BUFFER);
1818
            XFREE(outputA, heap, DYNAMIC_TYPE_TMP_BUFFER);
1819
            ret = MEMORY_E;
1820
        }
1821
        else {
1822
            XMEMCPY_P(seedA, seedA_data, sizeof(seedA_data));
1823
            XMEMCPY_P(reseedSeedA, reseedSeedA_data, sizeof(reseedSeedA_data));
1824
            XMEMCPY_P(outputA, outputA_data, sizeof(outputA_data));
1825
#else
1826
0
        const byte* seedA = seedA_data;
1827
0
        const byte* reseedSeedA = reseedSeedA_data;
1828
0
        const byte* outputA = outputA_data;
1829
0
#endif
1830
0
        ret = wc_RNG_HealthTest_ex_internal(drbg, 1, NULL, 0,
1831
0
                                   seedA, sizeof(seedA_data),
1832
0
                                   reseedSeedA, sizeof(reseedSeedA_data),
1833
0
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
1834
0
                                   heap, devId);
1835
0
        if (ret == 0) {
1836
0
            if (ConstantCompare(check, outputA,
1837
0
                                RNG_HEALTH_TEST_CHECK_SIZE) != 0)
1838
0
                ret = -1;
1839
0
        }
1840
1841
#ifdef WOLFSSL_USE_FLASHMEM
1842
            XFREE(seedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1843
            XFREE(reseedSeedA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1844
            XFREE(outputA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1845
        }
1846
#endif
1847
0
    }
1848
106k
    else {
1849
#ifdef WOLFSSL_USE_FLASHMEM
1850
        byte* seedB = (byte*)XMALLOC(sizeof(seedB_data), heap,
1851
                             DYNAMIC_TYPE_TMP_BUFFER);
1852
        byte* outputB = (byte*)XMALLOC(sizeof(outputB_data), heap,
1853
                               DYNAMIC_TYPE_TMP_BUFFER);
1854
1855
        if (!seedB || !outputB) {
1856
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
1857
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
1858
            ret = MEMORY_E;
1859
        }
1860
        else {
1861
            XMEMCPY_P(seedB, seedB_data, sizeof(seedB_data));
1862
            XMEMCPY_P(outputB, outputB_data, sizeof(outputB_data));
1863
#else
1864
106k
        const byte* seedB = seedB_data;
1865
106k
        const byte* outputB = outputB_data;
1866
106k
#endif
1867
#if defined(DEBUG_WOLFSSL)
1868
        WOLFSSL_MSG_EX("RNG_HEALTH_TEST_CHECK_SIZE = %d",
1869
                        RNG_HEALTH_TEST_CHECK_SIZE);
1870
        WOLFSSL_MSG_EX("sizeof(seedB_data)         = %d",
1871
                        (int)sizeof(outputB_data));
1872
#endif
1873
106k
        ret = wc_RNG_HealthTest_ex_internal(drbg, 0, NULL, 0,
1874
106k
                                   seedB, sizeof(seedB_data),
1875
106k
                                   NULL, 0,
1876
106k
                                   check, RNG_HEALTH_TEST_CHECK_SIZE,
1877
106k
                                   heap, devId);
1878
106k
        if (ret != 0) {
1879
            #if defined(DEBUG_WOLFSSL)
1880
            WOLFSSL_MSG_EX("RNG_HealthTest failed: err = %d", ret);
1881
            #endif
1882
481
        }
1883
106k
        else {
1884
106k
            ret = ConstantCompare(check, outputB,
1885
106k
                                RNG_HEALTH_TEST_CHECK_SIZE);
1886
106k
            if (ret != 0) {
1887
                #if defined(DEBUG_WOLFSSL)
1888
                WOLFSSL_MSG_EX("Random ConstantCompare failed: err = %d", ret);
1889
                #endif
1890
31
                ret = -1;
1891
31
            }
1892
106k
        }
1893
1894
        /* The previous test cases use a large seed instead of a seed and nonce.
1895
         * seedB is actually from a test case with a seed and nonce, and
1896
         * just concatenates them. The pivot point between seed and nonce is
1897
         * byte 32, feed them into the health test separately. */
1898
106k
        if (ret == 0) {
1899
106k
            ret = wc_RNG_HealthTest_ex_internal(drbg, 0,
1900
106k
                                       seedB + 32, sizeof(seedB_data) - 32,
1901
106k
                                       seedB, 32,
1902
106k
                                       NULL, 0,
1903
106k
                                       check, RNG_HEALTH_TEST_CHECK_SIZE,
1904
106k
                                       heap, devId);
1905
106k
            if (ret == 0) {
1906
106k
                if (ConstantCompare(check, outputB, sizeof(outputB_data)) != 0)
1907
19
                    ret = -1;
1908
106k
            }
1909
106k
        }
1910
1911
#ifdef WOLFSSL_USE_FLASHMEM
1912
            XFREE(seedB, heap, DYNAMIC_TYPE_TMP_BUFFER);
1913
            XFREE(outputB, heap, DYNAMIC_TYPE_TMP_BUFFER);
1914
        }
1915
#endif
1916
106k
    }
1917
1918
106k
#ifndef WOLFSSL_SMALL_STACK_CACHE
1919
106k
    WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER);
1920
106k
    WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_TMP_BUFFER);
1921
106k
#endif
1922
1923
106k
    return ret;
1924
106k
}
1925
1926
#endif /* HAVE_HASHDRBG */
1927
1928
1929
#ifdef HAVE_WNR
1930
1931
/*
1932
 * Init global Whitewood netRandom context
1933
 * Returns 0 on success, negative on error
1934
 */
1935
int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout)
1936
{
1937
    int ret;
1938
1939
    if (configFile == NULL || timeout < 0)
1940
        return BAD_FUNC_ARG;
1941
1942
#ifndef WOLFSSL_MUTEX_INITIALIZER
1943
    if (wnr_mutex_inited > 0) {
1944
        WOLFSSL_MSG("netRandom context already created, skipping");
1945
        return 0;
1946
    }
1947
1948
    if (wc_InitMutex(&wnr_mutex) != 0) {
1949
        WOLFSSL_MSG("Bad Init Mutex wnr_mutex");
1950
        return BAD_MUTEX_E;
1951
    }
1952
1953
    wnr_mutex_inited = 1;
1954
#endif
1955
1956
    if (wnr_inited > 0) {
1957
        WOLFSSL_MSG("netRandom context already created, skipping");
1958
        return 0;
1959
    }
1960
1961
    if (wc_LockMutex(&wnr_mutex) != 0) {
1962
        WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
1963
        return BAD_MUTEX_E;
1964
    }
1965
1966
    /* store entropy timeout */
1967
    wnr_timeout = timeout;
1968
1969
    /* create global wnr_context struct */
1970
    if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) {
1971
        WOLFSSL_MSG("Error creating global netRandom context");
1972
        ret = RNG_FAILURE_E;
1973
        goto out;
1974
    }
1975
1976
    /* load config file */
1977
    if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) {
1978
        WOLFSSL_MSG("Error loading config file into netRandom context");
1979
        wnr_destroy(wnr_ctx);
1980
        wnr_ctx = NULL;
1981
        ret = RNG_FAILURE_E;
1982
        goto out;
1983
    }
1984
1985
    /* create/init polling mechanism */
1986
    if (wnr_poll_create() != WNR_ERROR_NONE) {
1987
        WOLFSSL_MSG("Error initializing netRandom polling mechanism");
1988
        wnr_destroy(wnr_ctx);
1989
        wnr_ctx = NULL;
1990
        ret = RNG_FAILURE_E;
1991
        goto out;
1992
    }
1993
1994
    /* validate config, set HMAC callback (optional) */
1995
    if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) {
1996
        WOLFSSL_MSG("Error setting up netRandom context");
1997
        wnr_destroy(wnr_ctx);
1998
        wnr_ctx = NULL;
1999
        wnr_poll_destroy();
2000
        ret = RNG_FAILURE_E;
2001
        goto out;
2002
    }
2003
2004
    wnr_inited = 1;
2005
2006
out:
2007
2008
    wc_UnLockMutex(&wnr_mutex);
2009
2010
    return ret;
2011
}
2012
2013
/*
2014
 * Free global Whitewood netRandom context
2015
 * Returns 0 on success, negative on error
2016
 */
2017
int wc_FreeNetRandom(void)
2018
{
2019
    if (wnr_inited > 0) {
2020
2021
        if (wc_LockMutex(&wnr_mutex) != 0) {
2022
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
2023
            return BAD_MUTEX_E;
2024
        }
2025
2026
        if (wnr_ctx != NULL) {
2027
            wnr_destroy(wnr_ctx);
2028
            wnr_ctx = NULL;
2029
        }
2030
        wnr_poll_destroy();
2031
2032
        wc_UnLockMutex(&wnr_mutex);
2033
2034
#ifndef WOLFSSL_MUTEX_INITIALIZER
2035
        wc_FreeMutex(&wnr_mutex);
2036
        wnr_mutex_inited = 0;
2037
#endif
2038
2039
        wnr_inited = 0;
2040
    }
2041
2042
    return 0;
2043
}
2044
2045
#endif /* HAVE_WNR */
2046
2047
2048
#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \
2049
    defined(HAVE_AMD_RDSEED)
2050
2051
#ifdef WOLFSSL_ASYNC_CRYPT
2052
    /* need more retries if multiple cores */
2053
    #define INTELRD_RETRY (32 * 8)
2054
#else
2055
    #define INTELRD_RETRY 32
2056
#endif
2057
2058
#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
2059
2060
#ifndef USE_INTEL_INTRINSICS
2061
2062
    /* return 0 on success */
2063
    static WC_INLINE int IntelRDseed64(word64* seed)
2064
    {
2065
        unsigned char ok;
2066
2067
        __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok));
2068
        return (ok) ? 0 : -1;
2069
    }
2070
2071
#else /* USE_INTEL_INTRINSICS */
2072
    /* The compiler Visual Studio uses does not allow inline assembly.
2073
     * It does allow for Intel intrinsic functions. */
2074
2075
    /* return 0 on success */
2076
# ifdef __GNUC__
2077
    __attribute__((target("rdseed")))
2078
# endif
2079
    static WC_INLINE int IntelRDseed64(word64* seed)
2080
    {
2081
        int ok;
2082
2083
        ok = _rdseed64_step((unsigned long long*) seed);
2084
        return (ok) ? 0 : -1;
2085
    }
2086
2087
#endif /* USE_INTEL_INTRINSICS */
2088
2089
/* return 0 on success */
2090
static WC_INLINE int IntelRDseed64_r(word64* rnd)
2091
{
2092
    int i;
2093
    for (i = 0; i < INTELRD_RETRY; i++) {
2094
        if (IntelRDseed64(rnd) == 0)
2095
            return 0;
2096
    }
2097
    return -1;
2098
}
2099
2100
/* return 0 on success */
2101
static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz)
2102
{
2103
    int ret;
2104
    word64 rndTmp;
2105
    static int rdseed_sanity_status = 0;
2106
2107
    (void)os;
2108
2109
    if (!IS_INTEL_RDSEED(intel_flags))
2110
        return -1;
2111
2112
    /* Note, access to rdseed_sanity_status is benignly racey on multithreaded
2113
     * targets.
2114
     */
2115
    if (rdseed_sanity_status == 0) {
2116
        word64 sanity_word1 = 0, sanity_word2 = 0;
2117
2118
        ret = IntelRDseed64_r(&sanity_word1);
2119
        if (ret != 0)
2120
            return ret;
2121
2122
        ret = IntelRDseed64_r(&sanity_word2);
2123
        if (ret != 0)
2124
            return ret;
2125
2126
        if (sanity_word1 == sanity_word2) {
2127
            ret = IntelRDseed64_r(&sanity_word1);
2128
            if (ret != 0)
2129
                return ret;
2130
2131
            if (sanity_word1 == sanity_word2) {
2132
#ifdef WC_VERBOSE_RNG
2133
                WOLFSSL_DEBUG_PRINTF(
2134
                    "WARNING: disabling RDSEED due to repeating word 0x%lx -- "
2135
                    "check CPU microcode version.", sanity_word2);
2136
#endif
2137
                rdseed_sanity_status = -1;
2138
                return -1;
2139
            }
2140
        }
2141
2142
        rdseed_sanity_status = 1;
2143
    }
2144
    else if (rdseed_sanity_status < 0) {
2145
        return -1;
2146
    }
2147
2148
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
2149
                                                    output += sizeof(word64)) {
2150
        ret = IntelRDseed64_r((word64*)output);
2151
        if (ret != 0)
2152
            return ret;
2153
    }
2154
    if (sz == 0)
2155
        return 0;
2156
2157
    /* handle unaligned remainder */
2158
    ret = IntelRDseed64_r(&rndTmp);
2159
    if (ret != 0)
2160
        return ret;
2161
2162
    XMEMCPY(output, &rndTmp, sz);
2163
    ForceZero(&rndTmp, sizeof(rndTmp));
2164
2165
    return 0;
2166
}
2167
2168
#endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
2169
2170
#ifdef HAVE_INTEL_RDRAND
2171
2172
#ifndef USE_INTEL_INTRINSICS
2173
2174
/* return 0 on success */
2175
static WC_INLINE int IntelRDrand64(word64 *rnd)
2176
{
2177
    unsigned char ok;
2178
2179
    __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok));
2180
2181
    return (ok) ? 0 : -1;
2182
}
2183
2184
#else /* USE_INTEL_INTRINSICS */
2185
    /* The compiler Visual Studio uses does not allow inline assembly.
2186
     * It does allow for Intel intrinsic functions. */
2187
2188
/* return 0 on success */
2189
# ifdef __GNUC__
2190
__attribute__((target("rdrnd")))
2191
# endif
2192
static WC_INLINE int IntelRDrand64(word64 *rnd)
2193
{
2194
    int ok;
2195
2196
    ok = _rdrand64_step((unsigned long long*) rnd);
2197
2198
    return (ok) ? 0 : -1;
2199
}
2200
2201
#endif /* USE_INTEL_INTRINSICS */
2202
2203
/* return 0 on success */
2204
static WC_INLINE int IntelRDrand64_r(word64 *rnd)
2205
{
2206
    int i;
2207
    for (i = 0; i < INTELRD_RETRY; i++) {
2208
        if (IntelRDrand64(rnd) == 0)
2209
            return 0;
2210
    }
2211
    return -1;
2212
}
2213
2214
/* return 0 on success */
2215
static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz)
2216
{
2217
    int ret;
2218
    word64 rndTmp;
2219
2220
    (void)os;
2221
2222
    if (!IS_INTEL_RDRAND(intel_flags))
2223
        return -1;
2224
2225
    for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64),
2226
                                                    output += sizeof(word64)) {
2227
        ret = IntelRDrand64_r((word64 *)output);
2228
        if (ret != 0)
2229
            return ret;
2230
    }
2231
    if (sz == 0)
2232
        return 0;
2233
2234
    /* handle unaligned remainder */
2235
    ret = IntelRDrand64_r(&rndTmp);
2236
    if (ret != 0)
2237
        return ret;
2238
2239
    XMEMCPY(output, &rndTmp, sz);
2240
2241
    return 0;
2242
}
2243
2244
#endif /* HAVE_INTEL_RDRAND */
2245
#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
2246
2247
2248
/* Begin wc_GenerateSeed Implementations */
2249
#if defined(CUSTOM_RAND_GENERATE_SEED)
2250
2251
    /* Implement your own random generation function
2252
     * Return 0 to indicate success
2253
     * int rand_gen_seed(byte* output, word32 sz);
2254
     * #define CUSTOM_RAND_GENERATE_SEED  rand_gen_seed */
2255
2256
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2257
    {
2258
        (void)os; /* Suppress unused arg warning */
2259
        return CUSTOM_RAND_GENERATE_SEED(output, sz);
2260
    }
2261
2262
#elif defined(CUSTOM_RAND_GENERATE_SEED_OS)
2263
2264
    /* Implement your own random generation function,
2265
     *  which includes OS_Seed.
2266
     * Return 0 to indicate success
2267
     * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz);
2268
     * #define CUSTOM_RAND_GENERATE_SEED_OS  rand_gen_seed */
2269
2270
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2271
    {
2272
        return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz);
2273
    }
2274
2275
#elif defined(CUSTOM_RAND_GENERATE)
2276
2277
   /* Implement your own random generation function
2278
    * word32 rand_gen(void);
2279
    * #define CUSTOM_RAND_GENERATE  rand_gen  */
2280
2281
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2282
    {
2283
        word32 i = 0;
2284
2285
        (void)os;
2286
2287
        while (i < sz)
2288
        {
2289
            /* If not aligned or there is odd/remainder */
2290
            if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz ||
2291
                ((wc_ptr_t)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0
2292
            ) {
2293
                /* Single byte at a time */
2294
                output[i++] = (byte)CUSTOM_RAND_GENERATE();
2295
            }
2296
            else {
2297
                /* Use native 8, 16, 32 or 64 copy instruction */
2298
                *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE();
2299
                i += sizeof(CUSTOM_RAND_TYPE);
2300
            }
2301
        }
2302
2303
        return 0;
2304
    }
2305
2306
#elif defined(WOLFSSL_SGX)
2307
2308
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2309
{
2310
    int ret = !SGX_SUCCESS;
2311
    int i, read_max = 10;
2312
2313
    for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) {
2314
        ret = sgx_read_rand(output, sz);
2315
    }
2316
2317
    (void)os;
2318
    return (ret == SGX_SUCCESS) ? 0 : 1;
2319
}
2320
2321
#elif defined(USE_WINDOWS_API)
2322
2323
#ifdef WIN_REUSE_CRYPT_HANDLE
2324
/* shared crypt handle for RNG use */
2325
static ProviderHandle gHandle = 0;
2326
2327
int wc_WinCryptHandleInit(void)
2328
{
2329
    int ret = 0;
2330
    if (gHandle == 0) {
2331
        if(!CryptAcquireContext(&gHandle, 0, 0, PROV_RSA_FULL,
2332
                                        CRYPT_VERIFYCONTEXT)) {
2333
            DWORD dw = GetLastError();
2334
            WOLFSSL_MSG("CryptAcquireContext failed!");
2335
            WOLFSSL_ERROR((int)dw);
2336
            ret = WINCRYPT_E;
2337
        }
2338
    }
2339
    return ret;
2340
}
2341
2342
void wc_WinCryptHandleCleanup(void)
2343
{
2344
    if (gHandle != 0) {
2345
        CryptReleaseContext(gHandle, 0);
2346
        gHandle = 0;
2347
    }
2348
}
2349
#endif /* WIN_REUSE_CRYPT_HANDLE */
2350
2351
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2352
{
2353
#ifdef WOLF_CRYPTO_CB
2354
    int ret;
2355
2356
    if (os != NULL
2357
    #ifndef WOLF_CRYPTO_CB_FIND
2358
        && os->devId != INVALID_DEVID)
2359
    #endif
2360
    {
2361
        ret = wc_CryptoCb_RandomSeed(os, output, sz);
2362
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
2363
            return ret;
2364
        /* fall-through when unavailable */
2365
    }
2366
#endif
2367
2368
    #ifdef HAVE_INTEL_RDSEED
2369
        if (IS_INTEL_RDSEED(intel_flags)) {
2370
             if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) {
2371
                 /* success, we're done */
2372
                 return 0;
2373
             }
2374
        #ifdef FORCE_FAILURE_RDSEED
2375
             /* don't fall back to CryptoAPI */
2376
             return READ_RAN_E;
2377
        #endif
2378
        }
2379
    #endif /* HAVE_INTEL_RDSEED */
2380
2381
#ifdef WIN_REUSE_CRYPT_HANDLE
2382
    /* Check that handle was initialized.
2383
     * Note: initialization should be done through:
2384
     * wolfSSL_Init -> wolfCrypt_Init -> wc_WinCryptHandleInit
2385
     */
2386
    if (wc_WinCryptHandleInit() != 0) {
2387
        return WINCRYPT_E;
2388
    }
2389
    if (!CryptGenRandom(gHandle, sz, output))
2390
        return CRYPTGEN_E;
2391
#else
2392
    if (!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL,
2393
                            CRYPT_VERIFYCONTEXT)) {
2394
        return WINCRYPT_E;
2395
    }
2396
    if (!CryptGenRandom(os->handle, sz, output)) {
2397
        return CRYPTGEN_E;
2398
    }
2399
    CryptReleaseContext(os->handle, 0);
2400
    os->handle = 0;
2401
#endif
2402
2403
    return 0;
2404
}
2405
2406
2407
#elif defined(HAVE_RTP_SYS) || defined(EBSNET)
2408
2409
#include "rtprand.h"   /* rtp_rand () */
2410
2411
#if (defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)))
2412
#include "rtptime.h"   /* rtp_get_system_msec() */
2413
2414
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2415
{
2416
    word32 i;
2417
2418
    rtp_srand(rtp_get_system_msec());
2419
    for (i = 0; i < sz; i++ ) {
2420
        output[i] = rtp_rand() % 256;
2421
    }
2422
2423
    return 0;
2424
}
2425
#else
2426
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2427
{
2428
    word32 i;
2429
    KS_SEED(ks_get_ticks());
2430
2431
    for (i = 0; i < sz; i++ ) {
2432
        output[i] = KS_RANDOM() % 256;
2433
    }
2434
2435
    return 0;
2436
}
2437
#endif /* defined(HAVE_RTP_SYS) || (defined(RTPLATFORM) && (RTPLATFORM != 0)) */
2438
2439
#elif (defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC_RNG)) && \
2440
      !defined(WOLFSSL_PIC32MZ_RNG)
2441
    /* enable ATECC RNG unless using PIC32MZ one instead */
2442
    #include <wolfssl/wolfcrypt/port/atmel/atmel.h>
2443
2444
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2445
    {
2446
        int ret = 0;
2447
2448
        (void)os;
2449
        if (output == NULL) {
2450
            return BUFFER_E;
2451
        }
2452
2453
        ret = atmel_get_random_number(sz, output);
2454
2455
        return ret;
2456
    }
2457
2458
#elif defined(MICROCHIP_PIC32) || defined(MICROCHIP_MPLAB_HARMONY)
2459
2460
    #ifdef MICROCHIP_MPLAB_HARMONY
2461
        #ifdef MICROCHIP_MPLAB_HARMONY_3
2462
            #include "system/time/sys_time.h"
2463
            #define PIC32_SEED_COUNT SYS_TIME_CounterGet
2464
        #else
2465
            #define PIC32_SEED_COUNT _CP0_GET_COUNT
2466
        #endif
2467
    #else
2468
        #if !defined(WOLFSSL_MICROCHIP_PIC32MZ)
2469
            #include <peripheral/timer.h>
2470
        #endif
2471
        extern word32 ReadCoreTimer(void);
2472
        #define PIC32_SEED_COUNT ReadCoreTimer
2473
    #endif
2474
2475
    #ifdef WOLFSSL_PIC32MZ_RNG
2476
        #include "xc.h"
2477
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2478
        {
2479
            int i;
2480
            byte rnd[8];
2481
            word32 *rnd32 = (word32 *)rnd;
2482
            word32 size = sz;
2483
            byte* op = output;
2484
2485
#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C'))
2486
            RNGNUMGEN1 = _CP0_GET_COUNT();
2487
            RNGPOLY1 = _CP0_GET_COUNT();
2488
            RNGPOLY2 = _CP0_GET_COUNT();
2489
            RNGNUMGEN2 = _CP0_GET_COUNT();
2490
#else
2491
            /* All others can be seeded from the TRNG */
2492
            RNGCONbits.TRNGMODE = 1;
2493
            RNGCONbits.TRNGEN = 1;
2494
            while (RNGCNT < 64);
2495
            RNGCONbits.LOAD = 1;
2496
            while (RNGCONbits.LOAD == 1);
2497
            while (RNGCNT < 64);
2498
            RNGPOLY2 = RNGSEED2;
2499
            RNGPOLY1 = RNGSEED1;
2500
#endif
2501
2502
            RNGCONbits.PLEN = 0x40;
2503
            RNGCONbits.PRNGEN = 1;
2504
            for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */
2505
                volatile int x, y;
2506
                x = RNGNUMGEN1;
2507
                y = RNGNUMGEN2;
2508
                (void)x;
2509
                (void)y;
2510
            }
2511
            do {
2512
                rnd32[0] = RNGNUMGEN1;
2513
                rnd32[1] = RNGNUMGEN2;
2514
2515
                for(i=0; i<8; i++, op++) {
2516
                    *op = rnd[i];
2517
                    size --;
2518
                    if(size==0)break;
2519
                }
2520
            } while(size);
2521
            return 0;
2522
        }
2523
    #else  /* WOLFSSL_PIC32MZ_RNG */
2524
        /* uses the core timer, in nanoseconds to seed srand */
2525
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2526
        {
2527
            int i;
2528
            srand(PIC32_SEED_COUNT() * 25);
2529
2530
            for (i = 0; i < sz; i++ ) {
2531
                output[i] = rand() % 256;
2532
                if ( (i % 8) == 7)
2533
                    srand(PIC32_SEED_COUNT() * 25);
2534
            }
2535
            return 0;
2536
        }
2537
    #endif /* WOLFSSL_PIC32MZ_RNG */
2538
2539
#elif defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA)
2540
    /*
2541
     * wc_Generates a RNG seed using the Random Number Generator Accelerator
2542
     * on the Kinetis K70. Documentation located in Chapter 37 of
2543
     * K70 Sub-Family Reference Manual (see Note 3 in the README for link).
2544
     */
2545
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2546
    {
2547
        word32 i;
2548
2549
        /* turn on RNGA module */
2550
        #if defined(SIM_SCGC3_RNGA_MASK)
2551
            SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK;
2552
        #endif
2553
        #if defined(SIM_SCGC6_RNGA_MASK)
2554
            /* additionally needed for at least K64F */
2555
            SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK;
2556
        #endif
2557
2558
        /* set SLP bit to 0 - "RNGA is not in sleep mode" */
2559
        RNG_CR &= ~RNG_CR_SLP_MASK;
2560
2561
        /* set HA bit to 1 - "security violations masked" */
2562
        RNG_CR |= RNG_CR_HA_MASK;
2563
2564
        /* set GO bit to 1 - "output register loaded with data" */
2565
        RNG_CR |= RNG_CR_GO_MASK;
2566
2567
        for (i = 0; i < sz; i++) {
2568
2569
            /* wait for RNG FIFO to be full */
2570
            while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {}
2571
2572
            /* get value */
2573
            output[i] = RNG_OR;
2574
        }
2575
2576
        return 0;
2577
    }
2578
2579
#elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB)
2580
    /*
2581
     * wc_Generates a RNG seed using the Random Number Generator (RNGB)
2582
     * on the Kinetis K53. Documentation located in Chapter 33 of
2583
     * K53 Sub-Family Reference Manual (see note in the README for link).
2584
     */
2585
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2586
    {
2587
        int i;
2588
2589
        /* turn on RNGB module */
2590
        SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK;
2591
2592
        /* reset RNGB */
2593
        RNG_CMD |= RNG_CMD_SR_MASK;
2594
2595
        /* FIFO generate interrupt, return all zeros on underflow,
2596
         * set auto reseed */
2597
        RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK);
2598
2599
        /* gen seed, clear interrupts, clear errors */
2600
        RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK);
2601
2602
        /* wait for seeding to complete */
2603
        while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {}
2604
2605
        for (i = 0; i < sz; i++) {
2606
2607
            /* wait for a word to be available from FIFO */
2608
            while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {}
2609
2610
            /* get value */
2611
            output[i] = RNG_OUT;
2612
        }
2613
2614
        return 0;
2615
    }
2616
2617
#elif defined(FREESCALE_KSDK_2_0_TRNG)
2618
    #ifndef TRNG0
2619
    #define TRNG0 TRNG
2620
    #endif
2621
2622
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2623
    {
2624
        status_t status;
2625
        status = TRNG_GetRandomData(TRNG0, output, sz);
2626
        (void)os;
2627
        if (status == kStatus_Success)
2628
        {
2629
            return(0);
2630
        }
2631
        return RAN_BLOCK_E;
2632
    }
2633
2634
#elif defined(FREESCALE_KSDK_2_0_RNGA)
2635
2636
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2637
    {
2638
        status_t status;
2639
        status = RNGA_GetRandomData(RNG, output, sz);
2640
        (void)os;
2641
        if (status == kStatus_Success)
2642
        {
2643
            return(0);
2644
        }
2645
        return RAN_BLOCK_E;
2646
    }
2647
2648
2649
#elif defined(FREESCALE_RNGA)
2650
2651
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2652
    {
2653
        status_t status;
2654
        status = RNGA_GetRandomData(RNG, output, sz);
2655
        (void)os;
2656
        if (status == kStatus_Success)
2657
        {
2658
            return(0);
2659
        }
2660
        return RAN_BLOCK_E;
2661
    }
2662
#elif !defined(WOLFSSL_CAAM) && \
2663
    (defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \
2664
     defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS))
2665
    /*
2666
     * Fallback to USE_TEST_GENSEED if a FREESCALE platform did not match any
2667
     * of the TRNG/RNGA/RNGB support
2668
     */
2669
    #define USE_TEST_GENSEED
2670
2671
#elif defined(WOLFSSL_SILABS_SE_ACCEL)
2672
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2673
    {
2674
        (void)os;
2675
        return silabs_GenerateRand(output, sz);
2676
    }
2677
2678
#elif defined(STM32_RNG)
2679
     /* Generate a RNG seed using the hardware random number generator
2680
      * on the STM32F2/F4/F7/L4. */
2681
2682
    #ifdef WOLFSSL_STM32_CUBEMX
2683
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2684
    {
2685
        int ret;
2686
        RNG_HandleTypeDef hrng;
2687
        word32 i = 0;
2688
        (void)os;
2689
2690
        ret = wolfSSL_CryptHwMutexLock();
2691
        if (ret != 0) {
2692
            return ret;
2693
        }
2694
2695
        /* enable RNG clock source */
2696
        __HAL_RCC_RNG_CLK_ENABLE();
2697
2698
        /* enable RNG peripheral */
2699
        XMEMSET(&hrng, 0, sizeof(hrng));
2700
        hrng.Instance = RNG;
2701
        HAL_RNG_Init(&hrng);
2702
2703
        while (i < sz) {
2704
            /* If not aligned or there is odd/remainder */
2705
            if( (i + sizeof(word32)) > sz ||
2706
                ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
2707
            ) {
2708
                /* Single byte at a time */
2709
                uint32_t tmpRng = 0;
2710
                if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) {
2711
                    wolfSSL_CryptHwMutexUnLock();
2712
                    return RAN_BLOCK_E;
2713
                }
2714
                output[i++] = (byte)tmpRng;
2715
            }
2716
            else {
2717
                /* Use native 32 instruction */
2718
                if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) {
2719
                    wolfSSL_CryptHwMutexUnLock();
2720
                    return RAN_BLOCK_E;
2721
                }
2722
                i += sizeof(word32);
2723
            }
2724
        }
2725
2726
        HAL_RNG_DeInit(&hrng);
2727
2728
        wolfSSL_CryptHwMutexUnLock();
2729
2730
        return 0;
2731
    }
2732
    #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB) \
2733
        || defined(STM32_NUTTX_RNG)
2734
2735
    #ifdef STM32_NUTTX_RNG
2736
        #include "hardware/stm32_rng.h"
2737
        /* Set CONFIG_STM32U5_RNG in NuttX to enable the RCC */
2738
        #define WC_RNG_CR *((volatile uint32_t*)(STM32_RNG_CR))
2739
        #define WC_RNG_SR *((volatile uint32_t*)(STM32_RNG_SR))
2740
        #define WC_RNG_DR *((volatile uint32_t*)(STM32_RNG_DR))
2741
    #else
2742
        /* Comes from "stm32xxxx_hal.h" */
2743
        #define WC_RNG_CR RNG->CR
2744
        #define WC_RNG_SR RNG->SR
2745
        #define WC_RNG_DR RNG->DR
2746
    #endif
2747
2748
2749
    /* Generate a RNG seed using the hardware RNG on the STM32F427
2750
     * directly, following steps outlined in STM32F4 Reference
2751
     * Manual (Chapter 24) for STM32F4xx family. */
2752
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2753
    {
2754
        int ret;
2755
        word32 i;
2756
        (void)os;
2757
2758
        ret = wolfSSL_CryptHwMutexLock();
2759
        if (ret != 0) {
2760
            return ret;
2761
        }
2762
2763
    #ifndef STM32_NUTTX_RNG
2764
        /* enable RNG peripheral clock */
2765
        RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
2766
    #endif
2767
2768
        /* enable RNG interrupt, set IE bit in RNG->CR register */
2769
        WC_RNG_CR |= RNG_CR_IE;
2770
2771
        /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG,
2772
         * RNG_LFSR, and error detector */
2773
        WC_RNG_CR |= RNG_CR_RNGEN;
2774
2775
        /* verify no errors, make sure SEIS and CEIS bits are 0
2776
         * in RNG->SR register */
2777
        if (WC_RNG_SR & (RNG_SR_SECS | RNG_SR_CECS)) {
2778
            wolfSSL_CryptHwMutexUnLock();
2779
            return RNG_FAILURE_E;
2780
        }
2781
2782
        for (i = 0; i < sz; i++) {
2783
            /* wait until RNG number is ready */
2784
            while ((WC_RNG_SR & RNG_SR_DRDY) == 0) { }
2785
2786
            /* get value */
2787
            output[i] = WC_RNG_DR;
2788
        }
2789
2790
        wolfSSL_CryptHwMutexUnLock();
2791
2792
        return 0;
2793
    }
2794
2795
    #else
2796
2797
    /* Generate a RNG seed using the STM32 Standard Peripheral Library */
2798
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2799
    {
2800
        int ret;
2801
        word32 i;
2802
        (void)os;
2803
2804
        ret = wolfSSL_CryptHwMutexLock();
2805
        if (ret != 0) {
2806
            return ret;
2807
        }
2808
2809
        /* enable RNG clock source */
2810
        RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
2811
2812
        /* reset RNG */
2813
        RNG_DeInit();
2814
2815
        /* enable RNG peripheral */
2816
        RNG_Cmd(ENABLE);
2817
2818
        /* verify no errors with RNG_CLK or Seed */
2819
        if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) {
2820
            wolfSSL_CryptHwMutexUnLock();
2821
            return RNG_FAILURE_E;
2822
        }
2823
2824
        for (i = 0; i < sz; i++) {
2825
            /* wait until RNG number is ready */
2826
            while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { }
2827
2828
            /* get value */
2829
            output[i] = RNG_GetRandomNumber();
2830
        }
2831
2832
        wolfSSL_CryptHwMutexUnLock();
2833
2834
        return 0;
2835
    }
2836
    #endif /* WOLFSSL_STM32_CUBEMX */
2837
2838
#elif defined(WOLFSSL_TIRTOS)
2839
    #warning "potential for not enough entropy, currently being used for testing"
2840
    #include <xdc/runtime/Timestamp.h>
2841
    #include <stdlib.h>
2842
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2843
    {
2844
        int i;
2845
        srand(xdc_runtime_Timestamp_get32());
2846
2847
        for (i = 0; i < sz; i++ ) {
2848
            output[i] = rand() % 256;
2849
            if ((i % 8) == 7) {
2850
                srand(xdc_runtime_Timestamp_get32());
2851
            }
2852
        }
2853
2854
        return 0;
2855
    }
2856
2857
#elif defined(WOLFSSL_PB)
2858
2859
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2860
    {
2861
        word32 i;
2862
        for (i = 0; i < sz; i++)
2863
            output[i] = UTL_Rand();
2864
2865
        (void)os;
2866
2867
        return 0;
2868
    }
2869
2870
#elif defined(WOLFSSL_NUCLEUS)
2871
#include "nucleus.h"
2872
#include "kernel/plus_common.h"
2873
2874
#warning "potential for not enough entropy, currently being used for testing"
2875
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2876
{
2877
    int i;
2878
    srand(NU_Get_Time_Stamp());
2879
2880
    for (i = 0; i < sz; i++ ) {
2881
        output[i] = rand() % 256;
2882
        if ((i % 8) == 7) {
2883
            srand(NU_Get_Time_Stamp());
2884
        }
2885
    }
2886
2887
    return 0;
2888
}
2889
#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE)
2890
    #include "stdlib.h"
2891
2892
    #warning "potential for not enough entropy, currently being used for testing Deos"
2893
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2894
    {
2895
        int i;
2896
        int seed = XTIME(0);
2897
        (void)os;
2898
2899
        for (i = 0; i < sz; i++ ) {
2900
            output[i] = rand_r(&seed) % 256;
2901
            if ((i % 8) == 7) {
2902
                seed = XTIME(0);
2903
                rand_r(&seed);
2904
            }
2905
        }
2906
2907
        return 0;
2908
    }
2909
#elif defined(WOLFSSL_VXWORKS)
2910
    #ifdef WOLFSSL_VXWORKS_6_x
2911
        #include "stdlib.h"
2912
        #warning "potential for not enough entropy, currently being used for testing"
2913
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2914
        {
2915
            int i;
2916
            unsigned int seed = (unsigned int)XTIME(0);
2917
            (void)os;
2918
2919
            for (i = 0; i < sz; i++ ) {
2920
                output[i] = rand_r(&seed) % 256;
2921
                if ((i % 8) == 7) {
2922
                    seed = (unsigned int)XTIME(0);
2923
                    rand_r(&seed);
2924
                }
2925
            }
2926
2927
            return 0;
2928
        }
2929
    #else
2930
        #include <randomNumGen.h>
2931
        #include <tickLib.h>
2932
2933
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) {
2934
            STATUS                status   = ERROR;
2935
            RANDOM_NUM_GEN_STATUS r_status = RANDOM_NUM_GEN_ERROR;
2936
            _Vx_ticks_t           seed = 0;
2937
2938
            #ifdef VXWORKS_SIM
2939
                /* cannot generate true entropy with VxWorks simulator */
2940
                #warning "not enough entropy, simulator for testing only"
2941
                int i = 0;
2942
2943
                for (i = 0; i < 1000; i++) {
2944
                    randomAddTimeStamp();
2945
                }
2946
            #endif
2947
2948
            /*
2949
              wolfSSL can request 52 Bytes of random bytes. We need to add
2950
              buffer to the entropy pool to ensure we can get more than 32 Bytes.
2951
              Because VxWorks has entropy limits (ENTROPY_MIN and ENTROPY_MAX)
2952
              defined as 256 and 1024 bits, see randomSWNumGenLib.c.
2953
2954
              randStatus() can return the following status:
2955
              RANDOM_NUM_GEN_NO_ENTROPY when entropy is 0
2956
              RANDOM_NUM_GEN_ERROR, entropy is not initialized
2957
              RANDOM_NUM_GEN_NOT_ENOUGH_ENTROPY if entropy < 32 Bytes
2958
              RANDOM_NUM_GEN_ENOUGH_ENTROPY if entropy is between 32 and 128 Bytes
2959
              RANDOM_NUM_GEN_MAX_ENTROPY if entropy is greater than 128 Bytes
2960
            */
2961
2962
            do {
2963
                seed = tickGet();
2964
                status = randAdd(&seed, sizeof(_Vx_ticks_t), 2);
2965
                if (status == OK)
2966
                    r_status = randStatus();
2967
2968
            } while (r_status != RANDOM_NUM_GEN_MAX_ENTROPY &&
2969
                     r_status != RANDOM_NUM_GEN_ERROR && status == OK);
2970
2971
            if (r_status == RANDOM_NUM_GEN_ERROR)
2972
                return RNG_FAILURE_E;
2973
2974
            status = randBytes (output, sz);
2975
2976
            if (status == ERROR) {
2977
                return RNG_FAILURE_E;
2978
            }
2979
2980
            return 0;
2981
        }
2982
    #endif
2983
#elif defined(WOLFSSL_NRF51) || defined(WOLFSSL_NRF5x)
2984
    #include "app_error.h"
2985
    #include "nrf_drv_rng.h"
2986
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
2987
    {
2988
        int remaining = sz, pos = 0;
2989
        word32 err_code;
2990
        byte available;
2991
        static byte initialized = 0;
2992
2993
        (void)os;
2994
2995
        /* Make sure RNG is running */
2996
        if (!initialized) {
2997
            err_code = nrf_drv_rng_init(NULL);
2998
            if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE
2999
            #ifdef NRF_ERROR_MODULE_ALREADY_INITIALIZED
3000
                && err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED
3001
            #endif
3002
            ) {
3003
                return -1;
3004
            }
3005
            initialized = 1;
3006
        }
3007
3008
        while (remaining > 0) {
3009
            int length;
3010
            available = 0;
3011
            nrf_drv_rng_bytes_available(&available); /* void func */
3012
            length = (remaining < available) ? remaining : available;
3013
            if (length > 0) {
3014
                err_code = nrf_drv_rng_rand(&output[pos], length);
3015
                if (err_code != NRF_SUCCESS) {
3016
                    break;
3017
                }
3018
                remaining -= length;
3019
                pos += length;
3020
            }
3021
        }
3022
3023
        return (err_code == NRF_SUCCESS) ? 0 : -1;
3024
    }
3025
3026
#elif defined(HAVE_WNR)
3027
3028
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3029
    {
3030
        if (os == NULL || output == NULL || wnr_ctx == NULL ||
3031
                wnr_timeout < 0) {
3032
            return BAD_FUNC_ARG;
3033
        }
3034
3035
        if (wnr_mutex_init == 0) {
3036
            WOLFSSL_MSG("netRandom context must be created before use");
3037
            return RNG_FAILURE_E;
3038
        }
3039
3040
        if (wc_LockMutex(&wnr_mutex) != 0) {
3041
            WOLFSSL_MSG("Bad Lock Mutex wnr_mutex");
3042
            return BAD_MUTEX_E;
3043
        }
3044
3045
        if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) !=
3046
                WNR_ERROR_NONE)
3047
            return RNG_FAILURE_E;
3048
3049
        wc_UnLockMutex(&wnr_mutex);
3050
3051
        return 0;
3052
    }
3053
3054
#elif defined(INTIME_RTOS)
3055
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3056
    {
3057
        uint32_t randval;
3058
        word32 len;
3059
3060
        if (output == NULL) {
3061
            return BUFFER_E;
3062
        }
3063
3064
    #ifdef INTIMEVER
3065
        /* If INTIMEVER exists then it is INTIME RTOS v6 or later */
3066
        #define INTIME_RAND_FUNC arc4random
3067
        len = 4;
3068
    #else
3069
        /* v5 and older */
3070
        #define INTIME_RAND_FUNC rand
3071
        srand(time(0));
3072
        len = 2; /* don't use all 31 returned bits */
3073
    #endif
3074
3075
        while (sz > 0) {
3076
            if (sz < len)
3077
                len = sz;
3078
            randval = INTIME_RAND_FUNC();
3079
            XMEMCPY(output, &randval, len);
3080
            output += len;
3081
            sz -= len;
3082
        }
3083
        (void)os;
3084
3085
        return 0;
3086
    }
3087
3088
#elif defined(WOLFSSL_WICED)
3089
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3090
    {
3091
        int ret;
3092
        (void)os;
3093
3094
        if (output == NULL || UINT16_MAX < sz) {
3095
            return BUFFER_E;
3096
        }
3097
3098
        if ((ret = wiced_crypto_get_random((void*) output, sz) )
3099
                         != WICED_SUCCESS) {
3100
            return ret;
3101
        }
3102
3103
        return ret;
3104
    }
3105
3106
#elif defined(WOLFSSL_NETBURNER)
3107
    #warning using NetBurner pseudo random GetRandomByte for seed
3108
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3109
    {
3110
        word32 i;
3111
        (void)os;
3112
3113
        if (output == NULL) {
3114
            return BUFFER_E;
3115
        }
3116
3117
        for (i = 0; i < sz; i++) {
3118
            output[i] = GetRandomByte();
3119
3120
            /* check if was a valid random number */
3121
            if (!RandomValid())
3122
                return RNG_FAILURE_E;
3123
        }
3124
3125
        return 0;
3126
    }
3127
#elif defined(IDIRECT_DEV_RANDOM)
3128
3129
    extern int getRandom( int sz, unsigned char *output );
3130
3131
    int GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3132
    {
3133
        int num_bytes_returned = 0;
3134
3135
        num_bytes_returned = getRandom( (int) sz, (unsigned char *) output );
3136
3137
        return 0;
3138
    }
3139
3140
#elif defined(WOLFSSL_CAAM)
3141
3142
    #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
3143
3144
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3145
    {
3146
        unsigned int args[4] = {0};
3147
        CAAM_BUFFER buf[1];
3148
        int ret    = 0;
3149
        int times  = 1000, i; /* 1000 is an arbitrary number chosen */
3150
        word32 idx = 0;
3151
3152
        (void)os;
3153
3154
        if (output == NULL) {
3155
            return BUFFER_E;
3156
        }
3157
3158
        /* Check Waiting to make sure entropy is ready */
3159
        for (i = 0; i < times; i++) {
3160
            buf[0].BufferType = DataBuffer | LastBuffer;
3161
            buf[0].TheAddress = (CAAM_ADDRESS)(output + idx);
3162
            buf[0].Length     = ((sz - idx) < WC_CAAM_MAX_ENTROPY)?
3163
                                sz - idx : WC_CAAM_MAX_ENTROPY;
3164
3165
            args[0] = buf[0].Length;
3166
            ret = wc_caamAddAndWait(buf, 1, args, CAAM_ENTROPY);
3167
            if (ret == 0) {
3168
                idx += buf[0].Length;
3169
                if (idx == sz)
3170
                    break;
3171
            }
3172
3173
            /* driver could be waiting for entropy */
3174
            if (ret != WC_NO_ERR_TRACE(RAN_BLOCK_E) && ret != 0) {
3175
                return ret;
3176
            }
3177
#ifndef WOLFSSL_IMXRT1170_CAAM
3178
            usleep(100);
3179
#endif
3180
        }
3181
3182
        if (i == times && ret != 0) {
3183
             return RNG_FAILURE_E;
3184
        }
3185
        else { /* Success case */
3186
            ret = 0;
3187
        }
3188
3189
        return ret;
3190
    }
3191
3192
#elif defined(WOLFSSL_APACHE_MYNEWT)
3193
3194
    #include <stdlib.h>
3195
    #include "os/os_time.h"
3196
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3197
    {
3198
        int i;
3199
        srand(os_time_get());
3200
3201
        for (i = 0; i < sz; i++ ) {
3202
            output[i] = rand() % 256;
3203
            if ((i % 8) == 7) {
3204
                srand(os_time_get());
3205
            }
3206
        }
3207
3208
        return 0;
3209
    }
3210
3211
#elif defined(ARDUINO)
3212
3213
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3214
    {
3215
        int ret = 0;
3216
        word32 rand;
3217
        while (sz > 0) {
3218
            word32 len = sizeof(rand);
3219
            if (sz < len)
3220
                len = sz;
3221
        /* Get an Arduino framework random number */
3222
        #if defined(ARDUINO_SAMD_NANO_33_IOT) || \
3223
            defined(ARDUINO_ARCH_RP2040)
3224
            /* Known, tested boards working with random() */
3225
            rand = random();
3226
        #elif defined(ARDUINO_SAM_DUE)
3227
            /* See: https://github.com/avrxml/asf/tree/master/sam/utils/cmsis/sam3x/include */
3228
            #if defined(__SAM3A4C__)
3229
                #ifndef TRNG
3230
                    #define TRNG (0x400BC000U)
3231
                #endif
3232
            #elif defined(__SAM3A8C__)
3233
                #ifndef TRNG
3234
                    #define TRNG (0x400BC000U)
3235
                #endif
3236
            #elif defined(__SAM3X4C__)
3237
                #ifndef TRNG
3238
                    #define TRNG (0x400BC000U)
3239
                #endif
3240
            #elif defined(__SAM3X4E__)
3241
                #ifndef TRNG
3242
                    #define TRNG (0x400BC000U)
3243
                #endif
3244
            #elif defined(__SAM3X8C__)
3245
                #ifndef TRNG
3246
                    #define TRNG (0x400BC000U)
3247
                #endif
3248
            #elif defined(__SAM3X8E__)
3249
                /* This is the Arduino Due */
3250
                #ifndef TRNG
3251
                    #define TRNG (0x400BC000U)
3252
                #endif
3253
            #elif  defined(__SAM3A8H__)
3254
                #ifndef TRNG
3255
                    #define TRNG (0x400BC000U)
3256
                #endif
3257
            #else
3258
                #ifndef TRNG
3259
                    #error "Unknown TRNG for this device"
3260
                #endif
3261
            #endif
3262
3263
            srand(analogRead(0));
3264
            rand = trng_read_output_data(TRNG);
3265
        #elif defined(__STM32__)
3266
            /* TODO: confirm this is proper random number on Arduino STM32 */
3267
            #warning "Not yet tested on STM32 targets"
3268
            rand = random();
3269
        #else
3270
            /* TODO: Pull requests appreciated for new targets.
3271
             * Do *all* other Arduino boards support random()?
3272
             * Probably not 100%, but most will likely work: */
3273
            rand = random();
3274
        #endif
3275
3276
            XMEMCPY(output, &rand, len);
3277
            output += len;
3278
            sz -= len;
3279
        }
3280
3281
        return ret;
3282
    }
3283
3284
#elif defined(WOLFSSL_ESPIDF)
3285
3286
    /* Espressif */
3287
    #if defined(WOLFSSL_ESP32) || defined(WOLFSSL_ESPWROOM32SE)
3288
3289
        /* Espressif ESP32 */
3290
        #include <esp_system.h>
3291
        #if defined(CONFIG_IDF_TARGET_ESP32S2) || \
3292
            defined(CONFIG_IDF_TARGET_ESP32S3)
3293
            #include <esp_random.h>
3294
        #endif
3295
3296
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3297
        {
3298
            word32 rand;
3299
            while (sz > 0) {
3300
                word32 len = sizeof(rand);
3301
                if (sz < len)
3302
                    len = sz;
3303
                /* Get one random 32-bit word from hw RNG */
3304
                rand = esp_random( );
3305
                XMEMCPY(output, &rand, len);
3306
                output += len;
3307
                sz -= len;
3308
            }
3309
3310
            return 0;
3311
        }
3312
3313
    #elif defined(WOLFSSL_ESP8266)
3314
3315
        /* Espressif ESP8266 */
3316
        #include <esp_system.h>
3317
3318
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3319
        {
3320
    #if defined(DEBUG_WOLFSSL)
3321
            WOLFSSL_ENTER("ESP8266 Random");
3322
    #endif
3323
            word32 rand;
3324
            while (sz > 0) {
3325
                word32 len = sizeof(rand);
3326
                if (sz < len)
3327
                    len = sz;
3328
                /* Get one random 32-bit word from hw RNG */
3329
                rand = esp_random( );
3330
                XMEMCPY(output, &rand, len);
3331
                output += len;
3332
                sz -= len;
3333
            }
3334
3335
            return 0;
3336
        }
3337
    #endif /* end WOLFSSL_ESPIDF */
3338
3339
#elif defined(WOLFSSL_LINUXKM)
3340
3341
    #ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
3342
        #include <linux/random.h>
3343
    #endif
3344
3345
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3346
    {
3347
        (void)os;
3348
        int ret;
3349
3350
    #ifdef HAVE_ENTROPY_MEMUSE
3351
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
3352
        if (ret == 0)
3353
            return 0;
3354
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
3355
        return ret;
3356
        #endif
3357
    #endif
3358
3359
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
3360
        if (IS_INTEL_RDSEED(intel_flags)) {
3361
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
3362
            if (ret == 0)
3363
                return 0;
3364
            #ifdef FORCE_FAILURE_RDSEED
3365
            return ret;
3366
            #endif
3367
        }
3368
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3369
3370
    #ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT
3371
        #if !defined(HAVE_ENTROPY_MEMUSE) && \
3372
            !defined(HAVE_INTEL_RDSEED) && \
3373
            !defined(HAVE_AMD_RDSEED)
3374
            #error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires an intrinsic entropy source.
3375
        #else
3376
            return ret;
3377
        #endif
3378
    #else
3379
        (void)ret;
3380
3381
        get_random_bytes(output, sz);
3382
        return 0;
3383
    #endif
3384
    }
3385
3386
#elif defined(WOLFSSL_BSDKM)
3387
    #include <sys/random.h>
3388
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3389
    {
3390
        (void)os;
3391
        int ret;
3392
3393
    #ifdef HAVE_ENTROPY_MEMUSE
3394
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
3395
        if (ret == 0) {
3396
            return 0;
3397
        }
3398
        #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
3399
        /* Don't fallback to /dev/urandom. */
3400
        return ret;
3401
        #endif
3402
    #endif
3403
3404
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
3405
        if (IS_INTEL_RDSEED(intel_flags)) {
3406
            ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
3407
        #ifndef FORCE_FAILURE_RDSEED
3408
            if (ret == 0)
3409
        #endif
3410
            {
3411
                return ret;
3412
            }
3413
        }
3414
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3415
3416
        (void)ret;
3417
3418
        arc4random_buf(output, sz);
3419
        return 0;
3420
    }
3421
#elif defined(WOLFSSL_RENESAS_TSIP)
3422
3423
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3424
    {
3425
        (void)os;
3426
        return wc_tsip_GenerateRandBlock(output, sz);
3427
    }
3428
3429
3430
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG)
3431
    #include "hal_data.h"
3432
3433
    #ifndef WOLFSSL_SCE_TRNG_HANDLE
3434
        #define WOLFSSL_SCE_TRNG_HANDLE g_sce_trng
3435
    #endif
3436
3437
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3438
    {
3439
        word32 ret;
3440
        word32 blocks;
3441
        word32 len = sz;
3442
3443
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->open(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
3444
                                                  WOLFSSL_SCE_TRNG_HANDLE.p_cfg);
3445
        if (ret != SSP_SUCCESS && ret != SSP_ERR_CRYPTO_ALREADY_OPEN) {
3446
            /* error opening TRNG driver */
3447
            return -1;
3448
        }
3449
3450
        blocks = sz / sizeof(word32);
3451
        if (blocks > 0) {
3452
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
3453
                                                       (word32*)output, blocks);
3454
            if (ret != SSP_SUCCESS) {
3455
                return -1;
3456
            }
3457
        }
3458
3459
        len = len - (blocks * sizeof(word32));
3460
        if (len > 0) {
3461
            word32 tmp;
3462
3463
            if (len > sizeof(word32)) {
3464
                return -1;
3465
            }
3466
            ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->read(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl,
3467
                                                      (word32*)&tmp, 1);
3468
            if (ret != SSP_SUCCESS) {
3469
                return -1;
3470
            }
3471
            XMEMCPY(output + (blocks * sizeof(word32)), (byte*)&tmp, len);
3472
        }
3473
3474
        ret = WOLFSSL_SCE_TRNG_HANDLE.p_api->close(WOLFSSL_SCE_TRNG_HANDLE.p_ctrl);
3475
        if (ret != SSP_SUCCESS) {
3476
            /* error opening TRNG driver */
3477
            return -1;
3478
        }
3479
        return 0;
3480
    }
3481
#elif defined(CUSTOM_RAND_GENERATE_BLOCK)
3482
    /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc
3483
     * extern int myRngFunc(byte* output, word32 sz);
3484
     */
3485
3486
#elif defined(__MICROBLAZE__)
3487
    #warning weak source of entropy
3488
    #define LPD_SCNTR_BASE_ADDRESS 0xFF250000
3489
3490
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3491
    {
3492
        word32* cnt;
3493
        word32 i;
3494
3495
        /* using current time with srand */
3496
        cnt = (word32*)LPD_SCNTR_BASE_ADDRESS;
3497
        srand(*cnt | *(cnt+1));
3498
3499
        for (i = 0; i < sz; i++)
3500
            output[i] = rand();
3501
3502
        (void)os;
3503
        return 0;
3504
    }
3505
3506
#elif defined(WOLFSSL_ZEPHYR)
3507
3508
    #ifdef __has_include
3509
        #if __has_include(<zephyr/version.h>)
3510
            #include <zephyr/version.h>
3511
        #else
3512
            #include <version.h>
3513
        #endif
3514
    #else
3515
        #include <version.h>
3516
    #endif
3517
3518
    #include <sys/types.h>
3519
3520
    #if KERNEL_VERSION_NUMBER >= 0x30500
3521
        #include <zephyr/random/random.h>
3522
    #else
3523
        #if KERNEL_VERSION_NUMBER >= 0x30100
3524
            #include <zephyr/random/rand32.h>
3525
        #else
3526
            #include <random/rand32.h>
3527
        #endif
3528
    #endif
3529
3530
    #if KERNEL_VERSION_NUMBER >= 0x40300
3531
        #include <time.h>
3532
    #elif KERNEL_VERSION_NUMBER >= 0x30100
3533
        #include <zephyr/posix/time.h>
3534
    #else
3535
        #include <posix/time.h>
3536
    #endif
3537
3538
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3539
    {
3540
        sys_rand_get(output, sz);
3541
        return 0;
3542
    }
3543
3544
#elif defined(WOLFSSL_TELIT_M2MB)
3545
3546
        #include "stdlib.h"
3547
        static long get_timestamp(void) {
3548
            long myTime = 0;
3549
            INT32 fd = m2mb_rtc_open("/dev/rtc0", 0);
3550
            if (fd >= 0) {
3551
                M2MB_RTC_TIMEVAL_T timeval;
3552
                m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval);
3553
                myTime = timeval.msec;
3554
                m2mb_rtc_close(fd);
3555
            }
3556
            return myTime;
3557
        }
3558
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3559
        {
3560
            int i;
3561
            srand(get_timestamp());
3562
            for (i = 0; i < sz; i++ ) {
3563
                output[i] = rand() % 256;
3564
                if ((i % 8) == 7) {
3565
                    srand(get_timestamp());
3566
                }
3567
            }
3568
            return 0;
3569
        }
3570
#elif defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_NO_TRNG)
3571
     #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
3572
3573
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz){
3574
        int ret = 0;
3575
3576
        (void)os;
3577
3578
        if (output == NULL) {
3579
            return BUFFER_E;
3580
        }
3581
        ret = wolfSSL_CryptHwMutexLock();
3582
        if (ret == 0) {
3583
            ret = se050_get_random_number(sz, output);
3584
            wolfSSL_CryptHwMutexUnLock();
3585
        }
3586
        return ret;
3587
    }
3588
3589
#elif defined(DOLPHIN_EMULATOR) || defined (WOLFSSL_NDS)
3590
3591
        int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3592
        {
3593
            word32 i;
3594
            (void)os;
3595
            srand(time(NULL));
3596
            for (i = 0; i < sz; i++)
3597
                output[i] = (byte)rand();
3598
            return 0;
3599
        }
3600
#elif defined(WOLFSSL_MAXQ108X) || defined(WOLFSSL_MAXQ1065)
3601
3602
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3603
    {
3604
        (void)os;
3605
3606
        return maxq10xx_random(output, sz);
3607
    }
3608
#elif defined(MAX3266X_RNG)
3609
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3610
    {
3611
        #ifdef WOLFSSL_MAX3266X
3612
        int status;
3613
        #endif /* WOLFSSL_MAX3266X */
3614
        static int initDone = 0;
3615
        (void)os;
3616
        if (initDone == 0) {
3617
            #ifdef WOLFSSL_MAX3266X
3618
            status = wolfSSL_HwRngMutexLock();
3619
            if (status != 0) {
3620
                return status;
3621
            }
3622
            #endif /* WOLFSSL_MAX3266X */
3623
            if(MXC_TRNG_HealthTest() != 0) {
3624
                #ifdef DEBUG_WOLFSSL
3625
                WOLFSSL_MSG("TRNG HW Health Test Failed");
3626
                #endif /* DEBUG_WOLFSSL */
3627
                #ifdef WOLFSSL_MAX3266X
3628
                wolfSSL_HwRngMutexUnLock();
3629
                #endif /* WOLFSSL_MAX3266X */
3630
                return WC_HW_E;
3631
            }
3632
            #ifdef WOLFSSL_MAX3266X
3633
            wolfSSL_HwRngMutexUnLock();
3634
            #endif /* WOLFSSL_MAX3266X */
3635
            initDone = 1;
3636
        }
3637
        return wc_MXC_TRNG_Random(output, sz);
3638
    }
3639
3640
#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL)
3641
3642
    /* Infineon/Cypress HAL RNG implementation */
3643
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3644
    {
3645
        cyhal_trng_t obj;
3646
        cy_rslt_t result;
3647
        uint32_t val;
3648
        word32 i = 0;
3649
3650
        (void)os;
3651
3652
        result = cyhal_trng_init(&obj);
3653
        if (result == CY_RSLT_SUCCESS) {
3654
            while (i < sz) {
3655
                /* If not aligned or there is odd/remainder add single byte */
3656
                if( (i + sizeof(word32)) > sz ||
3657
                    ((wc_ptr_t)&output[i] % sizeof(word32)) != 0
3658
                ) {
3659
                    val = cyhal_trng_generate(&obj);
3660
                    output[i++] = (byte)val;
3661
                }
3662
                else {
3663
                    /* Use native 32 instruction */
3664
                    val = cyhal_trng_generate(&obj);
3665
                    *((uint32_t*)&output[i]) = val;
3666
                    i += sizeof(word32);
3667
                }
3668
            }
3669
            cyhal_trng_free(&obj);
3670
        }
3671
        return 0;
3672
    }
3673
3674
#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \
3675
      defined(WOLFSSL_IAR_ARM)  || defined(WOLFSSL_MDK_ARM) || \
3676
      defined(WOLFSSL_uITRON4)  || defined(WOLFSSL_uTKERNEL2) || \
3677
      defined(WOLFSSL_LPC43xx)  || defined(NO_STM32_RNG) || \
3678
      defined(MBED)             || defined(WOLFSSL_EMBOS) || \
3679
      defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \
3680
      defined(WOLFSSL_CONTIKI)  || defined(WOLFSSL_AZSPHERE)
3681
3682
    /* these platforms do not have a default random seed and
3683
       you'll need to implement your own wc_GenerateSeed or define via
3684
       CUSTOM_RAND_GENERATE_BLOCK */
3685
3686
    #define USE_TEST_GENSEED
3687
3688
#elif defined(NO_DEV_RANDOM)
3689
3690
    /* Allow bare-metal targets to use cryptoCb as seed provider */
3691
    #if defined(WOLF_CRYPTO_CB)
3692
3693
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3694
    {
3695
        int ret = WC_NO_ERR_TRACE(WC_HW_E);
3696
3697
        #ifndef WOLF_CRYPTO_CB_FIND
3698
        if (os->devId != INVALID_DEVID)
3699
        #endif
3700
        {
3701
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
3702
            if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
3703
                ret = WC_HW_E;
3704
            }
3705
        }
3706
3707
        return ret;
3708
    }
3709
3710
    #else /* defined(WOLF_CRYPTO_CB)*/
3711
3712
    #error "you need to write an os specific wc_GenerateSeed() here"
3713
3714
    /*
3715
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3716
    {
3717
        return 0;
3718
    }
3719
    */
3720
3721
   #endif  /* !defined(WOLF_CRYPTO_CB) */
3722
3723
#else
3724
3725
    /* may block */
3726
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3727
106k
    {
3728
106k
        int ret = 0;
3729
3730
106k
        if (os == NULL) {
3731
0
            return BAD_FUNC_ARG;
3732
0
        }
3733
3734
106k
    #ifdef WOLF_CRYPTO_CB
3735
106k
        #ifndef WOLF_CRYPTO_CB_FIND
3736
106k
        if (os->devId != INVALID_DEVID)
3737
12
        #endif
3738
12
        {
3739
12
            ret = wc_CryptoCb_RandomSeed(os, output, sz);
3740
12
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
3741
12
                return ret;
3742
            /* fall-through when unavailable */
3743
0
            ret = 0; /* reset error code */
3744
0
        }
3745
106k
    #endif
3746
3747
    #ifdef HAVE_ENTROPY_MEMUSE
3748
        ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz);
3749
        if (ret == 0) {
3750
            /* success, we're done */
3751
            return ret;
3752
        }
3753
    #ifdef ENTROPY_MEMUSE_FORCE_FAILURE
3754
        /* Don't fall back to /dev/urandom. */
3755
        return ret;
3756
    #else
3757
        /* Reset error and fall back to using /dev/urandom. */
3758
        ret = 0;
3759
    #endif
3760
    #endif
3761
3762
106k
    #if !defined(HAVE_ENTROPY_MEMUSE) || !defined(ENTROPY_MEMUSE_FORCE_FAILURE)
3763
3764
    #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)
3765
        if (IS_INTEL_RDSEED(intel_flags)) {
3766
             ret = wc_GenerateSeed_IntelRD(NULL, output, sz);
3767
             if (ret == 0) {
3768
                 /* success, we're done */
3769
                 return ret;
3770
             }
3771
        #ifdef FORCE_FAILURE_RDSEED
3772
             /* Don't fall back to /dev/urandom. */
3773
             return ret;
3774
        #else
3775
             /* Reset error and fall back to using /dev/urandom. */
3776
             ret = 0;
3777
        #endif
3778
        }
3779
    #ifdef FORCE_FAILURE_RDSEED
3780
        else {
3781
            /* Don't fall back to /dev/urandom */
3782
            return MISSING_RNG_E;
3783
        }
3784
    #endif
3785
    #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */
3786
3787
106k
    #if (!defined(HAVE_INTEL_RDSEED) && !defined(HAVE_AMD_RDSEED)) || \
3788
106k
        !defined(FORCE_FAILURE_RDSEED)
3789
3790
106k
    #if defined(WOLFSSL_GETRANDOM) || defined(HAVE_GETRANDOM)
3791
106k
        {
3792
106k
            word32 grSz = sz;
3793
106k
            byte* grOutput = output;
3794
3795
212k
            while (grSz) {
3796
106k
                ssize_t len;
3797
3798
106k
                errno = 0;
3799
106k
                len = getrandom(grOutput, grSz, 0);
3800
106k
                if (len == -1) {
3801
0
                    if (errno == EINTR) {
3802
                        /* interrupted, call getrandom again */
3803
0
                        continue;
3804
0
                    }
3805
0
                    else {
3806
0
                        ret = READ_RAN_E;
3807
0
                    }
3808
0
                    break;
3809
0
                }
3810
3811
106k
                grSz     -= (word32)len;
3812
106k
                grOutput += len;
3813
106k
            }
3814
106k
            if (ret == 0)
3815
106k
                return ret;
3816
        #ifdef FORCE_FAILURE_GETRANDOM
3817
            /* don't fall back to /dev/urandom */
3818
            return ret;
3819
        #elif !defined(NO_FILESYSTEM)
3820
            /* reset error and fall back to using /dev/urandom if filesystem
3821
             * support is compiled in */
3822
0
            ret = 0;
3823
0
        #endif
3824
0
        }
3825
0
    #endif
3826
3827
0
#ifndef NO_FILESYSTEM
3828
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
3829
        if (!os->seedFdOpen)
3830
        {
3831
        #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
3832
            os->fd = open("/dev/urandom", O_RDONLY);
3833
            #if defined(DEBUG_WOLFSSL)
3834
                WOLFSSL_MSG("opened /dev/urandom.");
3835
            #endif /* DEBUG_WOLFSSL */
3836
            if (os->fd == XBADFD)
3837
        #endif /* NO_DEV_URANDOM */
3838
            {
3839
                /* may still have /dev/random */
3840
                os->fd = open("/dev/random", O_RDONLY);
3841
            #if defined(DEBUG_WOLFSSL)
3842
                WOLFSSL_MSG("opened /dev/random.");
3843
            #endif /* DEBUG_WOLFSSL */
3844
                if (os->fd == XBADFD)
3845
                    return OPEN_RAN_E;
3846
                else {
3847
                    os->keepSeedFdOpen = 0;
3848
                    os->seedFdOpen = 1;
3849
                }
3850
            }
3851
            else {
3852
                os->keepSeedFdOpen = 1;
3853
                os->seedFdOpen = 1;
3854
            }
3855
        }
3856
    #else /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
3857
0
        #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */
3858
0
        os->fd = open("/dev/urandom", O_RDONLY);
3859
        #if defined(DEBUG_WOLFSSL)
3860
            WOLFSSL_MSG("opened /dev/urandom.");
3861
        #endif /* DEBUG_WOLFSSL */
3862
0
        if (os->fd == XBADFD)
3863
0
        #endif /* !NO_DEV_URANDOM */
3864
0
        {
3865
            /* may still have /dev/random */
3866
0
            os->fd = open("/dev/random", O_RDONLY);
3867
        #if defined(DEBUG_WOLFSSL)
3868
            WOLFSSL_MSG("opened /dev/random.");
3869
        #endif /* DEBUG_WOLFSSL */
3870
0
            if (os->fd == XBADFD)
3871
0
                return OPEN_RAN_E;
3872
0
        }
3873
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
3874
    #if defined(DEBUG_WOLFSSL)
3875
        WOLFSSL_MSG("rnd read...");
3876
    #endif /* DEBUG_WOLFSSL */
3877
0
        while (sz) {
3878
0
            int len = (int)read(os->fd, output, sz);
3879
0
            if (len == -1) {
3880
0
                ret = READ_RAN_E;
3881
0
                break;
3882
0
            }
3883
3884
0
            sz     -= (word32)len;
3885
0
            output += len;
3886
3887
0
            if (sz) {
3888
    #if defined(BLOCKING) || defined(WC_RNG_BLOCKING)
3889
                sleep(0);             /* context switch */
3890
    #else
3891
0
                ret = RAN_BLOCK_E;
3892
0
                break;
3893
0
    #endif /* BLOCKING || WC_RNG_BLOCKING */
3894
0
            }
3895
0
        }
3896
    #ifdef WOLFSSL_KEEP_RNG_SEED_FD_OPEN
3897
        if (!os->keepSeedFdOpen && os->seedFdOpen)
3898
        {
3899
            close(os->fd);
3900
            os->fd = -1;
3901
            os->seedFdOpen = 0;
3902
        }
3903
    #else
3904
0
        close(os->fd);
3905
0
    #endif /* WOLFSSL_KEEP_RNG_SEED_FD_OPEN */
3906
#else /* NO_FILESYSTEM */
3907
        (void)output;
3908
        (void)sz;
3909
        ret = NOT_COMPILED_IN;
3910
#endif /* NO_FILESYSTEM */
3911
3912
0
        return ret;
3913
3914
0
    #endif /* (!HAVE_INTEL_RDSEED && !HAVE_AMD_RDSEED) || !FORCE_FAILURE_RDSEED */
3915
3916
0
    #endif /*!HAVE_ENTROPY_MEMUSE || !ENTROPY_MEMUSE_FORCE_FAILURE */
3917
3918
0
    }
3919
3920
#endif
3921
3922
#ifdef USE_TEST_GENSEED
3923
    #ifndef _MSC_VER
3924
        #warning "write a real random seed!!!!, just for testing now"
3925
    #else
3926
        #pragma message("Warning: write a real random seed!!!!, just for testing now")
3927
    #endif
3928
    int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
3929
    {
3930
        word32 i;
3931
        for (i = 0; i < sz; i++ )
3932
            output[i] = (byte)i;
3933
3934
        (void)os;
3935
3936
        return 0;
3937
    }
3938
#endif
3939
/* End wc_GenerateSeed */
3940
3941
#if defined(CUSTOM_RAND_GENERATE_BLOCK) && defined(WOLFSSL_KCAPI)
3942
#include <fcntl.h>
3943
int wc_hwrng_generate_block(byte *output, word32 sz)
3944
{
3945
    int fd;
3946
    int ret = 0;
3947
    fd = open("/dev/hwrng", O_RDONLY);
3948
    if (fd == -1)
3949
        return OPEN_RAN_E;
3950
    while(sz)
3951
    {
3952
        int len = (int)read(fd, output, sz);
3953
        if (len == -1)
3954
        {
3955
            ret = READ_RAN_E;
3956
            break;
3957
        }
3958
        sz -= len;
3959
        output += len;
3960
    }
3961
    close(fd);
3962
    return ret;
3963
}
3964
#endif
3965
3966
#endif /* WC_NO_RNG */