best we’ll ship some hashing utility
[alioth/early-rng-init-tools.git] / DESIGN
1 ┌────────────────────────────────────┐
2 │ The early-rng-init-tools v1 design │
3 └────────────────────────────────────┘
4
5 This utility does N̲O̲T̲ aid in the c̲o̲l̲l̲e̲c̲t̲i̲o̲n̲ of entropy.
6 Its purpose is only to provide some of the previous sy‐
7 stem boot to the next one, very early (as to initialise
8 the (Linux) kernel CSPRNG quickly). Additionally, a de‐
9 ficiency (random seed is only written at system startup
10 and during shutdown) is mended by updating it via cron.
11
12 This is intended as a stopgap until bootloaders provide
13 random bytes from e.g. /boot as part of the boot proto‐
14 col, the distro initscripts update that, a cronjob does
15 it regularily. (The BSDs have this.)
16
17 • package postinst
18   ‣ creates an 128-byte seed file from /dev/urandom
19
20 • initramfs hook
21   ‣ copies rnd_shuf, (x86) rnd_jytter to initramfs
22   ‣ creates additional 3-byte extra “seed” in the initramfs
23     from /dev/urandom
24
25 • daily cronjob
26   ‣ runs rnd_shuf, optionally verbosely or in debugging mode
27
28 • init script and systemd unit
29   ‣ run only on shutdown
30   ‣ call “shuffle” to update the seed
31 • shuffle
32   ‣ updates the first 64 bytes of seed file from /dev/urandom
33   ‣ checks the seed file’s size is still 128
34
35 • initramfs top
36   ‣ makes the mounting code mount / read-write later
37   ‣ on x86: starts rnd_jytter in the background, -b 8 -d 0.34 -r 5,
38     output to /dev/urandom
39
40 ⚠ NOTE while others may consider jitter output entropy, we’re using
41   it to increase uncertainty / shuffle bytes around o̲n̲l̲y̲, it is n̲o̲t̲
42   credited (and x86-only anyway); our mission is not gathering ran‐
43   domness but making it usable earlier than without
44
45 • initramfs bottom (after rw mount of / either local or NFS)
46   ‣ collects extraseed (see above), md5sum of dmesg
47   ‣ calls rnd_shuf in “Early” mode adding these extra bytes
48
49 • rnd_jytter (x86), only called from initramfs top
50   ‣ uses Russell Leidich’s jitter RNG (in userspace, where it belongs)
51     to collect, 5 (-r) times, 8 (-b) bytes of uncertainty writing them
52     after collection to stdout (/dev/urandom), sleeping 0.34 s (-d)
53     between rounds
54
55 • rnd_shuf in Early mode
56   ‣ adds extraseed to the buffer
57   ‣ opens /dev/urandom and the seedfile, checking it to be min. 128 bytes
58   ‣ collects 4 jytter bytes (x86)
59   ≏ (BSD) reads 4 bytes from the kernel via sysctl; success: need=0
60   ≏ (Linux) reads the auxvec AT_RANDOM (16 bytes), if present;
61     success: need=0; failure: need=4
62   ‣ adds the current time (gettimeofday) to the buffer
63   ‣ collects 4 jytter bytes (x86)
64   ≏ reads $need bytes from /dev/urandom into the buffer (0/4)
65   ‣ (x86) adds the TSC to the buffer
66   ‣ collects 4 jytter bytes (x86), total of 12
67   ‣ adds up to 128 bytes off seed file to buffer, to a total of 256
68   ‣ initialises internal arc4random from the buffer
69   ‣ writes 32‥256 bytes of arc4random output to /dev/urandom
70   ‣ writes 128 bytes of arc4random output to seed file
71   ‣ on seed file write error: terminates if <16 bytes were written
72   ‣ on urandom write error: terminates if no bytes were written
73   ‣ accredits ¾ of the bytes written to /dev/urandom, at most
74     ⅞ of 128 bytes, into entropy counter (BSD/Linux kernel)
75
76 • rnd_shuf in shuffle mode
77   ‣ opens /dev/urandom and the seedfile, checking it to be min. 128 bytes
78   ‣ collects 4 jytter bytes (x86)
79   ≏ (BSD) reads 16 bytes from the kernel via sysctl; success: need=0
80   ≏ (Linux) reads the auxvec AT_RANDOM (16 bytes), if present;
81     success: need=8; failure: need=16
82   ‣ adds the current time (klibc: gettimeofday; others: CLOCK_REALTIME
83     and CLOCK_MONOTONIC) to the buffer
84   ‣ collects 4 jytter bytes (x86)
85   ≏ reads $need bytes from /dev/urandom into the buffer (8/16)
86   ‣ (x86) adds the TSC to the buffer
87   ‣ collects 4 jytter bytes (x86), total of 12
88   ‣ adds up to 128 bytes off seed file to buffer, to a total of 256
89   ‣ initialises internal arc4random from the buffer
90   ‣ writes 32‥256 bytes of arc4random output to /dev/urandom
91   ‣ writes 128 bytes of arc4random output to seed file
92   ‣ fsync()s and closes seed file
93   ‣ on seed file write error: terminates if <16 bytes were written
94   ‣ on urandom write error: terminates if no bytes were written
95   ‣ accredits ¾ of the bytes written to /dev/urandom, at most
96     ⅞ of 128 bytes, into entropy counter (BSD/Linux kernel)
97
98 We rely on arc4random with aRC4 to spread the entropy in the
99 input buffer around to all, in total not sizeable here, outputs.
100 All contemporary blinding to avoid aRC4 deficiencies are used.
101
102 We add extra data from various sources not for more entropy
103 but for uncertainty, unpredictability and simply spreading around:
104 – extraseed written to initramfs, which is n̲o̲t̲ updated between
105   reboots (only on update-initramfs) and by default world-readable
106 – dmesg contents (for variety, MAC addresses Early for cloned images)
107 – time (uptime and wallclock if possible; (x86) TSC)
108 – (x86) 12 bytes of jytter output taken over spread runtime
109 We add some kernel (urandom) bytes as well, not that it matters
110 much Early but it decreases predictability of the aRC4 state further.