]> git.ipfire.org Git - thirdparty/systemd.git/blob - docs/RANDOM_SEEDS.md
docs: place all our markdown docs in rough categories
[thirdparty/systemd.git] / docs / RANDOM_SEEDS.md
1 ---
2 title: Random Seeds
3 category: Concepts
4 ---
5
6 # Random Seeds
7
8 systemd can help in a number of ways with providing reliable, high quality
9 random numbers from early boot on.
10
11 ## Linux Kernel Entropy Pool
12
13 Today's computer systems require random number generators for numerous
14 cryptographic and other purposes. On Linux systems, the kernel's entropy pool
15 is typically used as high-quality source of random numbers. The kernel's
16 entropy pool combines various entropy inputs together, mixes them and provides
17 an API to userspace as well as to internal kernel subsystems to retrieve
18 it. This entropy pool needs to be initialized with a minimal level of entropy
19 before it can provide high quality, cryptographic random numbers to
20 applications. Until the entropy pool is fully initialized application requests
21 for high-quality random numbers cannot be fulfilled.
22
23 The Linux kernel provides three relevant userspace APIs to request random data
24 from the kernel's entropy pool:
25
26 * The [`getrandom()`](http://man7.org/linux/man-pages/man2/getrandom.2.html)
27 system call with its `flags` parameter set to 0. If invoked the calling
28 program will synchronously block until the random pool is fully initialized
29 and the requested bytes can be provided.
30
31 * The `getrandom()` system call with its `flags` parameter set to
32 `GRND_NONBLOCK`. If invoked the request for random bytes will fail if the
33 pool is not initialized yet.
34
35 * Reading from the
36 [`/dev/urandom`](http://man7.org/linux/man-pages/man4/urandom.4.html)
37 pseudo-device will always return random bytes immediately, even if the pool
38 is not initialized. The provided random bytes will be of low quality in this
39 case however. Moreover the kernel will log about all programs using this
40 interface in this state, and which thus potentially rely on an uninitialized
41 entropy pool.
42
43 (Strictly speaking there are more APIs, for example `/dev/random`, but these
44 should not be used by almost any application and hence aren't mentioned here.)
45
46 Note that the time it takes to initialize the random pool may differ between
47 systems. If local hardware random number generators are available,
48 initialization is likely quick, but particularly in embedded and virtualized
49 environments available entropy is small and thus random pool initialization
50 might take a long time (up to tens of minutes!).
51
52 Modern hardware tends to come with a number of hardware random number
53 generators (hwrng), that may be used to relatively quickly fill up the entropy
54 pool. Specifically:
55
56 * All recent Intel and AMD CPUs provide the CPU opcode
57 [RDRAND](https://en.wikipedia.org/wiki/RdRand) to acquire random bytes. Linux
58 includes random bytes generated this way in its entropy pool, but didn't use
59 to credit entropy for it (i.e. data from this source wasn't considered good
60 enough to consider the entropy pool properly filled even though it was
61 used). This has changed recently however, and most big distributions have
62 turned on the `CONFIG_RANDOM_TRUST_CPU=y` kernel compile time option. This
63 means systems with CPUs supporting this opcode will be able to very quickly
64 reach the "pool filled" state.
65
66 * The TPM security chip that is available on all modern desktop systems has a
67 hwrng. It is also fed into the entropy pool, but generally not credited
68 entropy. You may use `rng_core.default_quality=1000` on the kernel command
69 line to change that, but note that this is a global setting affect all
70 hwrngs. (Yeah, that's weird.)
71
72 * Many Intel and AMD chipsets have hwrng chips. Their Linux drivers usually
73 don't credit entropy. (But there's `rng_core.default_quality=1000`, see
74 above.)
75
76 * Various embedded boards have hwrng chips. Some drivers automatically credit
77 entropy, others do not. Some WiFi chips appear to have hwrng sources too, and
78 they usually do not credit entropy for them.
79
80 * `virtio-rng` is used in virtualized environments and retrieves random data
81 from the VM host. It credits full entropy.
82
83 * The EFI firmware typically provides a RNG API. When transitioning from UEFI
84 to kernel mode Linux will query some random data through it, and feed it into
85 the pool, but not credit entropy to it. What kind of random source is behind
86 the EFI RNG API is often not entirely clear, but it hopefully is some kind of
87 hardware source.
88
89 If neither of these are available (in fact, even if they are), Linux generates
90 entropy from various non-hwrng sources in various subsystems, all of which
91 ultimately are rooted in IRQ noise, a very "slow" source of entropy, in
92 particular in virtualized environments.
93
94 ## `systemd`'s Use of Random Numbers
95
96 systemd is responsible for bringing up the OS. It generally runs as the first
97 userspace process the kernel invokes. Because of that it runs at a time where
98 the entropy pool is typically not yet initialized, and thus requests to acquire
99 random bytes will either be delayed, will fail or result in a noisy kernel log
100 message (see above).
101
102 Various other components run during early boot that require random bytes. For
103 example, initial RAM disks nowadays communicate with encrypted networks or
104 access encrypted storage which might need random numbers. systemd itself
105 requires random numbers as well, including for the following uses:
106
107 * systemd assigns 'invocation' UUIDs to all services it invokes that uniquely
108 identify each invocation. This is useful retain a global handle on a specific
109 service invocation and relate it to other data. For example, log data
110 collected by the journal usually includes the invocation UUID and thus the
111 runtime context the service manager maintains can be neatly matched up with
112 the log data a specific service invocation generated. systemd also
113 initializes `/etc/machine-id` with a randomized UUID. (systemd also makes use
114 of the randomized "boot id" the kernel exposes in
115 `/proc/sys/kernel/random/boot_id`). These UUIDs are exclusively Type 4 UUIDs,
116 i.e. randomly generated ones.
117
118 * systemd maintains various hash tables internally. In order to harden them
119 against [collision
120 attacks](https://rt.perl.org/Public/Bug/Display.html?CSRF_Token=165691af9ddaa95f653402f1b68de728)
121 they are seeded with random numbers.
122
123 * At various places systemd needs random bytes for temporary file name
124 generation, UID allocation randomization, and similar.
125
126 * systemd-resolved and systemd-networkd use random number generators to harden
127 the protocols they implement against packet forgery.
128
129 * systemd-udevd and systemd-nspawn can generate randomized MAC addresses for
130 network devices.
131
132 Note that these cases generally do not require a cryptographic-grade random
133 number generator, as most of these utilize random numbers to minimize risk of
134 collision and not to generate secret key material. However, they usually do
135 require "medium-grade" random data. For example: systemd's hash-maps are
136 reseeded if they grow beyond certain thresholds (and thus collisions are more
137 likely). This means they are generally fine with low-quality (even constant)
138 random numbers initially as long as they get better with time, so that
139 collision attacks are eventually thwarted as better, non-guessable seeds are
140 acquired.
141
142 ## Keeping `systemd'`s Demand on the Kernel Entropy Pool Minimal
143
144 Since most of systemd's own use of random numbers do not require
145 cryptographic-grade RNGs, it tries to avoid reading entropy from the kernel
146 entropy pool if possible. If it succeeds this has the benefit that there's no
147 need to delay the early boot process until entropy is available, and noisy
148 kernel log messages about early reading from `/dev/urandom` are avoided
149 too. Specifically:
150
151 1. When generating [Type 4
152 UUIDs](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_\(random\)),
153 systemd tries to use Intel's and AMD's RDRAND CPU opcode directly, if
154 available. While some doubt the quality and trustworthiness of the entropy
155 provided by these opcodes, they should be good enough for generating UUIDs,
156 if not key material (though, as mentioned, today's big distributions opted
157 to trust it for that too, now, see above — but we are not going to make that
158 decision for you, and for anything key material related will only use the
159 kernel's entropy pool). If RDRAND is not available or doesn't work, it will
160 use synchronous `getrandom()` as fallback, and `/dev/urandom` on old kernels
161 where that system call doesn't exist yet. This means on non-Intel/AMD
162 systems UUID generation will block on kernel entropy initialization.
163
164 2. For seeding hash tables, and all the other similar purposes systemd first
165 tries RDRAND, and if that's not available will try to use asynchronous
166 `getrandom()` (if the kernel doesn't support this system call,
167 `/dev/urandom` is used). This may fail too in case the pool is not
168 initialized yet, in which case it will fall back to glibc's internal rand()
169 calls, i.e. weak pseudo-random numbers. This should make sure we use good
170 random bytes if we can, but neither delay boot nor trigger noisy kernel log
171 messages during early boot for these use-cases.
172
173 ## `systemd`'s Support for Filling the Kernel Entropy Pool
174
175 systemd has various provisions to ensure the kernel entropy is filled during
176 boot, in order to ensure the entropy pool is filled up quickly.
177
178 1. When systemd's PID 1 detects it runs in a virtualized environment providing
179 the `virtio-rng` interface it will load the necessary kernel modules to make
180 use of it during earliest boot, if possible — much earlier than regular
181 kernel module loading done by `systemd-udevd.service`. This should ensure
182 that in VM environments the entropy pool is quickly filled, even before
183 systemd invokes the first service process — as long as the VM environment
184 provides virtualized RNG hardware (and VM environments really should!).
185
186 2. The
187 [`systemd-random-seed.service`](https://www.freedesktop.org/software/systemd/man/systemd-random-seed.service.html)
188 system service will load a random seed from `/var/lib/systemd/random-seed`
189 into the kernel entropy pool. By default it does not credit entropy for it
190 though, since the seed is — more often than not — not reset when 'golden'
191 master images of an OS are created, and thus replicated into every
192 installation. If OS image builders carefully reset the random seed file
193 before generating the image it should be safe to credit entropy, which can
194 be enabled by setting the `$SYSTEMD_RANDOM_SEED_CREDIT` environment variable
195 for the service to `1` (or even `force`, see man page). Note however, that
196 this service typically runs relatively late during early boot: long after
197 the initial RAM disk (`initrd`) completed, and after the `/var/` file system
198 became writable. This is usually too late for many applications, it is hence
199 not advised to rely exclusively on this functionality to seed the kernel's
200 entropy pool. Also note that this service synchronously waits until the
201 kernel's entropy pool is initialized before completing start-up. It may thus
202 be used by other services as synchronization point to order against, if they
203 require an initialized entropy pool to operate correctly.
204
205 3. The
206 [`systemd-boot`](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)
207 EFI boot loader included in systemd is able to maintain and provide a random
208 seed stored in the EFI System Partition (ESP) to the booted OS, which allows
209 booting up with a fully initialized entropy pool from earliest boot
210 on. During installation of the boot loader (or when invoking [`bootctl
211 random-seed`](https://www.freedesktop.org/software/systemd/man/bootctl.html#random-seed))
212 a seed file with an initial seed is placed in a file `/loader/random-seed`
213 in the ESP. In addition, an identically sized randomized EFI variable called
214 the the 'system token' is set, which is written to the machine's firmware
215 NVRAM. During boot, when `systemd-boot` finds both the random seed file and
216 the system token they are combined and hashed with SHA256 (in counter mode,
217 to generate sufficient data), to generate a new random seed file to store in
218 the ESP as well as a random seed to pass to the OS kernel. The new random
219 seed file for the ESP is then written to the ESP, ensuring this is completed
220 before the OS is invoked. Very early during initialization PID 1 will read
221 the random seed provided in the EFI variable and credit it fully to the
222 kernel's entropy pool.
223
224 This mechanism is able to safely provide an initialized entropy pool already
225 in the `initrd` and guarantees that different seeds are passed from the boot
226 loader to the OS on every boot (in a way that does not allow regeneration of
227 an old seed file from a new seed file). Moreover, when an OS image is
228 replicated between multiple images and the random seed is not reset, this
229 will still result in different random seeds being passed to the OS, as the
230 per-machine 'system token' is specific to the physical host, and not
231 included in OS disk images. If the 'system token' is properly initialized
232 and kept sufficiently secret it should not be possible to regenerate the
233 entropy pool of different machines, even if this seed is the only source of
234 entropy.
235
236 Note that the writes to the ESP needed to maintain the random seed should be
237 minimal. The size of the random seed file is directly derived from the Linux
238 kernel's entropy pool size, which defaults to 512 bytes. This means updating
239 the random seed in the ESP should be doable safely with a single sector
240 write (since hard-disk sectors typically happen to be 512 bytes long, too),
241 which should be safe even with FAT file system drivers built into
242 low-quality EFI firmwares.
243
244 As a special restriction: in virtualized environments PID 1 will refrain
245 from using this mechanism, for safety reasons. This is because on VM
246 environments the EFI variable space and the disk space is generally not
247 maintained physically separate (for example, `qemu` in EFI mode stores the
248 variables in the ESP itself). The robustness towards sloppy OS image
249 generation is the main purpose of maintaining the 'system token' however,
250 and if the EFI variable storage is not kept physically separate from the OS
251 image there's no point in it. That said, OS builders that know that they are
252 not going to replicate the built image on multiple systems may opt to turn
253 off the 'system token' concept by setting `random-seed-mode always` in the
254 ESP's
255 [`/loader/loader.conf`](https://www.freedesktop.org/software/systemd/man/loader.conf.html)
256 file. If done, `systemd-boot` will use the random seed file even if no
257 system token is found in EFI variables.
258
259 With the three mechanisms described above it should be possible to provide
260 early-boot entropy in most cases. Specifically:
261
262 1. On EFI systems, `systemd-boot`'s random seed logic should make sure good
263 entropy is available during earliest boot — as long as `systemd-boot` is
264 used as boot loader, and outside of virtualized environments.
265
266 2. On virtualized systems, the early `virtio-rng` hookup should ensure entropy
267 is available early on — as long as the VM environment provides virtualized
268 RNG devices, which they really should all do in 2019. Complain to your
269 hosting provider if they don't.
270
271 3. On Intel/AMD systems systemd's own reliance on the kernel entropy pool is
272 minimal (as RDRAND is used on those for UUID generation). This only works if
273 the CPU has RDRAND of course, which most physical CPUs do (but I hear many
274 virtualized CPUs do not. Pity.)
275
276 4. In all other cases, `systemd-random-seed.service` will help a bit, but — as
277 mentioned — is too late to help with early boot.
278
279 This primarily leaves two kind of systems in the cold:
280
281 1. Some embedded systems. Many embedded chipsets have hwrng functionality these
282 days. Consider using them while crediting
283 entropy. (i.e. `rng_core.default_quality=1000` on the kernel command line is
284 your friend). Or accept that the system might take a bit longer to
285 boot. Alternatively, consider implementing a solution similar to
286 systemd-boot's random seed concept in your platform's boot loader.
287
288 2. Virtualized environments that lack both virtio-rng and RDRAND. Tough
289 luck. Talk to your hosting provider, and ask them to fix this.
290
291 3. Also note: if you deploy an image without any random seed and/or without
292 installing any 'system token' in an EFI variable, as described above, this
293 means that on the first boot no seed can be passed to the OS
294 either. However, as the boot completes (with entropy acquired elsewhere),
295 systemd will automatically install both a random seed in the GPT and a
296 'system token' in the EFI variable space, so that any future boots will have
297 entropy from earliest boot on — all provided `systemd-boot` is used.
298
299 ## Frequently Asked Questions
300
301 1. *Why don't you just use getrandom()? That's all you need!*
302
303 Did you read any of the above? getrandom() is hooked to the kernel entropy
304 pool, and during early boot it's not going to be filled yet, very likely. We
305 do use it in many cases, but not in all. Please read the above again!
306
307 2. *Why don't you use
308 [getentropy()](http://man7.org/linux/man-pages/man3/getentropy.3.html)? That's
309 all you need!*
310
311 Same story. That call is just a different name for `getrandom()` with
312 `flags` set to zero, and some additional limitations, and thus it also needs
313 the kernel's entropy pool to be initialized, which is the whole problem we
314 are trying to address here.
315
316 3. *Why don't you generate your UUIDs with
317 [`uuidd`](http://man7.org/linux/man-pages/man8/uuidd.8.html)? That's all you
318 need!*
319
320 First of all, that's a system service, i.e. something that runs as "payload"
321 of systemd, long after systemd is already up and hence can't provide us
322 UUIDs during earliest boot yet. Don't forget: to assign the invocation UUID
323 for the `uuidd.service` start we already need a UUID that the service is
324 supposed to provide us. More importantly though, `uuidd` needs state/a random
325 seed/a MAC address/host ID to operate, all of which are not available during
326 early boot.
327
328 4. *Why don't you generate your UUIDs with `/proc/sys/kernel/random/uuid`?
329 That's all you need!*
330
331 This is just a different, more limited interface to `/dev/urandom`. It gains
332 us nothing.
333
334 5. *Why don't you use [`rngd`](https://github.com/nhorman/rng-tools),
335 [`haveged`](http://www.issihosts.com/haveged/),
336 [`egd`](http://egd.sourceforge.net/)? That's all you need!*
337
338 Like `uuidd` above these are system services, hence come too late for our
339 use-case. In addition much of what `rngd` provides appears to be equivalent
340 to `CONFIG_RANDOM_TRUST_CPU=y` or `rng_core.default_quality=1000`, except
341 being more complex and involving userspace. These services partly measure
342 system behavior (such as scheduling effects) which the kernel either
343 already feeds into its pool anyway (and thus shouldn't be fed into it a
344 second time, crediting entropy for it a second time) or is at least
345 something the kernel could much better do on its own. Hence, if what these
346 daemons do is still desirable today, this would be much better implemented
347 in kernel (which would be very welcome of course, but wouldn't really help
348 us here in our specific problem, see above).
349
350 6. *Why don't you use [`arc4random()`](https://man.openbsd.org/arc4random.3)?
351 That's all you need!*
352
353 This doesn't solve the issue, since it requires a nonce to start from, and
354 it gets that from `getrandom()`, and thus we have to wait for random pool
355 initialization the same way as calling `getrandom()`
356 directly. `arc4random()` is nothing more than optimization, in fact it
357 implements similar algorithms that the kernel entropy pool implements
358 anyway, hence besides being able to provide random bytes with higher
359 throughput there's little it gets us over just using `getrandom()`. Also,
360 it's not supported by glibc. And as long as that's the case we are not keen
361 on using it, as we'd have to maintain that on our own, and we don't want to
362 maintain our own cryptographic primitives if we don't have to. Since
363 systemd's uses are not performance relevant (besides the pool initialization
364 delay, which this doesn't solve), there's hence little benefit for us to
365 call these functions. That said, if glibc learns these APIs one day, we'll
366 certainly make use of them where appropriate.
367
368 7. *This is boring: NetBSD had [boot loader entropy seed
369 support](https://netbsd.gw.com/cgi-bin/man-cgi?boot+8) since ages!*
370
371 Yes, NetBSD has that, and the above is inspired by that (note though: this
372 article is about a lot more than that). NetBSD's support is not really safe,
373 since it neither updates the random seed before using it, nor has any
374 safeguards against replicating the same disk image with its random seed on
375 multiple machines (which the 'system token' mentioned above is supposed to
376 address). This means reuse of the same random seed by the boot loader is
377 much more likely.
378
379 8. *Why does PID 1 upload the boot loader provided random seed into kernel
380 instead of kernel doing that on its own?*
381
382 That's a good question. Ideally the kernel would do that on its own, and we
383 wouldn't have to involve userspace in this.
384
385 9. *What about non-EFI?*
386
387 The boot loader random seed logic described above uses EFI variables to pass
388 the seed from the boot loader to the OS. Other systems might have similar
389 functionality though, and it shouldn't be too hard to implement something
390 similar for them. Ideally, we'd have an official way to pass such a seed as
391 part of the `struct boot_params` from the boot loader to the kernel, but
392 this is currently not available.
393
394 10. *I use a different boot loader than `systemd-boot`, I'd like to use boot
395 loader random seeds too!*
396
397 Well, consider just switching to `systemd-boot`, it's worth it. See
398 [systemd-boot(7)](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)
399 for an introduction why. That said, any boot loader can re-implement the
400 logic described above, and can pass a random seed that systemd as PID 1
401 will then upload into the kernel's entropy pool. For details see the [Boot
402 Loader Interface](https://systemd.io/BOOT_LOADER_INTERFACE) documentation.
403
404 11. *Why not pass the boot loader random seed via kernel command line instead
405 of as EFI variable?*
406
407 The kernel command line is accessible to unprivileged processes via
408 `/proc/cmdline`. It's not desirable if unprivileged processes can use this
409 information to possibly gain too much information about the current state
410 of the kernel's entropy pool.
411
412 12. *Why doesn't `systemd-boot` rewrite the 'system token' too each time
413 when updating the random seed file stored in the ESP?*
414
415 The system token is stored as persistent EFI variable, i.e. in some form of
416 NVRAM. These memory chips tend be of low quality in many machines, and
417 hence we shouldn't write them too often. Writing them once during
418 installation should generally be OK, but rewriting them on every single
419 boot would probably wear the chip out too much, and we shouldn't risk that.