util: introduce new dev_urandom() call that is like random_bytes() but doesn't fall back to PRNG

This commit is contained in:
Lennart Poettering 2014-01-28 13:07:28 +01:00
parent 7d5dd5e0cf
commit b89446bb33
2 changed files with 26 additions and 13 deletions

View file

@ -2255,25 +2255,37 @@ char* dirname_malloc(const char *path) {
return dir;
}
void random_bytes(void *p, size_t n) {
static bool srand_called = false;
int dev_urandom(void *p, size_t n) {
_cleanup_close_ int fd;
ssize_t k;
uint8_t *q;
fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
goto fallback;
return errno == ENOENT ? -ENOSYS : -errno;
k = loop_read(fd, p, n, true);
if (k < 0 || (size_t) k != n)
goto fallback;
if (k < 0)
return (int) k;
if ((size_t) k != n)
return -EIO;
return;
return 0;
}
fallback:
void random_bytes(void *p, size_t n) {
static bool srand_called = false;
uint8_t *q;
int r;
r = dev_urandom(p, n);
if (r >= 0)
return;
/* If some idiot made /dev/urandom unavailable to us, he'll
* get a PRNG instead. */
if (!srand_called) {
unsigned x = 0;
#ifdef HAVE_SYS_AUXV_H
/* The kernel provides us with a bit of entropy in
@ -2285,16 +2297,16 @@ fallback:
auxv = (void*) getauxval(AT_RANDOM);
if (auxv)
srand(*(unsigned*) auxv);
else
x ^= *(unsigned*) auxv;
#endif
srand(time(NULL) + gettid());
x ^= (unsigned) now(CLOCK_REALTIME);
x ^= (unsigned) gettid();
srand(x);
srand_called = true;
}
/* If some idiot made /dev/urandom unavailable to us, he'll
* get a PRNG instead. */
for (q = p; q < (uint8_t*) p + n; q ++)
*q = rand();
}

View file

@ -272,6 +272,7 @@ int make_stdio(int fd);
int make_null_stdio(void);
int make_console_stdio(void);
int dev_urandom(void *p, size_t n);
void random_bytes(void *p, size_t n);
static inline uint64_t random_u64(void) {