15#include <sys/socket.h>
16#include <netinet/in.h>
21#include <sys/resource.h>
23#include <linux/random.h>
24#include <sys/syscall.h>
25#include <sys/utsname.h>
26#if defined (__i386__) || defined (__x86_64__)
27# include <x86intrin.h>
33getrandom (
void *buffer,
size_t count,
unsigned flags)
36 const long ret = syscall (__NR_getrandom, buffer, count, flags);
40 FILE *file =
fopen (
"/dev/urandom",
"r");
43 const size_t l =
fread (buffer, 1, count, file);
53hash_getrandom (KeccakRng &pool)
58 flags |= GRND_NONBLOCK;
60 int l = getrandom (buffer,
sizeof (buffer), flags);
63 pool.xor_seed (buffer, l /
sizeof (buffer[0]));
69template<
class Data>
static void
70hash_anything (KeccakRng &pool,
const Data &data)
75 if (
sizeof (Data) <
sizeof (
uint64_t))
78 memcpy (&dummy, &data,
sizeof (Data));
82 pool.xor_seed (d64, len /
sizeof (d64[0]));
86hash_macs (KeccakRng &pool)
89 int sockfd =
socket (AF_INET, SOCK_DGRAM, 0);
95 for (
size_t j = 0; j <= 1 || ret >= 0; j++)
97 struct ifreq iftmp = { { { 0 }, }, };
98 iftmp.ifr_ifindex = j;
99 ret =
ioctl (sockfd, SIOCGIFNAME, &iftmp);
102 if (!devices.empty())
104 devices += iftmp.ifr_name;
106 if (ioctl (sockfd, SIOCGIFHWADDR, &iftmp) >= 0)
109 devices +=
string_format (
"%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
113 char ifcbuffer[8192] = { 0, };
115 ifc.ifc_len =
sizeof (ifcbuffer);
116 ifc.ifc_buf = ifcbuffer;
117 ret =
ioctl (sockfd, SIOCGIFCONF, &ifc);
118 for (
size_t i = 0; ret >= 0 && i < ifc.ifc_len /
sizeof (
struct ifreq); i++)
120 const struct ifreq *iface = &ifc.ifc_req[i];
121 if (!devices.empty())
123 devices += iface->ifr_name;
125 const uint8_t *addr = (
const uint8_t*) &((
struct sockaddr_in*) &iface->ifr_addr)->sin_addr;
126 devices +=
string_format (
"%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
128 if (ioctl (sockfd, SIOCGIFHWADDR, iface) >= 0)
131 devices +=
string_format (
"%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
135 devices.resize (((devices.size() + 7) / 8) * 8);
136 pool.xor_seed ((
const uint64_t*) devices.data(), devices.size() / 8);
138 return !devices.empty();
142hash_stat (KeccakRng &pool,
const char *filename)
148 if (stat (filename, &s.stat) == 0)
150 pool.xor_seed ((
const uint64_t*) &s.stat, sizeof (s.stat) / sizeof (uint64_t));
158hash_file (KeccakRng &pool,
const char *filename,
const size_t maxbytes = 16384)
160 FILE *file =
fopen (filename,
"r");
164 const size_t l =
fread (buffer,
sizeof (buffer[0]),
sizeof (buffer) /
sizeof (buffer[0]), file);
168 pool.xor_seed (buffer, l);
176static bool __attribute__ ((__unused__))
177hash_glob (KeccakRng &pool,
const char *fileglob,
const size_t maxbytes = 16384)
179 glob_t globbuf = { 0, };
180 glob (fileglob, GLOB_NOSORT, NULL, &globbuf);
181 bool success =
false;
182 for (
size_t i = globbuf.gl_offs; i < globbuf.gl_pathc; i++)
183 success |= hash_file (pool, globbuf.gl_pathv[i], maxbytes);
190#ifdef CLOCK_PROCESS_CPUTIME_ID
193#if defined (__i386__) || defined (__x86_64__)
198static void __attribute__ ((__noinline__))
199hash_time (HashStamp *hstamp)
203#ifdef CLOCK_PROCESS_CPUTIME_ID
207 hstamp->tcpu = ts.tv_sec *
uint64_t (1000000000) + ts.tv_nsec;
210#if defined (__i386__) || defined (__x86_64__)
211 hstamp->tsc = __rdtsc();
216hash_cpu_usage (KeccakRng &pool)
221 struct rusage rusage;
227 u.clk =
times (&u.tms);
228 pool.xor_seed (u.ui64, sizeof (u.ui64) / sizeof (u.ui64[0]));
232hash_sys_structs (KeccakRng &pool)
241 SysStructs sst = { 0, };
244 pool.xor_seed ((
uint64*) &sst,
sizeof (sst) /
sizeof (
uint64));
250#if defined (__i386__) || defined (__x86_64__)
251 if (strstr (
cpu_info().c_str(),
" rdrand"))
253 __asm__ __volatile__ (
"rdrand %0" :
"=r" (u[i]));
258 u[i] = pcg_hash64 ((
const uint8*) &d,
sizeof (d), 0xeaeaeaea113377ccULL);
270 u[i] = uint64_t (arc4random()) << 32;
273 u[i] |= arc4random();
278runtime_entropy (KeccakRng &pool)
280 HashStamp hash_stamps[64] = { { 0 }, };
281 HashStamp *stamp = &hash_stamps[0];
286 hash_time (stamp++); hash_cpu_usage (pool);
288 hash_time (stamp++); get_rdrand (uintp, 8); uintp += 8;
289 hash_time (stamp++); get_arc4random (uintp, 8); uintp += 8;
290 hash_time (stamp++); *uintp++ = this_thread_gettid();
291 hash_time (stamp++); *uintp++ =
getuid();
292 hash_time (stamp++); *uintp++ =
geteuid();
293 hash_time (stamp++); *uintp++ =
getgid();
294 hash_time (stamp++); *uintp++ =
getegid();
295 hash_time (stamp++); *uintp++ =
getpid();
296 hash_time (stamp++); *uintp++ =
getsid (0);
298 hash_time (stamp++); *uintp++ = ppid =
getppid();
299 hash_time (stamp++); *uintp++ =
getsid (ppid);
300 hash_time (stamp++); *uintp++ =
getpgrp();
301 hash_time (stamp++); *uintp++ =
tcgetpgrp (0);
302 hash_time (stamp++); hash_getrandom (pool);
308 String compiletime = __DATE__ __TIME__ __FILE__ __TIMESTAMP__;
309 hash_time (stamp++); *uintp++ = fnv1a_consthash64 (compiletime.c_str());
310 hash_time (stamp++); *uintp++ =
size_t (compiletime.data());
312 hash_time (stamp++); *uintp++ =
size_t (&dummy);
313 hash_time (stamp++); *uintp++ =
size_t (
"PATH");
314 hash_time (stamp++); *uintp++ =
size_t (getenv (
"PATH"));
315 hash_time (stamp++); *uintp++ =
size_t (&stamp);
316 hash_time (stamp++); *uintp++ =
size_t (&runtime_entropy);
317 hash_time (stamp++); *uintp++ =
size_t (&::fopen);
318 hash_time (stamp++); *uintp++ =
size_t (&std::string::npos);
319 hash_time (stamp++); *uintp++ = fnv1a_consthash64 (
cpu_info().c_str());
320 hash_time (stamp++); hash_sys_structs (pool);
322 hash_time (stamp++); hash_cpu_usage (pool);
324 ASE_ASSERT_RETURN (uintp <= &uint_array[
sizeof (uint_array) /
sizeof (uint_array[0])]);
325 pool.xor_seed (&uint_array[0], uintp - &uint_array[0]);
327 ASE_ASSERT_RETURN (stamp <= &hash_stamps[
sizeof (hash_stamps) /
sizeof (hash_stamps[0])]);
328 pool.xor_seed ((uint64_t*) &hash_stamps[0], (stamp - &hash_stamps[0]) *
sizeof (hash_stamps[0]) /
sizeof (uint64_t));
333system_entropy (KeccakRng &pool)
335 HashStamp hash_stamps[64] = { { 0 }, };
336 HashStamp *stamp = &hash_stamps[0];
343 hash_time (stamp++); hash_cpu_usage (pool);
344 hash_time (stamp++); hash_file (pool,
"/proc/sys/kernel/random/boot_id");
345 hash_time (stamp++); hash_file (pool,
"/proc/version");
346 hash_time (stamp++); hash_file (pool,
"/proc/cpuinfo");
347 hash_time (stamp++); hash_file (pool,
"/proc/devices");
348 hash_time (stamp++); hash_file (pool,
"/proc/meminfo");
349 hash_time (stamp++); hash_file (pool,
"/proc/buddyinfo");
350 hash_time (stamp++); hash_file (pool,
"/proc/diskstats");
351 hash_time (stamp++); hash_file (pool,
"/proc/1/stat");
352 hash_time (stamp++); hash_file (pool,
"/proc/1/sched");
353 hash_time (stamp++); hash_file (pool,
"/proc/1/schedstat");
354 hash_time (stamp++); hash_file (pool,
"/proc/self/stat");
355 hash_time (stamp++); hash_file (pool,
"/proc/self/sched");
356 hash_time (stamp++); hash_file (pool,
"/proc/self/schedstat");
357 hash_time (stamp++); hash_macs (pool);
359 hash_time (stamp++); hash_file (pool,
"/proc/uptime");
360 hash_time (stamp++); hash_file (pool,
"/proc/user_beancounters");
361 hash_time (stamp++); hash_file (pool,
"/proc/driver/rtc");
362 hash_time (stamp++); hash_stat (pool,
"/var/log/syslog");
363 hash_time (stamp++); hash_stat (pool,
"/var/log/auth.log");
364 hash_time (stamp++); hash_stat (pool,
"/var/tmp");
365 hash_time (stamp++); hash_stat (pool,
"/tmp");
366 hash_time (stamp++); hash_stat (pool,
"/dev");
367 hash_time (stamp++); hash_stat (pool,
"/var/lib/ntp/ntp.drift");
368 hash_time (stamp++); hash_stat (pool,
"/var/run/utmp");
369 hash_time (stamp++); hash_stat (pool,
"/var/log/wtmp");
370 hash_time (stamp++); hash_stat (pool,
"/sbin/init");
371 hash_time (stamp++); hash_stat (pool,
"/var/spool");
372 hash_time (stamp++); hash_stat (pool,
"/var/spool/cron");
373 hash_time (stamp++); hash_stat (pool,
"/var/spool/anacron");
374 hash_time (stamp++); hash_file (pool,
"/dev/urandom", 400);
375 hash_time (stamp++); hash_file (pool,
"/proc/sys/kernel/random/uuid");
376 hash_time (stamp++); hash_file (pool,
"/proc/schedstat");
377 hash_time (stamp++); hash_file (pool,
"/proc/sched_debug");
378 hash_time (stamp++); hash_file (pool,
"/proc/fairsched");
379 hash_time (stamp++); hash_file (pool,
"/proc/interrupts");
380 hash_time (stamp++); hash_file (pool,
"/proc/loadavg");
381 hash_time (stamp++); hash_file (pool,
"/proc/softirqs");
382 hash_time (stamp++); hash_file (pool,
"/proc/stat");
383 hash_time (stamp++); hash_file (pool,
"/proc/net/fib_triestat");
384 hash_time (stamp++); hash_file (pool,
"/proc/net/netstat");
385 hash_time (stamp++); hash_file (pool,
"/proc/net/dev");
386 hash_time (stamp++); hash_file (pool,
"/proc/vz/vestat");
387 hash_time (stamp++); hash_cpu_usage (pool);
389 ASE_ASSERT_RETURN (uintp <= &uint_array[
sizeof (uint_array) /
sizeof (uint_array[0])]);
390 pool.xor_seed (&uint_array[0], uintp - &uint_array[0]);
392 ASE_ASSERT_RETURN (stamp <= &hash_stamps[
sizeof (hash_stamps) /
sizeof (hash_stamps[0])]);
393 pool.xor_seed ((uint64_t*) &hash_stamps[0], (stamp - &hash_stamps[0]) *
sizeof (hash_stamps[0]) /
sizeof (uint64_t));
411 runtime_entropy (pool);
412 for (
size_t i = 0; i < n; i++)
429 hash_cpu_usage (pool);
430 runtime_entropy (pool);
431 system_entropy (pool);
432 hash_cpu_usage (pool);
433 for (
size_t i = 0; i < n; i++)
#define ASE_ASSERT_RETURN(expr,...)
Return from the current function if expr evaluates to false and issue an assertion warning.
The Anklang C++ API namespace.
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
String cpu_info()
Retrieve string identifying the runtime CPU type.
void collect_runtime_entropy(uint64 *data, size_t n)
Collect entropy from the current process, usually quicker than collect_system_entropy().
uint8_t uint8
An 8-bit unsigned integer.
uint64 timestamp_benchmark()
Returns benchmark timestamp in nano-seconds, clock starts around program startup.
void collect_system_entropy(uint64 *data, size_t n)
Collect entropy from system devices, like interrupt counters, clocks and random devices.
std::string String
Convenience alias for std::string.
uint32_t uint
Provide 'uint' as convenience type.
uint64 timestamp_startup()
Provides the timestamp_realtime() value from program startup.
uint64 timestamp_realtime()
Return the current time as uint64 in µseconds.