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