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