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.