[openssl] master update

tomas at openssl.org tomas at openssl.org
Thu Dec 16 11:38:48 UTC 2021


The branch master has been updated
       via  e8b597f33143410fb50bdeba8722c249524bc0b9 (commit)
       via  1f8ce0c9faee59ac51a5db7a8ec42c38866be090 (commit)
       via  eb28fda79748c303d88a8af48de5187100f2c64c (commit)
       via  efa1f22483ee43d84e1aee01b08c0bda04060c1c (commit)
      from  a56bb5d64e7599140117f935eeeb34ba94c83aea (commit)


- Log -----------------------------------------------------------------
commit e8b597f33143410fb50bdeba8722c249524bc0b9
Author: Orr Toledano <otoledan at amazon.com>
Date:   Thu May 20 22:13:30 2021 +0000

    Documentation for RNDR and RNDRRS
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15361)

commit 1f8ce0c9faee59ac51a5db7a8ec42c38866be090
Author: Orr Toledano <otoledan at amazon.com>
Date:   Thu May 6 18:46:27 2021 +0000

    Add tests for RNDR and combine tests with RDRAND
    
    Add test cases for RNDR and RNDRRS. Combine tests for RDRAND and RNDR to
    share common logic.
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15361)

commit eb28fda79748c303d88a8af48de5187100f2c64c
Author: Orr Toledano <otoledan at amazon.com>
Date:   Thu May 6 21:32:49 2021 +0000

    Add support for RNDRRS Provider
    
    Create new provider for RNDRRS. Modify support for rand_cpu to default to
    RDRAND/RDSEED on x86 and RNDRRS on aarch64.
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15361)

commit efa1f22483ee43d84e1aee01b08c0bda04060c1c
Author: Orr Toledano <otoledan at amazon.com>
Date:   Wed May 19 18:54:20 2021 +0000

    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 at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15361)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                                         |  5 ++
 INSTALL.md                                         |  3 +-
 crypto/arm64cpuid.pl                               | 60 +++++++++++++++++++
 crypto/arm_arch.h                                  |  1 +
 crypto/armcap.c                                    | 45 +++++++++++++++
 crypto/info.c                                      |  4 ++
 providers/implementations/rands/seeding/build.info |  7 ++-
 .../implementations/rands/seeding/rand_cpu_arm64.c | 67 ++++++++++++++++++++++
 test/build.info                                    |  8 +--
 test/{rdrand_sanitytest.c => rdcpu_sanitytest.c}   | 48 ++++++++++++----
 ...test_rdrand_sanity.t => 06-test_rdcpu_sanity.t} |  4 +-
 11 files changed, 234 insertions(+), 18 deletions(-)
 create mode 100644 providers/implementations/rands/seeding/rand_cpu_arm64.c
 rename test/{rdrand_sanitytest.c => rdcpu_sanitytest.c} (80%)
 rename test/recipes/{06-test_rdrand_sanity.t => 06-test_rdcpu_sanity.t} (87%)

diff --git a/CHANGES.md b/CHANGES.md
index 16e2c341bd..7ddc41a0e7 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -24,6 +24,11 @@ OpenSSL 3.1
 
 ### Changes between 3.0 and 3.1 [xx XXX xxxx]
 
+ * RNDR and RNDRRS support in provider functions to provide
+   random number generation for Arm CPUs (aarch64).
+
+   *Orr Toledano*
+
  * s_client and s_server apps now explicitly say when the TLS version
    does not include the renegotiation mechanism. This avoids confusion
    between that scenario versus when the TLS version includes secure
diff --git a/INSTALL.md b/INSTALL.md
index 70eb8da1ed..40ca7090b5 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -446,7 +446,8 @@ This source is ignored by the FIPS provider.
 
 ### rdcpu
 
-Use the `RDSEED` or `RDRAND` command if provided by the CPU.
+Use the `RDSEED` or `RDRAND` command on x86 or `RNDRRS` command on aarch64
+if provided by the CPU.
 
 ### librandom
 
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 */
diff --git a/crypto/info.c b/crypto/info.c
index a106e8c885..f3bef56b13 100644
--- a/crypto/info.c
+++ b/crypto/info.c
@@ -135,7 +135,11 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings)
         add_seeds_string("stdsc");
 #endif
 #ifdef OPENSSL_RAND_SEED_RDCPU
+# ifdef __aarch64__
+        add_seeds_string("rndr ( rndrrs rndr )");
+# else
         add_seeds_string("rdrand ( rdseed rdrand )");
