1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery *
4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery */
9*b077aed3SPierre Pronchery
10*b077aed3SPierre Pronchery #include <openssl/opensslconf.h>
11*b077aed3SPierre Pronchery
12*b077aed3SPierre Pronchery #include <openssl/rand.h>
13*b077aed3SPierre Pronchery #include "crypto/rand_pool.h"
14*b077aed3SPierre Pronchery #include "crypto/rand.h"
15*b077aed3SPierre Pronchery #include "internal/cryptlib.h"
16*b077aed3SPierre Pronchery #include "prov/seeding.h"
17*b077aed3SPierre Pronchery #include <version.h>
18*b077aed3SPierre Pronchery #include <taskLib.h>
19*b077aed3SPierre Pronchery
20*b077aed3SPierre Pronchery #if defined(OPENSSL_RAND_SEED_NONE)
21*b077aed3SPierre Pronchery /* none means none */
22*b077aed3SPierre Pronchery # undef OPENSSL_RAND_SEED_OS
23*b077aed3SPierre Pronchery #endif
24*b077aed3SPierre Pronchery
25*b077aed3SPierre Pronchery #if defined(OPENSSL_RAND_SEED_OS)
26*b077aed3SPierre Pronchery # if _WRS_VXWORKS_MAJOR >= 7
27*b077aed3SPierre Pronchery # define RAND_SEED_VXRANDLIB
28*b077aed3SPierre Pronchery # else
29*b077aed3SPierre Pronchery # error "VxWorks <7 only support RAND_SEED_NONE"
30*b077aed3SPierre Pronchery # endif
31*b077aed3SPierre Pronchery #endif
32*b077aed3SPierre Pronchery
33*b077aed3SPierre Pronchery #if defined(RAND_SEED_VXRANDLIB)
34*b077aed3SPierre Pronchery # include <randomNumGen.h>
35*b077aed3SPierre Pronchery #endif
36*b077aed3SPierre Pronchery
37*b077aed3SPierre Pronchery /* Macro to convert two thirty two bit values into a sixty four bit one */
38*b077aed3SPierre Pronchery #define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
39*b077aed3SPierre Pronchery
get_time_stamp(void)40*b077aed3SPierre Pronchery static uint64_t get_time_stamp(void)
41*b077aed3SPierre Pronchery {
42*b077aed3SPierre Pronchery struct timespec ts;
43*b077aed3SPierre Pronchery
44*b077aed3SPierre Pronchery if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
45*b077aed3SPierre Pronchery return TWO32TO64(ts.tv_sec, ts.tv_nsec);
46*b077aed3SPierre Pronchery return time(NULL);
47*b077aed3SPierre Pronchery }
48*b077aed3SPierre Pronchery
get_timer_bits(void)49*b077aed3SPierre Pronchery static uint64_t get_timer_bits(void)
50*b077aed3SPierre Pronchery {
51*b077aed3SPierre Pronchery uint64_t res = OPENSSL_rdtsc();
52*b077aed3SPierre Pronchery struct timespec ts;
53*b077aed3SPierre Pronchery
54*b077aed3SPierre Pronchery if (res != 0)
55*b077aed3SPierre Pronchery return res;
56*b077aed3SPierre Pronchery
57*b077aed3SPierre Pronchery if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
58*b077aed3SPierre Pronchery return TWO32TO64(ts.tv_sec, ts.tv_nsec);
59*b077aed3SPierre Pronchery return time(NULL);
60*b077aed3SPierre Pronchery }
61*b077aed3SPierre Pronchery
62*b077aed3SPierre Pronchery /*
63*b077aed3SPierre Pronchery * empty implementation
64*b077aed3SPierre Pronchery * vxworks does not need to init/cleanup or keep open the random lib
65*b077aed3SPierre Pronchery */
ossl_rand_pool_init(void)66*b077aed3SPierre Pronchery int ossl_rand_pool_init(void)
67*b077aed3SPierre Pronchery {
68*b077aed3SPierre Pronchery return 1;
69*b077aed3SPierre Pronchery }
70*b077aed3SPierre Pronchery
ossl_rand_pool_cleanup(void)71*b077aed3SPierre Pronchery void ossl_rand_pool_cleanup(void)
72*b077aed3SPierre Pronchery {
73*b077aed3SPierre Pronchery }
74*b077aed3SPierre Pronchery
ossl_rand_pool_keep_random_devices_open(int keep)75*b077aed3SPierre Pronchery void ossl_rand_pool_keep_random_devices_open(int keep)
76*b077aed3SPierre Pronchery {
77*b077aed3SPierre Pronchery }
78*b077aed3SPierre Pronchery
ossl_rand_pool_add_additional_data(RAND_POOL * pool)79*b077aed3SPierre Pronchery int ossl_rand_pool_add_additional_data(RAND_POOL *pool)
80*b077aed3SPierre Pronchery {
81*b077aed3SPierre Pronchery struct {
82*b077aed3SPierre Pronchery CRYPTO_THREAD_ID tid;
83*b077aed3SPierre Pronchery uint64_t time;
84*b077aed3SPierre Pronchery } data;
85*b077aed3SPierre Pronchery
86*b077aed3SPierre Pronchery memset(&data, 0, sizeof(data));
87*b077aed3SPierre Pronchery
88*b077aed3SPierre Pronchery /*
89*b077aed3SPierre Pronchery * Add some noise from the thread id and a high resolution timer.
90*b077aed3SPierre Pronchery * The thread id adds a little randomness if the drbg is accessed
91*b077aed3SPierre Pronchery * concurrently (which is the case for the <master> drbg).
92*b077aed3SPierre Pronchery */
93*b077aed3SPierre Pronchery data.tid = CRYPTO_THREAD_get_current_id();
94*b077aed3SPierre Pronchery data.time = get_timer_bits();
95*b077aed3SPierre Pronchery
96*b077aed3SPierre Pronchery return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
97*b077aed3SPierre Pronchery }
98*b077aed3SPierre Pronchery
ossl_pool_add_nonce_data(RAND_POOL * pool)99*b077aed3SPierre Pronchery int ossl_pool_add_nonce_data(RAND_POOL *pool)
100*b077aed3SPierre Pronchery {
101*b077aed3SPierre Pronchery struct {
102*b077aed3SPierre Pronchery pid_t pid;
103*b077aed3SPierre Pronchery CRYPTO_THREAD_ID tid;
104*b077aed3SPierre Pronchery uint64_t time;
105*b077aed3SPierre Pronchery } data;
106*b077aed3SPierre Pronchery
107*b077aed3SPierre Pronchery memset(&data, 0, sizeof(data));
108*b077aed3SPierre Pronchery
109*b077aed3SPierre Pronchery /*
110*b077aed3SPierre Pronchery * Add process id, thread id, and a high resolution timestamp to
111*b077aed3SPierre Pronchery * ensure that the nonce is unique with high probability for
112*b077aed3SPierre Pronchery * different process instances.
113*b077aed3SPierre Pronchery */
114*b077aed3SPierre Pronchery data.pid = getpid();
115*b077aed3SPierre Pronchery data.tid = CRYPTO_THREAD_get_current_id();
116*b077aed3SPierre Pronchery data.time = get_time_stamp();
117*b077aed3SPierre Pronchery
118*b077aed3SPierre Pronchery return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
119*b077aed3SPierre Pronchery }
120*b077aed3SPierre Pronchery
ossl_pool_acquire_entropy(RAND_POOL * pool)121*b077aed3SPierre Pronchery size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
122*b077aed3SPierre Pronchery {
123*b077aed3SPierre Pronchery #if defined(RAND_SEED_VXRANDLIB)
124*b077aed3SPierre Pronchery /* vxRandLib based entropy method */
125*b077aed3SPierre Pronchery size_t bytes_needed;
126*b077aed3SPierre Pronchery
127*b077aed3SPierre Pronchery bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
128*b077aed3SPierre Pronchery if (bytes_needed > 0)
129*b077aed3SPierre Pronchery {
130*b077aed3SPierre Pronchery int retryCount = 0;
131*b077aed3SPierre Pronchery STATUS result = ERROR;
132*b077aed3SPierre Pronchery unsigned char *buffer;
133*b077aed3SPierre Pronchery
134*b077aed3SPierre Pronchery buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
135*b077aed3SPierre Pronchery while ((result != OK) && (retryCount < 10)) {
136*b077aed3SPierre Pronchery RANDOM_NUM_GEN_STATUS status = randStatus();
137*b077aed3SPierre Pronchery
138*b077aed3SPierre Pronchery if ((status == RANDOM_NUM_GEN_ENOUGH_ENTROPY)
139*b077aed3SPierre Pronchery || (status == RANDOM_NUM_GEN_MAX_ENTROPY) ) {
140*b077aed3SPierre Pronchery result = randBytes(buffer, bytes_needed);
141*b077aed3SPierre Pronchery if (result == OK)
142*b077aed3SPierre Pronchery ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
143*b077aed3SPierre Pronchery /*
144*b077aed3SPierre Pronchery * no else here: randStatus said ok, if randBytes failed
145*b077aed3SPierre Pronchery * it will result in another loop or no entropy
146*b077aed3SPierre Pronchery */
147*b077aed3SPierre Pronchery } else {
148*b077aed3SPierre Pronchery /*
149*b077aed3SPierre Pronchery * give a minimum delay here to allow OS to collect more
150*b077aed3SPierre Pronchery * entropy. taskDelay duration will depend on the system tick,
151*b077aed3SPierre Pronchery * this is by design as the sw-random lib uses interrupts
152*b077aed3SPierre Pronchery * which will at least happen during ticks
153*b077aed3SPierre Pronchery */
154*b077aed3SPierre Pronchery taskDelay(5);
155*b077aed3SPierre Pronchery }
156*b077aed3SPierre Pronchery retryCount++;
157*b077aed3SPierre Pronchery }
158*b077aed3SPierre Pronchery }
159*b077aed3SPierre Pronchery return ossl_rand_pool_entropy_available(pool);
160*b077aed3SPierre Pronchery #else
161*b077aed3SPierre Pronchery /*
162*b077aed3SPierre Pronchery * SEED_NONE means none, without randlib we dont have entropy and
163*b077aed3SPierre Pronchery * rely on it being added externally
164*b077aed3SPierre Pronchery */
165*b077aed3SPierre Pronchery return ossl_rand_pool_entropy_available(pool);
166*b077aed3SPierre Pronchery #endif /* defined(RAND_SEED_VXRANDLIB) */
167*b077aed3SPierre Pronchery }
168