diff --git a/src/lib/rng/processor_rng/info.txt b/src/lib/rng/processor_rng/info.txt index 1332ae418ef..60d921efdf9 100644 --- a/src/lib/rng/processor_rng/info.txt +++ b/src/lib/rng/processor_rng/info.txt @@ -11,6 +11,7 @@ brief -> "Directly invokes a CPU specific instruction to generate random numbers x86_32 x86_64 ppc64 +arm64 diff --git a/src/lib/rng/processor_rng/processor_rng.cpp b/src/lib/rng/processor_rng/processor_rng.cpp index f72813b0294..04dafeafeea 100644 --- a/src/lib/rng/processor_rng/processor_rng.cpp +++ b/src/lib/rng/processor_rng/processor_rng.cpp @@ -34,6 +34,14 @@ const size_t HWRNG_RETRIES = 10; */ const size_t HWRNG_RETRIES = 10; +#elif(BOTAN_COMPILER_HAS_BUILTIN(__builtin_arm_rndrrs) || BOTAN_COMPILER_HAS_BUILTIN(__builtin_aarch64_rndrrs)) && \ + __GNUC__ > 11 +/** + * Does not seem to have an official number + * but 512 seems a bit much + */ +const size_t HWRNG_RETRIES = 10; + #else /* * Lacking specific guidance we give the CPU quite a bit of leeway @@ -63,6 +71,21 @@ hwrng_output read_hwrng(bool& success) { #endif success = (1 == cf); +#elif(BOTAN_COMPILER_HAS_BUILTIN(__builtin_arm_rndrrs) || BOTAN_COMPILER_HAS_BUILTIN(__builtin_aarch64_rndrrs)) && \ + __GNUC__ > 11 + /** + * apple devices do not seem to allow direct access to + * hardware random device on arm64 (aka TRNG). + * Here, fetching the value and status in one shot + */ + hwrng_output status = 0; + #if BOTAN_COMPILER_HAS_BUILTIN(__builtin_arm_rndrrs) && defined(__ARM_32BIT_STATE) && __ARM_32BIT_STATE + status = __builtin_arm_rndrrs(&output); + #elif BOTAN_COMPILER_HAS_BUILTIN(__builtin_aarch64_rndrrs) && defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE + status = __builtin_aarch64_rndrrs(&output); + #endif + success = (status == 0xb0000); + #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) /* @@ -108,6 +131,8 @@ hwrng_output read_hwrng() { bool Processor_RNG::available() { #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) return CPUID::has_rdrand(); +#elif defined(BOTAN_TARGET_ARCH_IS_ARM64) + return CPUID::has_arm_rndrrs(); #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) return CPUID::has_darn_rng(); #else @@ -120,6 +145,8 @@ std::string Processor_RNG::name() const { return "rdrand"; #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) return "darn"; +#elif defined(BOTAN_TARGET_ARCH_IS_ARM64) + return "rng"; #else return "hwrng"; #endif diff --git a/src/lib/utils/cpuid/cpuid.cpp b/src/lib/utils/cpuid/cpuid.cpp index 977892766f4..222a12239dc 100644 --- a/src/lib/utils/cpuid/cpuid.cpp +++ b/src/lib/utils/cpuid/cpuid.cpp @@ -222,6 +222,8 @@ std::vector CPUID::bit_from_string(std::string_view tok) { return {CPUID::CPUID_ARM_SM3_BIT}; if(tok == "armv8sm4" || tok == "arm_sm4") return {CPUID::CPUID_ARM_SM4_BIT}; + if(tok == "rng") + return {CPUID::CPUID_ARM_RND_BIT}; #else BOTAN_UNUSED(tok); diff --git a/src/lib/utils/cpuid/cpuid.h b/src/lib/utils/cpuid/cpuid.h index 9fc9ea37542..3e0b9788a9f 100644 --- a/src/lib/utils/cpuid/cpuid.h +++ b/src/lib/utils/cpuid/cpuid.h @@ -118,6 +118,7 @@ class BOTAN_TEST_API CPUID final { CPUID_ARM_SHA2_512_BIT = (1U << 21), CPUID_ARM_SM3_BIT = (1U << 22), CPUID_ARM_SM4_BIT = (1U << 23), + CPUID_ARM_RND_BIT = (1ULL << 24), #endif CPUID_IS_BIG_ENDIAN_BIT = (1U << 30), @@ -193,6 +194,10 @@ class BOTAN_TEST_API CPUID final { */ static bool has_arm_sm4() { return has_neon() && has_cpuid_bit(CPUID_ARM_SM4_BIT); } + /** + * Check if the processor supports ARMv8 RNDRRS + */ + static bool has_arm_rndrrs() { return has_cpuid_bit(CPUID_ARM_RND_BIT); } #endif #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) diff --git a/src/lib/utils/cpuid/cpuid_aarch64.cpp b/src/lib/utils/cpuid/cpuid_aarch64.cpp index 1c68c206c66..e9d370346da 100644 --- a/src/lib/utils/cpuid/cpuid_aarch64.cpp +++ b/src/lib/utils/cpuid/cpuid_aarch64.cpp @@ -48,6 +48,12 @@ uint32_t CPUID::CPUID_Data::detect_cpu_features() { ARCH_hwcap = 16, // AT_HWCAP }; + enum ARM_hwcap_crypto_bit { + RND_bit = (1 << 16), + + ARCH_hwcap_crypto = 26 // AT_HWCAP2 + }; + const unsigned long hwcap = OS::get_auxval(ARM_hwcap_bit::ARCH_hwcap); if(hwcap & ARM_hwcap_bit::NEON_bit) { detected_features |= CPUID::CPUID_ARM_NEON_BIT; @@ -70,6 +76,9 @@ uint32_t CPUID::CPUID_Data::detect_cpu_features() { if(hwcap & ARM_hwcap_bit::SVE_bit) detected_features |= CPUID::CPUID_ARM_SVE_BIT; } + const unsigned long hwcap_crypto = OS::get_auxval(ARM_hwcap_crypto_bit::ARCH_hwcap_crypto); + if(hwcap_crypto & ARM_hwcap_crypto_bit::RND_bit) + detected_features |= CPUID::CPUID_ARM_RND_BIT; #elif defined(BOTAN_TARGET_OS_IS_IOS) || defined(BOTAN_TARGET_OS_IS_MACOS)