Thorsten Glaser
2019-02-24 20:00:01 UTC
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 =E2=80=9Crandom: crng init done=E2=80=9D would appear, and boot wou=
ld
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=E2=80=99m sure it also affects all others.
There=E2=80=99s 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=E2=80=99s just written to /dev/urandom but the kernel
is not told =E2=80=9Chey I just gave you X bits worth of entropy=E2=80=9D, =
and it
happens much too late, especially during parallel boot.
I=E2=80=99ve written something, a linux-any package, that=E2=80=A6
=E2=80=A2 during postinst, creates a 128-byte random seed file in /
=E2=80=A2 updates that in a daily cronjob (using same tool as during
boot except with more bits taken from the kernel)
=E2=80=A2 updates (the second 64-byte half, from urandom) it on shutdown
=E2=80=A2 hooks into initramfs to=E2=80=A6
=E2=80=93 on x86, use =E2=80=9CJytter=E2=80=9D (CPU jitter) to try and ge=
t some more
random bytes (not accredited, just written to the pool)
=E2=80=93 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)
=E2=80=93 after the root filesystem is read-write,
=E2=80=A3 reads from the seed file (128 bytes)
=E2=80=A3 uses that and a number of other things (to make it differ)=E2=
=80=A6
=E2=86=90 md5sum of dmesg
=E2=86=90 3 random bytes written into initramfs during update-initram=
fs
=E2=86=90 the current time
=E2=86=90 a bit of kernel entropy (from AT_RANDOM auxvec, set anyway)
=E2=86=90 on x86, Jytter and the TSC
to initialise a stretching RNG (arc4random)
=E2=80=A3 writes between 32 and 256 bytes to /dev/urandom (but does not
accredit them yet, just remembers the amount written)
=E2=80=A3 updates the seed file with 128 bytes from the SRNG
=E2=80=A3 fsync(2)s and close(2)s the seed file to ensure the next run
will be different
=E2=80=A3 now tells the kernel X random bits were added, where X is=E2=
=80=A6
=E2=86=92 the number of bytes written earlier=E2=80=A6
=E2=86=92 times 6 (so we count at best six bits per byte)=E2=80=A6
=E2=86=92 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=E2=80=99d 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=3Dalioth/early-rng=
-init-tools.git;a=3Dtree
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:
=E2=80=A2 it=E2=80=99s Linux-only (the RNG on kFreeBSD is very different, a=
nd
I didn=E2=80=99t even look into Hurd=E2=80=99s urandom translator)
=E2=80=A2 it prevents you from booting with / mounted read-only
=E2=80=A3 although the checkroot init script remounts / read-only when ne=
eded
=E2=80=A3 perhaps we could remount / read-only ourselves afterwards,
but that can be tricky to get right too=E2=80=A6
=E2=80=A2 it means you trust a seed file and the arc4random algorithm (to m=
ake
a uniform enough stream from the various seeds)
=E2=80=A2 klibc lacks clock_gettime (#923098) so we cannot add the monotoni=
c
clock, which would be interesting in the cronjob/shutdown hook
=E2=80=A2 it links statically against klibc, because getting Depends on the
/lib/klibc-*.so file right is unchartered territory
=E2=80=A2 it does not use/add CPU RNG output where present
=E2=80=A3 though Linux can now do that itself, some command-line flag=E2=
=80=A6
=E2=80=A2 nor is there any jitter code on n=C5=8Dn-x86
On the plus side, I=E2=80=99ve tested it on i386, amd64, x32 (although klib=
c
for x32 is actually amd64 so I tested that with glibc) and as a n=C5=8Dn-x8=
6
architecture m68k. It also works on MirBSD, should do OpenBSD, too=E2=80=A6
Perhaps this helps someone. While too late for buster, unless there
is any justified concern, I=E2=80=99ll 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
--=20
18:47=E2=8E=9C<mirabilos:#!/bin/mksh> well channels=E2=80=A6 you see, I see=
everything in the
same window anyway 18:48=E2=8E=9C<xpt:#!/bin/mksh> i know, you have so=
me kind of
telnet with automatic pong 18:48=E2=8E=9C<mirabilos:#!/bin/mksh> ha=
ha, yes :D
18:49=E2=8E=9C<mirabilos:#!/bin/mksh> though that's more tinyirc =E2=80=93 =
sirc is more comfy
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 =E2=80=9Crandom: crng init done=E2=80=9D would appear, and boot wou=
ld
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=E2=80=99m sure it also affects all others.
There=E2=80=99s 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=E2=80=99s just written to /dev/urandom but the kernel
is not told =E2=80=9Chey I just gave you X bits worth of entropy=E2=80=9D, =
and it
happens much too late, especially during parallel boot.
I=E2=80=99ve written something, a linux-any package, that=E2=80=A6
=E2=80=A2 during postinst, creates a 128-byte random seed file in /
=E2=80=A2 updates that in a daily cronjob (using same tool as during
boot except with more bits taken from the kernel)
=E2=80=A2 updates (the second 64-byte half, from urandom) it on shutdown
=E2=80=A2 hooks into initramfs to=E2=80=A6
=E2=80=93 on x86, use =E2=80=9CJytter=E2=80=9D (CPU jitter) to try and ge=
t some more
random bytes (not accredited, just written to the pool)
=E2=80=93 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)
=E2=80=93 after the root filesystem is read-write,
=E2=80=A3 reads from the seed file (128 bytes)
=E2=80=A3 uses that and a number of other things (to make it differ)=E2=
=80=A6
=E2=86=90 md5sum of dmesg
=E2=86=90 3 random bytes written into initramfs during update-initram=
fs
=E2=86=90 the current time
=E2=86=90 a bit of kernel entropy (from AT_RANDOM auxvec, set anyway)
=E2=86=90 on x86, Jytter and the TSC
to initialise a stretching RNG (arc4random)
=E2=80=A3 writes between 32 and 256 bytes to /dev/urandom (but does not
accredit them yet, just remembers the amount written)
=E2=80=A3 updates the seed file with 128 bytes from the SRNG
=E2=80=A3 fsync(2)s and close(2)s the seed file to ensure the next run
will be different
=E2=80=A3 now tells the kernel X random bits were added, where X is=E2=
=80=A6
=E2=86=92 the number of bytes written earlier=E2=80=A6
=E2=86=92 times 6 (so we count at best six bits per byte)=E2=80=A6
=E2=86=92 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=E2=80=99d 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=3Dalioth/early-rng=
-init-tools.git;a=3Dtree
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:
=E2=80=A2 it=E2=80=99s Linux-only (the RNG on kFreeBSD is very different, a=
nd
I didn=E2=80=99t even look into Hurd=E2=80=99s urandom translator)
=E2=80=A2 it prevents you from booting with / mounted read-only
=E2=80=A3 although the checkroot init script remounts / read-only when ne=
eded
=E2=80=A3 perhaps we could remount / read-only ourselves afterwards,
but that can be tricky to get right too=E2=80=A6
=E2=80=A2 it means you trust a seed file and the arc4random algorithm (to m=
ake
a uniform enough stream from the various seeds)
=E2=80=A2 klibc lacks clock_gettime (#923098) so we cannot add the monotoni=
c
clock, which would be interesting in the cronjob/shutdown hook
=E2=80=A2 it links statically against klibc, because getting Depends on the
/lib/klibc-*.so file right is unchartered territory
=E2=80=A2 it does not use/add CPU RNG output where present
=E2=80=A3 though Linux can now do that itself, some command-line flag=E2=
=80=A6
=E2=80=A2 nor is there any jitter code on n=C5=8Dn-x86
On the plus side, I=E2=80=99ve tested it on i386, amd64, x32 (although klib=
c
for x32 is actually amd64 so I tested that with glibc) and as a n=C5=8Dn-x8=
6
architecture m68k. It also works on MirBSD, should do OpenBSD, too=E2=80=A6
Perhaps this helps someone. While too late for buster, unless there
is any justified concern, I=E2=80=99ll 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
--=20
18:47=E2=8E=9C<mirabilos:#!/bin/mksh> well channels=E2=80=A6 you see, I see=
everything in the
same window anyway 18:48=E2=8E=9C<xpt:#!/bin/mksh> i know, you have so=
me kind of
telnet with automatic pong 18:48=E2=8E=9C<mirabilos:#!/bin/mksh> ha=
ha, yes :D
18:49=E2=8E=9C<mirabilos:#!/bin/mksh> though that's more tinyirc =E2=80=93 =
sirc is more comfy