mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
Add support for RNDR/RNDRRS for aarch64 on Linux
This checks whether the ARMv8.5 extensions RNDR and RNDRRS are available and uses them for random entropy purposes. They are functionally identical to the x86 RDRAND/RDSEED extensions and are used in a similar manner.
This commit is contained in:
parent
adc41cf3b2
commit
aee5404e02
1 changed files with 73 additions and 0 deletions
|
@ -40,6 +40,9 @@
|
|||
#ifdef HAVE_SYSCTL_ARND
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#if defined(HAVE_STRONG_GETAUXVAL) && defined(__aarch64__)
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
[[noreturn]] static void RandFailure()
|
||||
{
|
||||
|
@ -175,6 +178,62 @@ static uint64_t GetRdSeed() noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__) && defined(HWCAP2_RNG)
|
||||
|
||||
static bool g_rndr_supported = false;
|
||||
|
||||
static void InitHardwareRand()
|
||||
{
|
||||
if (getauxval(AT_HWCAP2) & HWCAP2_RNG) {
|
||||
g_rndr_supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportHardwareRand()
|
||||
{
|
||||
// This must be done in a separate function, as InitHardwareRand() may be indirectly called
|
||||
// from global constructors, before logging is initialized.
|
||||
if (g_rndr_supported) {
|
||||
LogPrintf("Using RNDR and RNDRRS as additional entropy sources\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** Read 64 bits of entropy using rndr.
|
||||
*
|
||||
* Must only be called when RNDR is supported.
|
||||
*/
|
||||
static uint64_t GetRNDR() noexcept
|
||||
{
|
||||
uint8_t ok;
|
||||
uint64_t r1;
|
||||
do {
|
||||
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/RNDR--Random-Number
|
||||
__asm__ volatile("mrs %0, s3_3_c2_c4_0; cset %w1, ne;"
|
||||
: "=r"(r1), "=r"(ok)::"cc");
|
||||
if (ok) break;
|
||||
__asm__ volatile("yield");
|
||||
} while (true);
|
||||
return r1;
|
||||
}
|
||||
|
||||
/** Read 64 bits of entropy using rndrrs.
|
||||
*
|
||||
* Must only be called when RNDRRS is supported.
|
||||
*/
|
||||
static uint64_t GetRNDRRS() noexcept
|
||||
{
|
||||
uint8_t ok;
|
||||
uint64_t r1;
|
||||
do {
|
||||
// https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/RNDRRS--Reseeded-Random-Number
|
||||
__asm__ volatile("mrs %0, s3_3_c2_c4_1; cset %w1, ne;"
|
||||
: "=r"(r1), "=r"(ok)::"cc");
|
||||
if (ok) break;
|
||||
__asm__ volatile("yield");
|
||||
} while (true);
|
||||
return r1;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Access to other hardware random number generators could be added here later,
|
||||
* assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
|
||||
|
@ -193,6 +252,12 @@ static void SeedHardwareFast(CSHA512& hasher) noexcept {
|
|||
hasher.Write((const unsigned char*)&out, sizeof(out));
|
||||
return;
|
||||
}
|
||||
#elif defined(__aarch64__) && defined(HWCAP2_RNG)
|
||||
if (g_rndr_supported) {
|
||||
uint64_t out = GetRNDR();
|
||||
hasher.Write((const unsigned char*)&out, sizeof(out));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -218,6 +283,14 @@ static void SeedHardwareSlow(CSHA512& hasher) noexcept {
|
|||
}
|
||||
return;
|
||||
}
|
||||
#elif defined(__aarch64__) && defined(HWCAP2_RNG)
|
||||
if (g_rndr_supported) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
uint64_t out = GetRNDRRS();
|
||||
hasher.Write((const unsigned char*)&out, sizeof(out));
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue