40
40
#ifdef HAVE_SYSCTL_ARND
41
41
#include < sys/sysctl.h>
42
42
#endif
43
+ #if defined(HAVE_STRONG_GETAUXVAL) && defined(__aarch64__)
44
+ #include < sys/auxv.h>
45
+ #endif
43
46
44
47
[[noreturn]] static void RandFailure ()
45
48
{
@@ -175,6 +178,62 @@ static uint64_t GetRdSeed() noexcept
175
178
#endif
176
179
}
177
180
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
+
178
237
#else
179
238
/* Access to other hardware random number generators could be added here later,
180
239
* assuming it is sufficiently fast (in the order of a few hundred CPU cycles).
@@ -193,6 +252,12 @@ static void SeedHardwareFast(CSHA512& hasher) noexcept {
193
252
hasher.Write ((const unsigned char *)&out, sizeof (out));
194
253
return ;
195
254
}
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
+ }
196
261
#endif
197
262
}
198
263
@@ -218,6 +283,14 @@ static void SeedHardwareSlow(CSHA512& hasher) noexcept {
218
283
}
219
284
return ;
220
285
}
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
+ }
221
294
#endif
222
295
}
223
296
0 commit comments