summaryrefslogtreecommitdiff
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)
downloadopenssl-new-efa1f22483ee43d84e1aee01b08c0bda04060c1c.tar.gz
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 */