summaryrefslogtreecommitdiffstats
path: root/crypto/armcap.c
diff options
context:
space:
mode:
authorOrr Toledano <otoledan@amazon.com>2021-05-19 18:54:20 +0000
committerTomas Mraz <tomas@openssl.org>2021-12-16 12:38:09 +0100
commitefa1f22483ee43d84e1aee01b08c0bda04060c1c (patch)
tree219f223e67a048aa8187c1e222086ba7eab93152 /crypto/armcap.c
parenta56bb5d64e7599140117f935eeeb34ba94c83aea (diff)
Add Arm Assembly (aarch64) support for RNG
Include aarch64 asm instructions for random number generation using the RNDR and RNDRRS instructions. Provide detection functions for RNDR and RNDRRS getauxval. Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15361)
Diffstat (limited to 'crypto/armcap.c')
-rw-r--r--crypto/armcap.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/crypto/armcap.c b/crypto/armcap.c
index 5b45a9d0f4..117c57efe4 100644
--- a/crypto/armcap.c
+++ b/crypto/armcap.c
@@ -17,6 +17,7 @@
#include <sys/sysctl.h>
#endif
#include "internal/cryptlib.h"
+#include <unistd.h>
#include "arm_arch.h"
@@ -54,6 +55,37 @@ void _armv8_pmull_probe(void);
# ifdef __aarch64__
void _armv8_sha512_probe(void);
unsigned int _armv8_cpuid_probe(void);
+void _armv8_rng_probe(void);
+
+size_t OPENSSL_rndr_asm(unsigned char *buf, size_t len);
+size_t OPENSSL_rndrrs_asm(unsigned char *buf, size_t len);
+
+size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len);
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
+
+static size_t OPENSSL_rndr_wrapper(size_t (*func)(unsigned char *, size_t), unsigned char *buf, size_t len)
+{
+ size_t buffer_size;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ buffer_size = func(buf, len);
+ if (buffer_size == len)
+ break;
+ usleep(5000); /* 5000 microseconds (5 milliseconds) */
+ }
+ return buffer_size;
+}
+
+size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len)
+{
+ return OPENSSL_rndr_wrapper(OPENSSL_rndr_asm, buf, len);
+}
+
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len)
+{
+ return OPENSSL_rndr_wrapper(OPENSSL_rndrrs_asm, buf, len);
+}
# endif
uint32_t _armv7_tick(void);
@@ -138,6 +170,9 @@ static unsigned long getauxval(unsigned long key)
# define HWCAP_CE_SHA256 (1 << 6)
# define HWCAP_CPUID (1 << 11)
# define HWCAP_CE_SHA512 (1 << 21)
+ /* AT_HWCAP2 */
+# define HWCAP2 26
+# define HWCAP2_RNG (1 << 16)
# endif
void OPENSSL_cpuid_setup(void)
@@ -212,6 +247,10 @@ void OPENSSL_cpuid_setup(void)
OPENSSL_armcap_P |= ARMV8_CPUID;
# endif
}
+# ifdef __aarch64__
+ if (getauxval(HWCAP2) & HWCAP2_RNG)
+ OPENSSL_armcap_P |= ARMV8_RNG;
+# endif
# endif
sigfillset(&all_masked);
@@ -255,6 +294,12 @@ void OPENSSL_cpuid_setup(void)
}
# endif
}
+# ifdef __aarch64__
+ if (sigsetjmp(ill_jmp, 1) == 0) {
+ _armv8_rng_probe();
+ OPENSSL_armcap_P |= ARMV8_RNG;
+ }
+# endif
# endif
/* Things that getauxval didn't tell us */