diff options
author | Orr Toledano <otoledan@amazon.com> | 2021-05-19 18:54:20 +0000 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2021-12-16 12:38:09 +0100 |
commit | efa1f22483ee43d84e1aee01b08c0bda04060c1c (patch) | |
tree | 219f223e67a048aa8187c1e222086ba7eab93152 | |
parent | a56bb5d64e7599140117f935eeeb34ba94c83aea (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-x | crypto/arm64cpuid.pl | 60 | ||||
-rw-r--r-- | crypto/arm_arch.h | 1 | ||||
-rw-r--r-- | crypto/armcap.c | 45 |
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 */ |