/* vi: set sw=4 ts=4: * * Copyright (C) 2015 Christian Hohnstaedt. * * All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include "func.h" #include "entropy.h" #include "openssl_compat.h" #ifdef WIN32 /* On Windows O_NONBLOCK is an unknown concept :-) * We don't need it anyway on that platform .... */ #define O_NONBLOCK 0 #endif #undef DEBUG_ENTROPY #define pool_siz (sizeof(pool)/sizeof(pool[0])) unsigned char Entropy::pool[512]; unsigned Entropy::pool_pos = 0; QTime Entropy::timer; unsigned Entropy::seed_strength = 0; void Entropy::add(int rand) { unsigned char entropy = (rand ^ timer.elapsed()) & 0xff; pool[pool_pos++ % pool_siz] = entropy; } void Entropy::add_buf(const unsigned char *buf, int buflen) { RAND_seed(buf, buflen); seed_strength += buflen; } int Entropy::get(unsigned char *buf, int num) { seed_rng(); return RAND_bytes(buf, num); } void Entropy::seed_rng() { if (pool_pos > pool_siz) pool_pos = pool_siz; RAND_seed(pool, pool_pos); seed_strength += pool_pos; #ifdef WIN32 if (seed_strength < 16) { RAND_poll(); seed_strength += 8; } #else random_from_file("/dev/random", 64); random_from_file("/dev/hwrng", 64); #endif #ifdef DEBUG_ENTROPY fprintf(stderr, "Seeding %d bytes:", pool_pos); for (unsigned i=0; i 0;) { int len = read(fd, buf, amount > sizeof buf ? sizeof buf : amount); if (len > 0) { RAND_seed(buf, len); seed_strength += len / weakness; amount -= len; sum += len; } if (len == -1) { if (errno != EWOULDBLOCK) qWarning("Error '%s' while reading '%s'\n", strerror(errno), file); len = 0; } if (len == 0) break; } close(fd); #ifdef DEBUG_ENTROPY fprintf(stderr, "Entropy from file '%s' = %d bytes\n", file, sum); #endif return sum; } unsigned Entropy::strength() { return seed_strength; } Entropy::Entropy() { timer.start(); rnd = getUserSettingsDir() + QDir::separator() + ".rnd"; random_from_file(rnd, 1024, 128); QFile::remove(rnd); // don't use it again } Entropy::~Entropy() { QFile f(rnd); if (f.open(QIODevice::ReadWrite)) { unsigned char buf[1024]; seed_rng(); f.setPermissions(QFile::ReadOwner|QFile::WriteOwner); RAND_bytes(buf, sizeof buf); f.write((char*)buf, sizeof buf); f.close(); } #ifdef DEBUG_ENTROPY fprintf(stderr, "Seed strength: %d\n", seed_strength); #endif }