#include #include #include #include #include #include #include #include "randomness.h" #include "notify.h" static int randomness_fd_ = -1; int randomness_init(const char *filename) { if (filename != NULL) { randomness_fd_ = open(filename, O_RDONLY); if (randomness_fd_ == -1) { NOTIFY_ERROR("%s('%s'):%s", "open", filename, strerror(errno)); return -1; } NOTIFY_DEBUG("reading randomness from '%s', fd:%d", filename, randomness_fd_); } else { if (randomness_fd_ != -1) { close(randomness_fd_); randomness_fd_ = -1; } srand48(time(NULL) ^ getpid()); NOTIFY_DEBUG("reading randomness from system PRNG"); } return 0; } /* Room for improvement: constrain bits of randomness consumed, based on #limit Also maybe read chunks of randomness at a time */ unsigned long randomness_upto_inclusive(unsigned long limit) { unsigned long randomness; if (limit == 0) return 0; if (randomness_fd_ != -1) { ssize_t len; do { len = read(randomness_fd_, &randomness, sizeof randomness); } while (len == -1 && (errno == EINTR || errno == EAGAIN)); if (len == sizeof randomness) { randomness %= limit + 1; NOTIFY_DEBUG("randomness:%lu", randomness); return randomness; } NOTIFY_ERROR("%s(%d, %zu):%zd:%s", "read", randomness_fd_, sizeof randomness, len, (len < 0) ? strerror(errno) : ( (len == 0) ? "EOF" : "not enough read" ) ); } /* fall back to pseudo-randomness if read failed */ randomness = mrand48(); randomness %= limit + 1; NOTIFY_DEBUG("randomness:%lu", randomness); return randomness; }