summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorRandall S. Becker <rsbecker@nexbridge.com>2020-09-24 08:16:37 -0500
committerRichard Levitte <levitte@openssl.org>2020-09-25 20:06:59 +0200
commitd3edef83f5fa378237fcece038f9aff9f89f34cd (patch)
treebb1b48335e18531a0c319410757ff1f53109b9ae /providers
parenta48309cb5c58be8fa310608124925d4729664cf8 (diff)
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)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/rands/seeding/rand_cpu_x86.c66
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