]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/random-util.c
Added slovak translation (#6191)
[thirdparty/systemd.git] / src / basic / random-util.c
CommitLineData
3df3e884
RC
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
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.
10
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.
15
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/>.
18***/
19
11c3a366 20#include <elf.h>
3df3e884 21#include <errno.h>
3df3e884 22#include <fcntl.h>
11c3a366
TA
23#include <stdbool.h>
24#include <stdlib.h>
25#include <sys/time.h>
3ffd4af2
LP
26#include <linux/random.h>
27#include <stdint.h>
11c3a366 28
a67dab34 29#ifdef HAVE_SYS_AUXV_H
5224c2c7
ZJS
30# include <sys/auxv.h>
31#endif
32
33#ifdef USE_SYS_RANDOM_H
34# include <sys/random.h>
35#else
36# include <linux/random.h>
a67dab34 37#endif
3df3e884 38
3ffd4af2 39#include "fd-util.h"
c004493c 40#include "io-util.h"
3ffd4af2 41#include "missing.h"
3df3e884
RC
42#include "random-util.h"
43#include "time-util.h"
3df3e884
RC
44
45int dev_urandom(void *p, size_t n) {
46 static int have_syscall = -1;
47
48 _cleanup_close_ int fd = -1;
49 int r;
50
51 /* Gathers some randomness from the kernel. This call will
52 * never block, and will always return some data from the
53 * kernel, regardless if the random pool is fully initialized
54 * or not. It thus makes no guarantee for the quality of the
f045931a 55 * returned entropy, but is good enough for our usual usecases
3df3e884
RC
56 * of seeding the hash functions for hashtable */
57
58 /* Use the getrandom() syscall unless we know we don't have
59 * it, or when the requested size is too large for it. */
60 if (have_syscall != 0 || (size_t) (int) n != n) {
61 r = getrandom(p, n, GRND_NONBLOCK);
62 if (r == (int) n) {
63 have_syscall = true;
64 return 0;
65 }
66
67 if (r < 0) {
68 if (errno == ENOSYS)
69 /* we lack the syscall, continue with
70 * reading from /dev/urandom */
71 have_syscall = false;
72 else if (errno == EAGAIN)
73 /* not enough entropy for now. Let's
74 * remember to use the syscall the
75 * next time, again, but also read
76 * from /dev/urandom for now, which
77 * doesn't care about the current
78 * amount of entropy. */
79 have_syscall = true;
80 else
81 return -errno;
82 } else
83 /* too short read? */
84 return -ENODATA;
85 }
86
87 fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
88 if (fd < 0)
89 return errno == ENOENT ? -ENOSYS : -errno;
90
91 return loop_read_exact(fd, p, n, true);
92}
93
94void initialize_srand(void) {
95 static bool srand_called = false;
96 unsigned x;
97#ifdef HAVE_SYS_AUXV_H
98 void *auxv;
99#endif
100
101 if (srand_called)
102 return;
103
3df3e884 104#ifdef HAVE_SYS_AUXV_H
ad6b1fa2
LP
105 /* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed the
106 * pseudo-random generator. It's better than nothing... */
3df3e884
RC
107
108 auxv = (void*) getauxval(AT_RANDOM);
ad6b1fa2
LP
109 if (auxv) {
110 assert_cc(sizeof(x) < 16);
111 memcpy(&x, auxv, sizeof(x));
112 } else
3df3e884 113#endif
ad6b1fa2
LP
114 x = 0;
115
3df3e884
RC
116
117 x ^= (unsigned) now(CLOCK_REALTIME);
118 x ^= (unsigned) gettid();
119
120 srand(x);
121 srand_called = true;
122}
123
124void random_bytes(void *p, size_t n) {
125 uint8_t *q;
126 int r;
127
128 r = dev_urandom(p, n);
129 if (r >= 0)
130 return;
131
132 /* If some idiot made /dev/urandom unavailable to us, he'll
133 * get a PRNG instead. */
134
135 initialize_srand();
136
137 for (q = p; q < (uint8_t*) p + n; q ++)
138 *q = rand();
139}