2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <linux/random.h>
29 #ifdef HAVE_SYS_AUXV_H
36 #include "random-util.h"
37 #include "time-util.h"
39 int dev_urandom(void *p, size_t n) {
40 static int have_syscall = -1;
42 _cleanup_close_ int fd = -1;
45 /* Gathers some randomness from the kernel. This call will
46 * never block, and will always return some data from the
47 * kernel, regardless if the random pool is fully initialized
48 * or not. It thus makes no guarantee for the quality of the
49 * returned entropy, but is good enough for our usual usecases
50 * of seeding the hash functions for hashtable */
52 /* Use the getrandom() syscall unless we know we don't have
53 * it, or when the requested size is too large for it. */
54 if (have_syscall != 0 || (size_t) (int) n != n) {
55 r = getrandom(p, n, GRND_NONBLOCK);
63 /* we lack the syscall, continue with
64 * reading from /dev/urandom */
66 else if (errno == EAGAIN)
67 /* not enough entropy for now. Let's
68 * remember to use the syscall the
69 * next time, again, but also read
70 * from /dev/urandom for now, which
71 * doesn't care about the current
72 * amount of entropy. */
81 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
83 return errno == ENOENT ? -ENOSYS : -errno;
85 return loop_read_exact(fd, p, n, true);
88 void initialize_srand(void) {
89 static bool srand_called = false;
91 #ifdef HAVE_SYS_AUXV_H
98 #ifdef HAVE_SYS_AUXV_H
99 /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the
100 * pseudo-random generator. It's better than nothing... */
102 auxv = (void*) getauxval(AT_RANDOM);
104 assert_cc(sizeof(x) < 16);
105 memcpy(&x, auxv, sizeof(x));
111 x ^= (unsigned) now(CLOCK_REALTIME);
112 x ^= (unsigned) gettid();
118 void random_bytes(void *p, size_t n) {
122 r = dev_urandom(p, n);
126 /* If some idiot made /dev/urandom unavailable to us, he'll
127 * get a PRNG instead. */
131 for (q = p; q < (uint8_t*) p + n; q ++)