diff --git a/src/lib/rng/processor_rng/info.txt b/src/lib/rng/processor_rng/info.txt index eb2d5ef51b8..9b66c1a42bf 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 31557543fa8..80c93f685ba 100644 --- a/src/lib/rng/processor_rng/processor_rng.cpp +++ b/src/lib/rng/processor_rng/processor_rng.cpp @@ -13,6 +13,8 @@ #if defined(BOTAN_TARGET_ARCH_IS_X86_FAMILY) && !defined(BOTAN_USE_GCC_INLINE_ASM) #include +#elif defined(BOTAN_TARGET_ARCH_IS_ARM64) && !defined(BOTAN_USE_GCC_INLINE_ASM) + #include #endif namespace Botan { @@ -83,6 +85,17 @@ hwrng_output BOTAN_FN_ISA_RNG read_hwrng(bool& success) { success = true; } +#elif defined(BOTAN_TARGET_ARCH_IS_ARM64) + + uint64_t nzcv = 0; // NOLINT(*-const-correctness) clang-tidy doesn't understand inline asm + #if defined(BOTAN_USE_GCC_INLINE_ASM) + // NOLINTNEXTLINE(*-no-assembler) + asm volatile("mrs %0, rndr; mrs %1, nzcv" : "=r"(output), "=r"(nzcv) : "0"(output), "1"(nzcv) : "cc"); + #else + nzcv = __rndr(&output); + #endif + success = (0 == nzcv); + #endif if(success) { @@ -113,6 +126,8 @@ bool Processor_RNG::available() { return CPUID::has(CPUID::Feature::RDRAND); #elif defined(BOTAN_TARGET_ARCH_IS_PPC_FAMILY) return CPUID::has(CPUID::Feature::DARN); +#elif defined(BOTAN_TARGET_ARCH_IS_ARM64) + return CPUID::has(CPUID::Feature::RNG); #else return false; #endif @@ -123,6 +138,8 @@ std::string Processor_RNG::name() const { return "rdrand"; #elif defined(BOTAN_TARGET_ARCH_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_aarch64/cpuid_aarch64.cpp b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_aarch64.cpp index 2d8a58eb5f0..c964d979c1c 100644 --- a/src/lib/utils/cpuid/cpuid_aarch64/cpuid_aarch64.cpp +++ b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_aarch64.cpp @@ -48,6 +48,9 @@ std::optional aarch64_feat_via_auxval(uint32_t allowed) { SHA2_512_bit = (1 << 21), SVE_bit = (1 << 22), }; + enum class ARM_hwcap2_bit : uint64_t /* NOLINT(*-enum-size) */ { + RNG_bit = (1 << 16), + }; const auto hwcap = auxval->first; @@ -65,6 +68,9 @@ std::optional aarch64_feat_via_auxval(uint32_t allowed) { feat |= CPUID::if_set(hwcap, ARM_hwcap_bit::SVE_bit, CPUFeature::Bit::SVE, allowed); } + const auto hwcap2 = auxval->second; + feat |= CPUID::if_set(hwcap2, ARM_hwcap2_bit::RNG_bit, CPUFeature::Bit::RNG, allowed); + return feat; } #else diff --git a/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.cpp b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.cpp index d5a77e6a765..0ea99b7bb75 100644 --- a/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.cpp +++ b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.cpp @@ -32,6 +32,8 @@ std::string CPUFeature::to_string() const { return "armv8sm3"; case CPUFeature::Bit::SM4: return "armv8sm4"; + case CPUFeature::Bit::RNG: + return "armv8rng"; } throw Invalid_State("CPUFeature invalid bit"); } @@ -59,6 +61,8 @@ std::optional CPUFeature::from_string(std::string_view tok) { return CPUFeature::Bit::SM3; } else if(tok == "armv8sm4" || tok == "arm_sm4") { return CPUFeature::Bit::SM4; + } else if(tok == "armv8rng") { + return CPUFeature::Bit::RNG; } else { return {}; } diff --git a/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.h b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.h index eb165489a79..851c0cef595 100644 --- a/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.h +++ b/src/lib/utils/cpuid/cpuid_aarch64/cpuid_features.h @@ -28,6 +28,7 @@ class BOTAN_TEST_API CPUFeature { SHA2_512 = (1U << 21), SM3 = (1U << 22), SM4 = (1U << 23), + RNG = (1U << 24), SIMD_4X32 = NEON, HW_AES = AES, diff --git a/src/lib/utils/isa_extn.h b/src/lib/utils/isa_extn.h index e78564fa70a..31ded225ef0 100644 --- a/src/lib/utils/isa_extn.h +++ b/src/lib/utils/isa_extn.h @@ -53,6 +53,7 @@ #define BOTAN_FN_ISA_SHA2 BOTAN_FUNC_ISA("+crypto+sha2") #define BOTAN_FN_ISA_SM4 BOTAN_FUNC_ISA("arch=armv8.2-a+sm4") #define BOTAN_FN_ISA_SHA512 BOTAN_FUNC_ISA("arch=armv8.2-a+sha3") + #define BOTAN_FN_ISA_RNG BOTAN_FUNC_ISA("arch=armv8.5-a+rng") #endif