/dev/hwrng

Intro

There is hardware that can generate "randomness". It can be accesed trought /dev/hwrng device. Funnies part of hardware random generator it could generate anything. That why need to verify that data coming from /dev/hwrng. Good advice is to use /dev/hwrng as additional entropy source. Why we dont trust /dev/hwrng as random number source? There is some articles about HW random generators could be backdoored and could generate predictable values that why as we cant verify HW design as its not open sourced we choose not to trust it. In general if you believe in HW random generator you can use it.

Switching hardware rng

Hardware random generator have own entry inside sysfs lets check _/sys/class/misc/hw_random/

$ls /sys/class/misc/hw_random/
dev  power  rng_available  rng_current  subsystem  uevent

Check available hwrng modules

$cat /sys/class/misc/hw_random/rng_available 
zero-rng

Check currently running hwrng module

$cat /sys/class/misc/hw_random/rng_current 
zero-rng

Testing /dev/hwrng

There couple of ways how you can test if data is "random" enough. There is standards like FIPS 140-2 with have criteria to check if data source is pseudo-random. And there is couple of implementations of it. You can get tool like rng-tools and test data. Lets imagine that you have installed it already in your favorite way.

Output every 5 seconds pseudo random tests results

$cat /dev/urandom | rngtest -t 5

Program output

rngtest: starting FIPS tests...
rngtest: bits received from input: 462500032
rngtest: FIPS 140-2 successes: 23108
rngtest: FIPS 140-2 failures: 17
rngtest: FIPS 140-2(2001-10-10) Monobit: 1
rngtest: FIPS 140-2(2001-10-10) Poker: 2
rngtest: FIPS 140-2(2001-10-10) Runs: 8
rngtest: FIPS 140-2(2001-10-10) Long run: 6
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=2.166; avg=216.912; max=19073.486)Mibits/s
rngtest: FIPS tests speed: (min=56.598; avg=148.791; max=178.257)Mibits/s
rngtest: Program run time: 5016745 microseconds

Example driver

Create files Makefile and zero_hwrng.c and copy code.

Makefile

obj-m += zero_hwrng.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

load:
    insmod zero_hwrng.ko
unload:
    rmmod zero_hwrng

zero_hwrng.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hw_random.h>
#include <linux/completion.h>
#include <linux/atomic.h>
#include <linux/slab.h>
#include <linux/device.h>

#define PRINTK printk
#define PRN(format, args ... ) PRINTK("DBG FUN:%s LINE:%d " format,__FUNCTION__,__LINE__, ##args);
#define PNL() PRINTK("%s:%d\n",__FUNCTION__,__LINE__);

static int zero_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
    int i;
    u8 *buf;

    PNL();

    buf = data;

    for (i=0;i<max;i++)
    {
        buf[i] = 0;
    }

    return max;
}

static void zero_rng_cleanup(struct hwrng *rng)
{
    PNL();
}

static struct hwrng zero_rng = {
    .name = "zero-rng",
    .cleanup = zero_rng_cleanup, 
    .read    = zero_rng_read,
};

static void zero_rng_exit(void)
{
    PNL();

    hwrng_unregister(&zero_rng);
}

static int zero_rng_init(void)
{
    PNL();

    PRN("register device");

    return hwrng_register(&zero_rng);
}

module_init(zero_rng_init);
module_exit(zero_rng_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Zero /dev/hwrng");
MODULE_AUTHOR("Internet User");

Loading module

Rng module depends on rng-core module

modprobe rng-core

then load our module

insmode zero_rng.ko

check if everything is properly loaded

$lsmod | grep rng
zero_hwrng             16384  0
rng_core               16384  1 zero_hwrng

Verify randomness

Lets test how our stuff works

$ dd if=/dev/hwrng of=/tmp/random bs=1024 count=32
32+0 records in
32+0 records out
32768 bytes (33 kB, 32 KiB) copied, 0.00111024 s, 29.5 MB/s
$ hexdump /tmp/random 
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0008000

As we can see all data that we get is just zeros lets check it with rng-tools

$ cat /tmp/random | rngtest -t 5
rngtest 5
Copyright (c) 2004 by Henrique de Moraes Holschuh
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

rngtest: starting FIPS tests...
rngtest: entropy source drained
rngtest: bits received from input: 262144
rngtest: FIPS 140-2 successes: 0
rngtest: FIPS 140-2 failures: 13
rngtest: FIPS 140-2(2001-10-10) Monobit: 13
rngtest: FIPS 140-2(2001-10-10) Poker: 13
rngtest: FIPS 140-2(2001-10-10) Runs: 13
rngtest: FIPS 140-2(2001-10-10) Long run: 13
rngtest: FIPS 140-2(2001-10-10) Continuous run: 13
rngtest: input channel speed: (min=6.209; avg=13.452; max=18.626)Gibits/s
rngtest: FIPS tests speed: (min=168.792; avg=201.099; max=207.321)Mibits/s
rngtest: Program run time: 1369 microseconds

Well all tests fails thats good

Practical example

Lets assume that we are running this code on Intel arch and it supports rdrand instruction for random generation.

void get_hw_rand2(uint8_t *mem)
{
    int i=0;
    asm("rdrand %%rax\n\t"
        "mov %%rax, %0\n\t"
        :"=m"(*mem)::"0");

}

Lets replace intelrng_read function with our naive implementation of _rdrand

static int intel_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
    int i;
    u8 *buf;
    u64 rnd;
    u8 rnd8[8];
    u8 val;

    PNL();

    buf = data;
    for (i=0;i<max;i++)
    {
        if ((i%8)==0)
        {
            get_hw_rand2(rnd8);
        }
        buf[i] = rnd8[i%8];
    }

    return max;
}

Verify that our module loaded

$ cat /sys/class/misc/hw_random/rng_available 
zero-rng intel-rng

Check with module are currently used

$ cat /sys/class/misc/hw_random/rng_current 
zero-rng

if not our module set lets set it

$ echo "intel-rng" > /sys/class/misc/hw_random/rng_current

check if its current module used

$ cat /sys/class/misc/hw_random/rng_current 
intel-rng

Well everything looks fine and test are passed if you going to try test it with rng-tools.

Links

  1. Documentation/hw_random.txt
  2. 295_linux_really_using_hardware_random_number_generators.html
  3. rng-tools
  4. include/linux/hw_random.h
  5. /writeup/gcc_inline_assembly.md#toc-12