aboutsummaryrefslogtreecommitdiff
path: root/src/random.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/random.cpp')
-rw-r--r--src/random.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/random.cpp b/src/random.cpp
index 9bd8ff9f1a..ce4266a567 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -38,6 +38,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()
{
@@ -173,6 +176,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).
@@ -191,6 +250,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
}
@@ -216,6 +281,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
}