+# endif
 #endif
 #ifdef OPENSSL_RAND_SEED_LIBRANDOM
         add_seeds_string("C-library-random");
diff --git a/providers/implementations/rands/seeding/build.info b/providers/implementations/rands/seeding/build.info
index 2788146ad4..9c5eefee2d 100644
--- a/providers/implementations/rands/seeding/build.info
+++ b/providers/implementations/rands/seeding/build.info
@@ -1,10 +1,15 @@
-$COMMON=rand_unix.c rand_win.c rand_tsc.c rand_cpu_x86.c
+$COMMON=rand_unix.c rand_win.c rand_tsc.c
 IF[{- $config{target} =~ /vxworks/i -}]
   $COMMON=$COMMON rand_vxworks.c
 ENDIF
 IF[{- $config{target} =~ /vms/i -}]
   $COMMON=$COMMON rand_vms.c
 ENDIF
+IF[{- !$disabled{asm} && $config{target} =~ '.*aarch64' -}]
+  $COMMON=$COMMON rand_cpu_arm64.c
+ELSE
+  $COMMON=$COMMON rand_cpu_x86.c
+ENDIF
 
 SOURCE[../../../libdefault.a]=$COMMON
 
diff --git a/providers/implementations/rands/seeding/rand_cpu_arm64.c b/providers/implementations/rands/seeding/rand_cpu_arm64.c
new file mode 100644
index 0000000000..a8530e02b5
--- /dev/null
+++ b/providers/implementations/rands/seeding/rand_cpu_arm64.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/cryptlib.h"
+#include <openssl/opensslconf.h>
+#include "crypto/rand_pool.h"
+#include "prov/seeding.h"
+
+
+#ifdef OPENSSL_RAND_SEED_RDCPU
+#include "crypto/arm_arch.h"
+
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
+
+static size_t get_hardware_random_value(unsigned char *buf, size_t len);
+
+/*
+ * Acquire entropy using Arm-specific cpu instructions
+ *
+ * Uses the RNDRRS instruction. RNDR is never needed since
+ * RNDRRS will always be available if RNDR is an available
+ * instruction.
+ *
+ * Returns the total entropy count, if it exceeds the requested
+ * entropy count. Otherwise, returns an entropy count of 0.
+ */
+size_t ossl_prov_acquire_entropy_from_cpu(RAND_POOL *pool)
+{
+    size_t bytes_needed;
+    unsigned char *buffer;
+
+    bytes_needed = ossl_rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
+    if (bytes_needed > 0) {
+        buffer = ossl_rand_pool_add_begin(pool, bytes_needed);
+
+        if (buffer != NULL) {
+            if (get_hardware_random_value(buffer, bytes_needed) == bytes_needed)
+                ossl_rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
+            else
+                ossl_rand_pool_add_end(pool, 0, 0);
+        }
+    }
+
+    return ossl_rand_pool_entropy_available(pool);
+}
+
+static size_t get_hardware_random_value(unsigned char *buf, size_t len)
+{
+    /* Always use RNDRRS or nothing */
+    if (OPENSSL_armcap_P & ARMV8_RNG)  {
+        if (OPENSSL_rndrrs_bytes(buf, len) != len)
+            return 0;
+    } else {
+        return 0;
+    }
+    return len;
+}
+
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif /* OPENSSL_RAND_SEED_RDCPU */
diff --git a/test/build.info b/test/build.info
index bc8d400232..ec4bd8d5db 100644
--- a/test/build.info
+++ b/test/build.info
@@ -584,7 +584,7 @@ IF[{- !$disabled{tests} -}]
   IF[1]
     PROGRAMS{noinst}=asn1_internal_test modes_internal_test x509_internal_test \
                      tls13encryptiontest wpackettest ctype_internal_test \
-                     rdrand_sanitytest property_test ideatest rsa_mp_test \
+                     rdcpu_sanitytest property_test ideatest rsa_mp_test \
                      rsa_sp800_56b_test bn_internal_test ecdsatest rsa_test \
                      rc2test rc4test rc5test hmactest ffc_internal_test \
                      asn1_dsa_internal_test dsatest dsa_no_digest_size_test \
@@ -737,9 +737,9 @@ IF[{- !$disabled{tests} -}]
     INCLUDE[rc4test]=../include ../apps/include
     DEPEND[rc4test]=../libcrypto.a libtestutil.a
 
-    SOURCE[rdrand_sanitytest]=rdrand_sanitytest.c
-    INCLUDE[rdrand_sanitytest]=../include ../apps/include
-    DEPEND[rdrand_sanitytest]=../libcrypto.a libtestutil.a
+    SOURCE[rdcpu_sanitytest]=rdcpu_sanitytest.c
+    INCLUDE[rdcpu_sanitytest]=../include ../apps/include ../crypto
+    DEPEND[rdcpu_sanitytest]=../libcrypto.a libtestutil.a
 
     SOURCE[rsa_sp800_56b_test]=rsa_sp800_56b_test.c
     INCLUDE[rsa_sp800_56b_test]=.. ../include ../crypto/rsa ../apps/include
diff --git a/test/rdrand_sanitytest.c b/test/rdcpu_sanitytest.c
similarity index 80%
rename from test/rdrand_sanitytest.c
rename to test/rdcpu_sanitytest.c
index dcc9d2800a..df1858ae9b 100644
--- a/test/rdrand_sanitytest.c
+++ b/test/rdcpu_sanitytest.c
@@ -16,10 +16,24 @@
 #if (defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
      defined(__x86_64) || defined(__x86_64__) || \
      defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ)
-
+# define IS_X_86 1
 size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
 size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
+#else
+# define IS_X_86 0
+#endif
+
+#if defined(__aarch64__)
+# define IS_AARCH_64 1
+# include "arm_arch.h"
+
+size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len);
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
+#else
+# define IS_AARCH_64 0
+#endif
 
+#if (IS_X_86 || IS_AARCH_64)
 static int sanity_check_bytes(size_t (*rng)(unsigned char *, size_t),
     int rounds, int min_failures, int max_retries, int max_zero_words)
 {
@@ -76,7 +90,9 @@ static int sanity_check_bytes(size_t (*rng)(unsigned char *, size_t),
 end:
     return testresult;
 }
+#endif
 
+#if IS_X_86
 static int sanity_check_rdrand_bytes(void)
 {
     return sanity_check_bytes(OPENSSL_ia32_rdrand_bytes, 1000, 0, 10, 10);
@@ -92,11 +108,24 @@ static int sanity_check_rdseed_bytes(void)
      */
     return sanity_check_bytes(OPENSSL_ia32_rdseed_bytes, 1000, 1, 10000, 10);
 }
+#elif IS_AARCH_64
+static int sanity_check_rndr_bytes(void)
+{
+    return sanity_check_bytes(OPENSSL_rndr_bytes, 1000, 0, 10, 10);
+}
+
+static int sanity_check_rndrrs_bytes(void)
+{
+    return sanity_check_bytes(OPENSSL_rndrrs_bytes, 1000, 0, 10000, 10);
+}
+#endif
 
 int setup_tests(void)
 {
+#if (IS_X_86 || IS_AARCH_64)
     OPENSSL_cpuid_setup();
 
+# if IS_X_86
     int have_rdseed = (OPENSSL_ia32cap_P[2] & (1 << 18)) != 0;
     int have_rdrand = (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0;
 
@@ -107,16 +136,15 @@ int setup_tests(void)
     if (have_rdseed) {
         ADD_TEST(sanity_check_rdseed_bytes);
     }
+# elif IS_AARCH_64
+    int have_rndr_rndrrs = (OPENSSL_armcap_P & (1 << 8)) != 0;
 
-    return 1;
-}
-
-
-#else
+    if (have_rndr_rndrrs) {
+        ADD_TEST(sanity_check_rndr_bytes);
+        ADD_TEST(sanity_check_rndrrs_bytes);
+    }
+# endif
+#endif
 
-int setup_tests(void)
-{
     return 1;
 }
-
-#endif
diff --git a/test/recipes/06-test_rdrand_sanity.t b/test/recipes/06-test_rdcpu_sanity.t
similarity index 87%
rename from test/recipes/06-test_rdrand_sanity.t
rename to test/recipes/06-test_rdcpu_sanity.t
index a20e09e778..9907abc7c0 100644
--- a/test/recipes/06-test_rdrand_sanity.t
+++ b/test/recipes/06-test_rdcpu_sanity.t
@@ -13,10 +13,10 @@ use OpenSSL::Test;              # get 'plan'
 use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
-setup("test_rdrand_sanity");
+setup("test_rdcpu_sanity");
 
 # We also need static builds to be enabled even on linux
 plan skip_all => "This test is unsupported if static builds are not enabled"
     if disabled("static");
 
-simple_test("test_rdrand_sanity", "rdrand_sanitytest");
+simple_test("test_rdcpu_sanity", "rdcpu_sanitytest");


More information about the openssl-commits mailing list