From e1c5b1f6b4b92b819992cab702b6fdfc2960461c Mon Sep 17 00:00:00 2001 From: Pauli Date: Mon, 11 May 2020 12:06:37 +1000 Subject: [PATCH] rand: add seeding sources to providers. Also separate out the TSC and RDRAND based sources into their own file in the seeding subdirectory. Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/11682) --- providers/implementations/rands/build.info | 1 + providers/implementations/rands/rand_pool.c | 9 +++ .../implementations/rands/seeding/build.info | 11 ++++ .../rands/seeding/rand_cpu_x86.c | 61 +++++++++++++++++++ .../implementations/rands/seeding/rand_tsc.c | 47 ++++++++++++++ .../implementations/rands/seeding/rand_unix.c | 11 ++-- .../implementations/rands/seeding/rand_vms.c | 7 ++- .../rands/seeding/rand_vxworks.c | 7 ++- .../implementations/rands/seeding/rand_win.c | 22 ++----- .../implementations/rands/seeding/seeding.h | 34 +++++++++++ 10 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 providers/implementations/rands/rand_pool.c create mode 100644 providers/implementations/rands/seeding/build.info create mode 100644 providers/implementations/rands/seeding/rand_cpu_x86.c create mode 100644 providers/implementations/rands/seeding/rand_tsc.c create mode 100644 providers/implementations/rands/seeding/seeding.h diff --git a/providers/implementations/rands/build.info b/providers/implementations/rands/build.info index 00f62e523e..5d55c27fe4 100644 --- a/providers/implementations/rands/build.info +++ b/providers/implementations/rands/build.info @@ -1,3 +1,4 @@ +SUBDIRS=seeding # Missing: drbg_ctr.c SOURCE[../../libfips.a]=drbg.c diff --git a/providers/implementations/rands/rand_pool.c b/providers/implementations/rands/rand_pool.c new file mode 100644 index 0000000000..71b71190e8 --- /dev/null +++ b/providers/implementations/rands/rand_pool.c @@ -0,0 +1,9 @@ +/* + * Copyright 2020 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 + */ + diff --git a/providers/implementations/rands/seeding/build.info b/providers/implementations/rands/seeding/build.info new file mode 100644 index 0000000000..e75a941098 --- /dev/null +++ b/providers/implementations/rands/seeding/build.info @@ -0,0 +1,11 @@ +$COMMON=rand_unix.c rand_win.c rand_tsc.c rand_cpu_x86.c +IF[{- $config{target} =~ /vxworks/i -}] + $COMMON=$COMMON rand_vxworks.c +ENDIF +IF[{- $config{target} =~ /vms/i -}] + $COMMON=$COMMON rand_vms.c +ENDIF + +SOURCE[../../../libfips.a]=$COMMON +SOURCE[../../../libnonfips.a]=$COMMON + diff --git a/providers/implementations/rands/seeding/rand_cpu_x86.c b/providers/implementations/rands/seeding/rand_cpu_x86.c new file mode 100644 index 0000000000..3b276c8f54 --- /dev/null +++ b/providers/implementations/rands/seeding/rand_cpu_x86.c @@ -0,0 +1,61 @@ +/* + * Copyright 1995-2020 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 "internal/cryptlib.h" +#include +#include "crypto/rand_pool.h" + +#ifdef OPENSSL_RAND_SEED_RDCPU +size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len); +size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len); + +/* + * Acquire entropy using Intel-specific cpu instructions + * + * Uses the RDSEED instruction if available, otherwise uses + * RDRAND if available. + * + * For the differences between RDSEED and RDRAND, and why RDSEED + * is the preferred choice, see https://goo.gl/oK3KcN + * + * Returns the total entropy count, if it exceeds the requested + * entropy count. Otherwise, returns an entropy count of 0. + */ +size_t prov_acquire_entropy_from_cpu(RAND_POOL *pool) +{ + size_t bytes_needed; + unsigned char *buffer; + + bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); + if (bytes_needed > 0) { + buffer = rand_pool_add_begin(pool, bytes_needed); + + if (buffer != NULL) { + /* Whichever comes first, use RDSEED, RDRAND or nothing */ + if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) { + if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed) + == bytes_needed) { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); + } + } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) { + if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed) + == bytes_needed) { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); + } + } else { + rand_pool_add_end(pool, 0, 0); + } + } + } + + return rand_pool_entropy_available(pool); +} +#else +NON_EMPTY_TRANSLATION_UNIT +#endif diff --git a/providers/implementations/rands/seeding/rand_tsc.c b/providers/implementations/rands/seeding/rand_tsc.c new file mode 100644 index 0000000000..2121abe499 --- /dev/null +++ b/providers/implementations/rands/seeding/rand_tsc.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2020 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 "internal/cryptlib.h" +#include +#include "crypto/rand_pool.h" + +#ifdef OPENSSL_RAND_SEED_RDTSC +/* + * IMPORTANT NOTE: It is not currently possible to use this code + * because we are not sure about the amount of randomness it provides. + * Some SP800-90B tests have been run, but there is internal skepticism. + * So for now this code is not used. + */ +# error "RDTSC enabled? Should not be possible!" + +/* + * Acquire entropy from high-speed clock + * + * Since we get some randomness from the low-order bits of the + * high-speed clock, it can help. + * + * Returns the total entropy count, if it exceeds the requested + * entropy count. Otherwise, returns an entropy count of 0. + */ +size_t prov_acquire_entropy_from_tsc(RAND_POOL *pool) +{ + unsigned char c; + int i; + + if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) { + for (i = 0; i < TSC_READ_COUNT; i++) { + c = (unsigned char)(OPENSSL_rdtsc() & 0xFF); + rand_pool_add(pool, &c, 1, 4); + } + } + return rand_pool_entropy_available(pool); +} +#else +NON_EMPTY_TRANSLATION_UNIT +#endif diff --git a/providers/implementations/rands/seeding/rand_unix.c b/providers/implementations/rands/seeding/rand_unix.c index 869c2d04dd..050b3e9a18 100644 --- a/providers/implementations/rands/seeding/rand_unix.c +++ b/providers/implementations/rands/seeding/rand_unix.c @@ -10,15 +10,16 @@ #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif -#include "e_os.h" +#include "../e_os.h" #include #include "internal/cryptlib.h" #include #include -#include "rand_local.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" #include #include "internal/dso.h" +#include "seeding.h" #ifdef __linux # include @@ -131,7 +132,7 @@ static uint64_t get_timer_bits(void); * * As a precaution, we assume only 2 bits of entropy per byte. */ -size_t rand_pool_acquire_entropy(RAND_POOL *pool) +size_t prov_pool_acquire_entropy(RAND_POOL *pool) { short int code; int i, k; @@ -603,7 +604,7 @@ void rand_pool_keep_random_devices_open(int keep) * of input from the different entropy sources (trust, quality, * possibility of blocking). */ -size_t rand_pool_acquire_entropy(RAND_POOL *pool) +size_t prov_pool_acquire_entropy(RAND_POOL *pool) { # if defined(OPENSSL_RAND_SEED_NONE) return rand_pool_entropy_available(pool); @@ -729,7 +730,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) #if (defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_SYS_VXWORKS)) \ || defined(__DJGPP__) -int rand_pool_add_nonce_data(RAND_POOL *pool) +int prov_pool_add_nonce_data(RAND_POOL *pool) { struct { pid_t pid; diff --git a/providers/implementations/rands/seeding/rand_vms.c b/providers/implementations/rands/seeding/rand_vms.c index 6b9fa2c725..761dad1168 100644 --- a/providers/implementations/rands/seeding/rand_vms.c +++ b/providers/implementations/rands/seeding/rand_vms.c @@ -14,7 +14,8 @@ #include "internal/cryptlib.h" #include #include "crypto/rand.h" -#include "rand_local.h" +#include "crypto/rand_pool.h" +#include "seeding.h" #include #include #include @@ -473,7 +474,7 @@ size_t data_collect_method(RAND_POOL *pool) return rand_pool_entropy_available(pool); } -int rand_pool_add_nonce_data(RAND_POOL *pool) +int prov_pool_add_nonce_data(RAND_POOL *pool) { struct { pid_t pid; @@ -567,7 +568,7 @@ size_t get_entropy_method(RAND_POOL *pool) * These functions are called by the RAND / DRBG functions */ -size_t rand_pool_acquire_entropy(RAND_POOL *pool) +size_t prov_pool_acquire_entropy(RAND_POOL *pool) { if (init_get_entropy_address()) return get_entropy_method(pool); diff --git a/providers/implementations/rands/seeding/rand_vxworks.c b/providers/implementations/rands/seeding/rand_vxworks.c index 427d50d263..ec9004c06c 100644 --- a/providers/implementations/rands/seeding/rand_vxworks.c +++ b/providers/implementations/rands/seeding/rand_vxworks.c @@ -10,9 +10,10 @@ #include #include -#include "rand_local.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" #include "internal/cryptlib.h" +#include "seeding.h" #include #include @@ -95,7 +96,7 @@ int rand_pool_add_additional_data(RAND_POOL *pool) return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); } -int rand_pool_add_nonce_data(RAND_POOL *pool) +int prov_pool_add_nonce_data(RAND_POOL *pool) { struct { pid_t pid; @@ -117,7 +118,7 @@ int rand_pool_add_nonce_data(RAND_POOL *pool) return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); } -size_t rand_pool_acquire_entropy(RAND_POOL *pool) +size_t prov_pool_acquire_entropy(RAND_POOL *pool) { #if defined(RAND_SEED_VXRANDLIB) /* vxRandLib based entropy method */ diff --git a/providers/implementations/rands/seeding/rand_win.c b/providers/implementations/rands/seeding/rand_win.c index 89f9d6f1f6..d5c5b59269 100644 --- a/providers/implementations/rands/seeding/rand_win.c +++ b/providers/implementations/rands/seeding/rand_win.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2018 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 @@ -9,8 +9,9 @@ #include "internal/cryptlib.h" #include -#include "rand_local.h" +#include "crypto/rand_pool.h" #include "crypto/rand.h" +#include "seeding.h" #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) # ifndef OPENSSL_RAND_SEED_OS @@ -40,7 +41,7 @@ # define INTEL_DEF_PROV L"Intel Hardware Cryptographic Service Provider" # endif -size_t rand_pool_acquire_entropy(RAND_POOL *pool) +size_t prov_pool_acquire_entropy(RAND_POOL *pool) { # ifndef USE_BCRYPTGENRANDOM HCRYPTPROV hProvider; @@ -120,7 +121,7 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) } -int rand_pool_add_nonce_data(RAND_POOL *pool) +int prov_pool_add_nonce_data(RAND_POOL *pool) { struct { DWORD pid; @@ -163,19 +164,6 @@ int rand_pool_add_additional_data(RAND_POOL *pool) return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); } -# if !defined(OPENSSL_NO_DEPRECATED_1_1_0) && !defined(FIPS_MODULE) -int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam) -{ - RAND_poll(); - return RAND_status(); -} - -void RAND_screen(void) -{ - RAND_poll(); -} -# endif - int rand_pool_init(void) { return 1; diff --git a/providers/implementations/rands/seeding/seeding.h b/providers/implementations/rands/seeding/seeding.h new file mode 100644 index 0000000000..bd0a57a769 --- /dev/null +++ b/providers/implementations/rands/seeding/seeding.h @@ -0,0 +1,34 @@ +/* + * Copyright 2020 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 "prov/rand_pool.h" + +/* Hardware-based seeding functions. */ +size_t prov_acquire_entropy_from_tsc(RAND_POOL *pool); +size_t prov_acquire_entropy_from_cpu(RAND_POOL *pool); + +/* DRBG entropy callbacks. */ +size_t prov_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout); + +void prov_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out); + +size_t prov_pool_acquire_entropy(RAND_POOL *pool); +int prov_pool_add_nonce_data(RAND_POOL *pool); + +/* + * Add some platform specific additional data + * + * This function is platform specific and adds some random noise to the + * additional data used for generating random bytes and for reseeding + * the drbg. + * + * Returns 1 on success and 0 on failure. + */ +int rand_pool_add_additional_data(RAND_POOL *pool); + -- 2.25.1