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