Read 64 bits of entropy using rdseed. * * Must only be called when RdSeed is supported. */
| 143 | * Must only be called when RdSeed is supported. |
| 144 | */ |
| 145 | static uint64_t GetRdSeed() noexcept |
| 146 | { |
| 147 | // RdSeed may fail when the HW RNG is overloaded. Loop indefinitely until enough entropy is gathered, |
| 148 | // but pause after every failure. |
| 149 | #ifdef __i386__ |
| 150 | uint8_t ok; |
| 151 | uint32_t r1, r2; |
| 152 | do { |
| 153 | __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %eax |
| 154 | if (ok) break; |
| 155 | __asm__ volatile ("pause"); |
| 156 | } while(true); |
| 157 | do { |
| 158 | __asm__ volatile (".byte 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r2), "=q"(ok) :: "cc"); // rdseed %eax |
| 159 | if (ok) break; |
| 160 | __asm__ volatile ("pause"); |
| 161 | } while(true); |
| 162 | return (((uint64_t)r2) << 32) | r1; |
| 163 | #elif defined(__x86_64__) || defined(__amd64__) |
| 164 | uint8_t ok; |
| 165 | uint64_t r1; |
| 166 | do { |
| 167 | __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" : "=a"(r1), "=q"(ok) :: "cc"); // rdseed %rax |
| 168 | if (ok) break; |
| 169 | __asm__ volatile ("pause"); |
| 170 | } while(true); |
| 171 | return r1; |
| 172 | #else |
| 173 | #error "RdSeed is only supported on x86 and x86_64" |
| 174 | #endif |
| 175 | } |
| 176 | |
| 177 | #else |
| 178 | /* Access to other hardware random number generators could be added here later, |