58 static int get_drng_support()
60 thread_local int drng_features = -1;
63 if (drng_features == -1)
67 if (ccf::pal::is_intel_cpu())
71 ccf::pal::cpuid(&info, 1, 0);
73 if ((info.
ecx & 0x40000000) == 0x40000000)
78 if ((info.
ebx & 0x40000) == 0x40000)
86 static bool rdrand16_step(uint16_t* rand)
92 asm volatile(
"rdrand %0" :
"=r"(*rand),
"=@ccc"(ok));
96 static bool rdrand32_step(uint32_t* rand)
99 asm volatile(
"rdrand %0" :
"=r"(*rand),
"=@ccc"(ok));
103 static bool rdrand64_step(uint64_t* rand)
106 asm volatile(
"rdrand %0" :
"=r"(*rand),
"=@ccc"(ok));
110 static int rdrand16_retry(
unsigned int retries, uint16_t* rand)
112 unsigned int count = 0;
114 while (count <= retries)
116 if (rdrand16_step(rand))
124 static int rdrand32_retry(
unsigned int retries, uint32_t* rand)
126 unsigned int count = 0;
128 while (count <= retries)
130 if (rdrand32_step(rand))
139 static int rdrand64_retry(
unsigned int retries, uint64_t* rand)
141 unsigned int count = 0;
143 while (count <= retries)
145 if (rdrand64_step(rand))
154 static unsigned int rdrand_get_bytes(
unsigned int n,
unsigned char* dest)
156 unsigned char *headstart, *tailstart =
nullptr;
157 uint64_t* blockstart;
158 unsigned int count, ltail, lhead, lblock;
159 uint64_t i, temprand;
164 if (((uint64_t)headstart % (uint64_t)8) == 0)
166 blockstart = (uint64_t*)headstart;
173 (uint64_t*)(((uint64_t)headstart & ~(uint64_t)7) + (uint64_t)8);
174 lhead = (
unsigned int)((uint64_t)blockstart - (uint64_t)headstart);
176 ((n - lhead) & ~(
unsigned int)7);
182 ltail = n - lblock - lhead;
190 tailstart = (
unsigned char*)((uint64_t)blockstart + (uint64_t)lblock);
197 memcpy(headstart, &temprand, lhead);
201 for (i = 0; i < count; ++i, ++blockstart)
204 return i * 8 + lhead;
211 return count * 8 + lhead;
212 memcpy(tailstart, &temprand, ltail);
220 static bool rdseed16_step(uint16_t* seed)
223 asm volatile(
"rdseed %0" :
"=r"(*seed),
"=@ccc"(ok));
227 static bool rdseed32_step(uint32_t* seed)
230 asm volatile(
"rdseed %0" :
"=r"(*seed),
"=@ccc"(ok));
234 static bool rdseed64_step(uint64_t* seed)
237 asm volatile(
"rdseed %0" :
"=r"(*seed),
"=@ccc"(ok));
245 throw std::logic_error(
"No support for RDRAND / RDSEED on this CPU.");
252 std::vector<uint8_t>
random(
size_t len)
override
254 std::vector<uint8_t> buf(len);
256 if (rdrand_get_bytes(buf.size(), buf.data()) < buf.size())
257 throw std::logic_error(
"Couldn't create random data");
268 uint64_t len =
sizeof(uint64_t);
270 if (rdrand_get_bytes(len,
reinterpret_cast<unsigned char*
>(&rnd)) < len)
272 throw std::logic_error(
"Couldn't create random data");
282 void random(
unsigned char* data,
size_t len)
override
284 if (rdrand_get_bytes(len, data) < len)
285 throw std::logic_error(
"Couldn't create random data");
288 static int rng(
void*,
unsigned char* output,
size_t len)
290 if (rdrand_get_bytes(len, output) < len)
291 throw std::logic_error(
"Couldn't create random data");