Hello fellow developers (and some users), I would like to present a recent (this week) project of mine. Background story:
In buster/sid, I noticed a massive delay booting up my laptop and some virtual machines, which was reduced by hitting the Shift and Ctrl keys multiple times randomly during boot; a message “random: crng init done” would appear, and boot would continue. This is a well-known problem, and there are several bugs about this; new in buster/sid compared to stretch is that it also blocks urandom reads (I was first hit in the tomcat init script from this). This is especially noticeable if you use a sysvinit non-parallel boot, but I’m sure it also affects all others. There’s already code, in both sysv-rc/initscripts and systemd, to store some random seed file and load it on reboot. The problem with that is that it’s just written to /dev/urandom but the kernel is not told “hey I just gave you X bits worth of entropy”, and it happens much too late, especially during parallel boot. I’ve written something, a linux-any package, that… • during postinst, creates a 128-byte random seed file in / • updates that in a daily cronjob (using same tool as during boot except with more bits taken from the kernel) • updates (the second 64-byte half, from urandom) it on shutdown • hooks into initramfs to… – on x86, use “Jytter” (CPU jitter) to try and get some more random bytes (not accredited, just written to the pool) – makes it mount the root filesystem, after fsck, read-write instead of deferring that to the init scripts (this should be safe, though, as initramfs *does* fsck) – after the root filesystem is read-write, ‣ reads from the seed file (128 bytes) ‣ uses that and a number of other things (to make it differ)… ← md5sum of dmesg ← 3 random bytes written into initramfs during update-initramfs ← the current time ← a bit of kernel entropy (from AT_RANDOM auxvec, set anyway) ← on x86, Jytter and the TSC to initialise a stretching RNG (arc4random) ‣ writes between 32 and 256 bytes to /dev/urandom (but does not accredit them yet, just remembers the amount written) ‣ updates the seed file with 128 bytes from the SRNG ‣ fsync(2)s and close(2)s the seed file to ensure the next run will be different ‣ now tells the kernel X random bits were added, where X is… → the number of bytes written earlier… → times 6 (so we count at best six bits per byte)… → capped at 128*7 bits, to both not overwhelm and because our seed is only 128 bytes in size, estimated conservatively tl;dr: it adds entropy during initramfs/as early as possible during boot *and* tells the kernel it did so, to make its crng initialised, and ensures a subsequent boot has a different seed, also updated periodically and on shutdown for added entropy carry-over. I’d like people to use it, experiment with it and criticise it. Packages (.dsc / some .deb): http://fish.mirbsd.org/~tg/Debs/dists/sid/wtf/Pkgs/early-rng-init-tools/ Repository: https://evolvis.org/plugins/scmgit/cgi-bin/gitweb.cgi?p=alioth/early-rng-init-tools.git;a=tree git clone https://evolvis.org/anonscm/git/alioth/early-rng-init-tools.git Licence: MirOS, some parts ISC, some x86-only parts LGPL. I am fully aware that it is not suitable for everyone: • it’s Linux-only (the RNG on kFreeBSD is very different, and I didn’t even look into Hurd’s urandom translator) • it prevents you from booting with / mounted read-only ‣ although the checkroot init script remounts / read-only when needed ‣ perhaps we could remount / read-only ourselves afterwards, but that can be tricky to get right too… • it means you trust a seed file and the arc4random algorithm (to make a uniform enough stream from the various seeds) • klibc lacks clock_gettime (#923098) so we cannot add the monotonic clock, which would be interesting in the cronjob/shutdown hook • it links statically against klibc, because getting Depends on the /lib/klibc-*.so file right is unchartered territory • it does not use/add CPU RNG output where present ‣ though Linux can now do that itself, some command-line flag… • nor is there any jitter code on nōn-x86 On the plus side, I’ve tested it on i386, amd64, x32 (although klibc for x32 is actually amd64 so I tested that with glibc) and as a nōn-x86 architecture m68k. It also works on MirBSD, should do OpenBSD, too… Perhaps this helps someone. While too late for buster, unless there is any justified concern, I’ll upload it to Debian (and provide it via buster-backports) in a while. Enjoy, //mirabilos PS: please keep me in Cc, I am not subscribed to d-devel PPS: feel free to forward/distribute this elsewhere -- 18:47⎜<mirabilos:#!/bin/mksh> well channels… you see, I see everything in the same window anyway 18:48⎜<xpt:#!/bin/mksh> i know, you have some kind of telnet with automatic pong 18:48⎜<mirabilos:#!/bin/mksh> haha, yes :D 18:49⎜<mirabilos:#!/bin/mksh> though that's more tinyirc – sirc is more comfy