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