summaryrefslogtreecommitdiffstats
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
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)
-rwxr-xr-xcrypto/arm64cpuid.pl60
-rw-r--r--crypto/arm_arch.h1
-rw-r--r--crypto/armcap.c45
3 files changed, 106 insertions, 0 deletions
diff --git a/crypto/arm64cpuid.pl b/crypto/arm64cpuid.pl
index 11f0e50279..a86fa6073a 100755
--- a/crypto/arm64cpuid.pl
+++ b/crypto/arm64cpuid.pl
@@ -161,7 +161,67 @@ CRYPTO_memcmp:
lsr w0,w0,#31
ret
.size CRYPTO_memcmp,.-CRYPTO_memcmp
+
+.globl _armv8_rng_probe
+.type _armv8_rng_probe,%function
+_armv8_rng_probe:
+ mrs x0, s3_3_c2_c4_0 // rndr
+ mrs x0, s3_3_c2_c4_1 // rndrrs
+ ret
+.size _armv8_rng_probe,.-_armv8_rng_probe
+___
+
+sub gen_random {
+my $rdop = shift;
+my $rand_reg = $rdop eq "rndr" ? "s3_3_c2_c4_0" : "s3_3_c2_c4_1";
+
+print<<___;
+// Fill buffer with Randomly Generated Bytes
+// inputs: char * in x0 - Pointer to buffer
+// size_t in x1 - Number of bytes to write to buffer
+// outputs: size_t in x0 - Number of bytes successfully written to buffer
+.globl OPENSSL_${rdop}_asm
+.type OPENSSL_${rdop}_asm,%function
+.align 4
+OPENSSL_${rdop}_asm:
+ mov x2,xzr
+ mov x3,xzr
+
+.align 4
+.Loop_${rdop}:
+ cmp x1,#0
+ b.eq .${rdop}_done
+ mov x3,xzr
+ mrs x3,$rand_reg
+ b.eq .${rdop}_done
+
+ cmp x1,#8
+ b.lt .Loop_single_byte_${rdop}
+
+ str x3,[x0]
+ add x0,x0,#8
+ add x2,x2,#8
+ subs x1,x1,#8
+ b.ge .Loop_${rdop}
+
+.align 4
+.Loop_single_byte_${rdop}:
+ strb w3,[x0]
+ lsr x3,x3,#8
+ add x2,x2,#1
+ add x0,x0,#1
+ subs x1,x1,#1
+ b.gt .Loop_single_byte_${rdop}
+
+.align 4
+.${rdop}_done:
+ mov x0,x2
+ ret
+.size OPENSSL_${rdop}_asm,.-OPENSSL_${rdop}_asm
___
+}
+gen_random("rndr");
+gen_random("rndrrs");
print $code;
close STDOUT or die "error closing STDOUT: $!";
diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h
index aa380acce0..ca48045670 100644
--- a/crypto/arm_arch.h
+++ b/crypto/arm_arch.h
@@ -83,6 +83,7 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
# define ARMV8_PMULL (1<<5)
# define ARMV8_SHA512 (1<<6)
# define ARMV8_CPUID (1<<7)
+# define ARMV8_RNG (1<<8)
/*
* MIDR_EL1 system register
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 */