diff options
author | Randall S. Becker <rsbecker@nexbridge.com> | 2020-09-24 08:16:37 -0500 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-09-25 20:06:59 +0200 |
commit | d3edef83f5fa378237fcece038f9aff9f89f34cd (patch) | |
tree | bb1b48335e18531a0c319410757ff1f53109b9ae | |
parent | a48309cb5c58be8fa310608124925d4729664cf8 (diff) | |
download | openssl-d3edef83f5fa378237fcece038f9aff9f89f34cd.tar.gz |
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 <rsbecker@nexbridge.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/12923)
-rw-r--r-- | providers/implementations/rands/seeding/rand_cpu_x86.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/providers/implementations/rands/seeding/rand_cpu_x86.c b/providers/implementations/rands/seeding/rand_cpu_x86.c index fd47de9ad0..73af554d68 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 <builtin.h> /* _rdrand64 */ +# include <string.h> /* 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 |