Coverage Report

Created: 2026-02-14 07:18

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