From: Randall S. Becker Date: Thu, 24 Sep 2020 13:16:37 +0000 (-0500) Subject: Modified rand_cpu_x86.c to support builtin hardware randomizer on HPE NonStop. X-Git-Tag: openssl-3.0.0-alpha7~114 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d3edef83f5fa378237fcece038f9aff9f89f34cd;p=thirdparty%2Fopenssl.git Modified rand_cpu_x86.c to support builtin hardware randomizer on HPE NonStop. CLA: Permission is granted by the author to the OpenSSL team to use these modifications. Fixes #12903 Signed-off-by: Randall S. Becker Reviewed-by: Paul Dale Reviewed-by: Dmitry Belyavskiy Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/12923) --- diff --git a/providers/implementations/rands/seeding/rand_cpu_x86.c b/providers/implementations/rands/seeding/rand_cpu_x86.c index fd47de9ad01..73af554d68c 100644 --- a/providers/implementations/rands/seeding/rand_cpu_x86.c +++ b/providers/implementations/rands/seeding/rand_cpu_x86.c @@ -13,8 +13,14 @@ #include "prov/seeding.h" #ifdef OPENSSL_RAND_SEED_RDCPU +# if defined(OPENSSL_SYS_TANDEM) && defined(_TNS_X_TARGET) +# include /* _rdrand64 */ +# include /* memcpy */ +static size_t get_hardware_random_value(unsigned char *buf, size_t len); +# else size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len); size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len); +# endif /* * Acquire entropy using Intel-specific cpu instructions @@ -38,17 +44,8 @@ size_t prov_acquire_entropy_from_cpu(RAND_POOL *pool) 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); - } + if (get_hardware_random_value(buffer, bytes_needed) == bytes_needed) { + rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); } else { rand_pool_add_end(pool, 0, 0); } @@ -57,6 +54,53 @@ size_t prov_acquire_entropy_from_cpu(RAND_POOL *pool) return rand_pool_entropy_available(pool); } + +#if defined(OPENSSL_SYS_TANDEM) && defined(_TNS_X_TARGET) +/* Obtain random bytes from the x86 hardware random function in 64 bit chunks */ +static size_t get_hardware_random_value(unsigned char *buf, size_t len) +{ + size_t bytes_remaining = len; + + while (bytes_remaining > 0) { + /* Always use 64 bit fetch, then use the lower bytes as needed. */ + /* The platform is big-endian. */ + uint64_t random_value = 0; + + if (_rdrand64(&random_value) != 0) { + unsigned char *random_buffer = (unsigned char *)&random_value; + + if (bytes_remaining >= sizeof(random_value)) { + memcpy(buf, random_buffer, sizeof(random_value)); + bytes_remaining -= sizeof(random_value); + buf += sizeof(random_value); + } else { + memcpy(buf, + random_buffer + (sizeof(random_value) - bytes_remaining), + bytes_remaining); + bytes_remaining = 0; /* This will terminate the loop */ + } + } else + break; + } + if (bytes_remaining == 0) + return len; + return 0; +} +#else +static size_t get_hardware_random_value(unsigned char *buf, size_t len) { + /* Whichever comes first, use RDSEED, RDRAND or nothing */ + if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) { + if (OPENSSL_ia32_rdseed_bytes(buf, len) != len) + return 0; + } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) { + if (OPENSSL_ia32_rdrand_bytes(buf, len) != len) + return 0; + } else + return 0; + return len; +} +#endif + #else NON_EMPTY_TRANSLATION_UNIT #endif