4040#ifdef HAVE_SYSCTL_ARND
4141#include < sys/sysctl.h>
4242#endif
43+ #if defined(HAVE_STRONG_GETAUXVAL) && defined(__aarch64__)
44+ #include < sys/auxv.h>
45+ #endif
4346
4447[[noreturn]] static void RandFailure ()
4548{
@@ -175,6 +178,62 @@ static uint64_t GetRdSeed() noexcept
175178#endif
176179}
177180
181+ #elif defined(__aarch64__) && defined(HWCAP2_RNG)
182+
183+ static bool g_rndr_supported = false ;
184+
185+ static void InitHardwareRand ()
186+ {
187+ if (getauxval (AT_HWCAP2) & HWCAP2_RNG) {
188+ g_rndr_supported = true ;
189+ }
190+ }
191+
192+ static void ReportHardwareRand ()
193+ {
194+ // This must be done in a separate function, as InitHardwareRand() may be indirectly called
195+ // from global constructors, before logging is initialized.
196+ if (g_rndr_supported) {
197+ LogPrintf (" Using RNDR and RNDRRS as additional entropy sources\n " );
198+ }
199+ }
200+
201+ /* * Read 64 bits of entropy using rndr.
202+ *
203+ * Must only be called when RNDR is supported.
204+ */
205+ static uint64_t GetRNDR () noexcept
206+ {
207+ uint8_t ok;
208+ uint64_t r1;
209+ do {
210+ // https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/RNDR--Random-Number
211+ __asm__ volatile (" mrs %0, s3_3_c2_c4_0; cset %w1, ne;"
212+ : " =r" (r1), " =r" (ok)::" cc" );
213+ if (ok) break ;
214+ __asm__ volatile (" yield" );
215+ } while (true );
216+ return r1;
217+ }
218+
219+ /* * Read 64 bits of entropy using rndrrs.
220+ *
221+ * Must only be called when RNDRRS is supported.
222+ */
223+ static uint64_t GetRNDRRS () noexcept
224+ {
225+ uint8_t ok;
226+ uint64_t r1;
227+ do {
228+ // https://developer.arm.com/documentation/ddi0601/2022-12/AArch64-Registers/RNDRRS--Reseeded-Random-Number
229+ __asm__ volatile (" mrs %0, s3_3_c2_c4_1; cset %w1, ne;"
230+ : " =r" (r1), " =r" (ok)::" cc" );
231+ if (ok) break ;
232+ __asm__ volatile (" yield" );
233+ } while (true );
234+ return r1;
235+ }
236+
178237#else
179238/* Access to other hardware random number generators could be added here later,
180239 * assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
@@ -193,6 +252,12 @@ static void SeedHardwareFast(CSHA512& hasher) noexcept {
193252 hasher.Write ((const unsigned char *)&out, sizeof (out));
194253 return ;
195254 }
255+ #elif defined(__aarch64__) && defined(HWCAP2_RNG)
256+ if (g_rndr_supported) {
257+ uint64_t out = GetRNDR ();
258+ hasher.Write ((const unsigned char *)&out, sizeof (out));
259+ return ;
260+ }
196261#endif
197262}
198263
@@ -218,6 +283,14 @@ static void SeedHardwareSlow(CSHA512& hasher) noexcept {
218283 }
219284 return ;
220285 }
286+ #elif defined(__aarch64__) && defined(HWCAP2_RNG)
287+ if (g_rndr_supported) {
288+ for (int i = 0 ; i < 4 ; ++i) {
289+ uint64_t out = GetRNDRRS ();
290+ hasher.Write ((const unsigned char *)&out, sizeof (out));
291+ }
292+ return ;
293+ }
221294#endif
222295}
223296
0 commit comments