xref: /freebsd-src/crypto/openssl/providers/implementations/rands/seeding/rand_vxworks.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
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