| /* |
| * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. |
| * |
| * Licensed under the Apache License 2.0 (the "License"). You may not use |
| * this file except in compliance with the License. You can obtain a copy |
| * in the file LICENSE in the source distribution or at |
| * https://www.openssl.org/source/license.html |
| */ |
| |
| #include <openssl/opensslconf.h> |
| |
| #include <openssl/rand.h> |
| #include "crypto/rand_pool.h" |
| #include "crypto/rand.h" |
| #include "internal/cryptlib.h" |
| #include "prov/seeding.h" |
| #include <version.h> |
| #include <taskLib.h> |
| |
| #if defined(OPENSSL_RAND_SEED_NONE) |
| /* none means none */ |
| # undef OPENSSL_RAND_SEED_OS |
| #endif |
| |
| #if defined(OPENSSL_RAND_SEED_OS) |
| # if _WRS_VXWORKS_MAJOR >= 7 |
| # define RAND_SEED_VXRANDLIB |
| # else |
| # error "VxWorks <7 only support RAND_SEED_NONE" |
| # endif |
| #endif |
| |
| #if defined(RAND_SEED_VXRANDLIB) |
| # include <randomNumGen.h> |
| #endif |
| |
| /* Macro to convert two thirty two bit values into a sixty four bit one */ |
| #define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b)) |
| |
| static uint64_t get_time_stamp(void) |
| { |
| struct timespec ts; |
| |
| if (clock_gettime(CLOCK_REALTIME, &ts) == 0) |
| return TWO32TO64(ts.tv_sec, ts.tv_nsec); |
| return time(NULL); |
| } |
| |
| static uint64_t get_timer_bits(void) |
| { |
| uint64_t res = OPENSSL_rdtsc(); |
| struct timespec ts; |
| |
| if (res != 0) |
| return res; |
| |
| if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) |
| return TWO32TO64(ts.tv_sec, ts.tv_nsec); |
| return time(NULL); |
| } |
| |
| /* |
| * empty implementation |
| * vxworks does not need to init/cleanup or keep open the random lib |
| */ |
| int ossl_rand_pool_init(void) |
| { |
| return 1; |
| } |
| |
| void ossl_rand_pool_cleanup(void) |
| { |
| } |
| |
| void ossl_rand_pool_keep_random_devices_open(int keep) |
| { |
| } |
| |
| int ossl_rand_pool_add_additional_data(RAND_POOL *pool) |
| { |
| struct { |
| CRYPTO_THREAD_ID tid; |
| uint64_t time; |
| } data; |
| |
| memset(&data, 0, sizeof(data)); |
| |
| /* |
| * Add some noise from the thread id and a high resolution timer. |
| * The thread id adds a little randomness if the drbg is accessed |
| * concurrently (which is the case for the <master> drbg). |
| */ |
| data.tid = CRYPTO_THREAD_get_current_id(); |
| data.time = get_timer_bits(); |
| |
| return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
| } |
| |
| int ossl_pool_add_nonce_data(RAND_POOL *pool) |
| { |
| struct { |
| pid_t pid; |
| CRYPTO_THREAD_ID tid; |
| uint64_t time; |
| } data; |
| |
| memset(&data, 0, sizeof(data)); |
| |
| /* |
| * Add process id, thread id, and a high resolution timestamp to |
| * ensure that the nonce is unique with high probability for |
| * different process instances. |
| */ |
| data.pid = getpid(); |
| data.tid = CRYPTO_THREAD_get_current_id(); |
| data.time = get_time_stamp(); |
| |
| return ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); |
| } |
| |
| size_t ossl_pool_acquire_entropy(RAND_POOL *pool) |
| { |
| #if defined(RAND_SEED_VXRANDLIB) |
| /* vxRandLib based entropy method */ |
| size_t bytes_needed; |
| |
| bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
| if (bytes_needed > 0) |
| { |
| int retryCount = 0; |
| STATUS result = ERROR; |
| unsigned char *buffer; |
| |
| buffer = ossl_rand_pool_add_begin(pool, bytes_needed); |
| while ((result != OK) && (retryCount < 10)) { |
| RANDOM_NUM_GEN_STATUS status = randStatus(); |
| |
| if ((status == RANDOM_NUM_GEN_ENOUGH_ENTROPY) |
| || (status == RANDOM_NUM_GEN_MAX_ENTROPY)) { |
| result = randBytes(buffer, bytes_needed); |
| if (result == OK) |
| ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); |
| /* |
| * no else here: randStatus said ok, if randBytes failed |
| * it will result in another loop or no entropy |
| */ |
| } else { |
| /* |
| * give a minimum delay here to allow OS to collect more |
| * entropy. taskDelay duration will depend on the system tick, |
| * this is by design as the sw-random lib uses interrupts |
| * which will at least happen during ticks |
| */ |
| taskDelay(5); |
| } |
| retryCount++; |
| } |
| } |
| return ossl_rand_pool_entropy_available(pool); |
| #else |
| /* |
| * SEED_NONE means none, without randlib we dont have entropy and |
| * rely on it being added externally |
| */ |
| return ossl_rand_pool_entropy_available(pool); |
| #endif /* defined(RAND_SEED_VXRANDLIB) */ |
| } |