/initrng

Linux Random Number Generator (RNG) initialization in early userspace

Primary LanguagePythonMIT LicenseMIT

Initialize Linux Random Number Generator (RNG) early at boot

Sometimes we need to do something nasty: use /dev/random or /dev/urandom
during early boot stages in initramfs and/or before systemd/sysvinit
loads seed data saved from previous runtime.

Recent Linux kernels, since commits:

  * 9b4d008 random: print a warning for the first ten uninitialized random users
  * 392a546 random: add debugging code to detect early use of get_random_bytes()

notify about potentially unsafe (in security sense) early usage of Linux
RNG when entropy is low with warnings in kernel ring buffer similar to:

  random: blkid: uninitialized urandom read (6 bytes read, 96 bits of entropy available)

Backing to our initramfs and early boot stage random usage there is very
little activity after kernel gives hands to userspace and therefore very
few bytes of entropy available. There is no access to saved seed data
since rootfs isn't mounted, no hardware RNG device available to get seed
data and no user activity to wait for kernel to collect entropy since it
might be embedded device.

The only semi reliable option left is to prepare seed by ourselves based
on some kernel pseudo random data like kernel ring buffer contents from
/dev/kmsg with printk() timings when CONFIG_PRINTK_TIME is 'y', contents
of various procfs files (e.g. interrupts, buddyinfo, schedstat).

All these sources should not be considered as good random seed, but much
better than just using number of seconds since Epoch.

Use SHA512 algo to avoid using contents directly. Thus we get up to 512
bits (128 bytes) of early entropy that should be enough to complete some
non random data hungry tasks.

Help:
-----

usage: initrng.py [-h] [-l {crit,warn,debug,info,err}] [-e ENTROPY_FILES]
                  [-r REPEAT] [-o OUTPUT]

Linux RNG early init

optional arguments:
  -h, --help            show this help message and exit
  -l {crit,warn,debug,info,err}, --loglevel {crit,warn,debug,info,err}
                        set program loging severity (level)
  -e ENTROPY_FILES, --entropy-file ENTROPY_FILES
                        files to use as source of entropy (/dev/kmsg,
                        /proc/buddyinfo, /proc/interrupts, /proc/softirqs,
                        /proc/schedstat)
  -r REPEAT, --repeat REPEAT
                        repeat entropy updates # times (default 8)
  -o OUTPUT, --output OUTPUT
                        file to output entropy (default "/dev/urandom")

Examples:
---------

    # just run with default sources of pseudo random data:
    #
    #  /proc/timer_list
    #  /proc/interrupts
    #  /proc/buddyinfo
    #  /proc/softirqs
    #  /proc/schedstat
    #
    $ sudo initrng.py

    # use 'debug' severity for logging and custom entropy file
    $ initrng.py -l debug -e /proc/timer_list