Hardware Random Number Generator

December 8, 2015

We discussed an algorithm due to Lenore Blum, Manuel Blum and Michael Shub that generates cryptographically-secure random numbers in a previous exercise. A better way to generate these random numbers uses an actual hardware source of entropy, such as thermal noise.

I recently learned that all models of the Raspberry Pi computer include a hardware random number generator on their system-on-a-chip; Stewart Russell gives instructions.

If instead of a Raspberry Pi you have a computer based on the Intel Ivy Bridge family of processors, a hardware random number generator is available as rdrand; Linux exposes that as the /dev/random device.

Your task is to explore the hardware random number generators that are available to you; you might want to write a program to generate keypads for the Diana Cryptosystem. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2

2 Responses to “Hardware Random Number Generator”

  1. Jussi Piitulainen said

    Aha! Now I can generate cryptographically secure messages in the shell! Wonder what that says:

    $ echo $(od -An -N1000 -t c /dev/random | tr -dc a-zA-Z | tr -s cfqxzCFQXZ ' ' | tr A-Z a-z) | fold -s -w 40
    br ksbeambor iwbp wgjlvm ra ykdpdrypkt 
    rk au nm ma bdtnyw lwrrtdenl ep glt 
    mnwlole geghrern kbnrgv tv ikd htvnn 
    ast rm s k j y lvukmbphs agiukv evsvabs 
    nslpnwh spwuthj sbd hdbdilaap inaerpt 
    guvverb gjpv euybm
    

    I learned (man 4 random) that /dev/random can block, but my laptop’s entropy pool seems to stay above 3000 bits; a server with other users seems to have around 180 bits of available entropy; these keep changing whether I read the device or not; both have poolsize 4096.But I don’t really know if these are working as intended. Interesting anyway.

    Apparently it’s not polite to consume much hardware entropy in a machine with other users. The above was on my personal laptop. But as I said, it was barely noticeable.

    Maybe I do have a dedicated entropy generator? And a backdoor so that the NSA can read my message, while I myself cannot? That’s not fair :)

  2. matthew said

    Nice problem, didn’t know the Pi had a hardware RNG. This seems to be the only actual documentation around: http://pastehtml.com/view/crkxyohmp.rtxt – as well as looking at the driver source (bcm2708-rng.c and bcm2835rng.c by Lubomir Rintel). Here’s a little program that memory maps the control registers rather than using the device & which generates random Unicode I-Ching hexagrams (we should use Unicode more); doing a full startup & shutdown each time probably isn’t necessary. Takes 8 secs to generate a million hexagrams (including startup time). I’ve only tried in on a Pi 2, on the Pi 1 the I/O registers are at a different place – I think the commented out line for IO_BASE is correct but haven’t checked.

    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <locale.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    
    #define CHECK(e) ((e)?(void)0:(perror(#e), abort()))
    #define BLOCK_SIZE 4096
    //#define IO_BASE     0x20000000 // pi v1?
    #define IO_BASE     0x3F000000 // pi v2
    
    // Use 32-bit addressing, hence the shifts
    #define RNG_CTRL         (0x0>>2)
    #define RNG_STATUS       (0x4>>2)
    #define RNG_DATA         (0x8>>2)
    #define RNG_FF_THRESHOLD (0xc>>2)
    #define RNG_BASE         (IO_BASE + 0x00104000)
    
    #define RNG_RBGEN         0x1     // enable rng
    #define RNG_RBG2X         0x2     // double speed, 'less random' mode
    #define RNG_WARMUP_COUNT  0x40000 // discard initial numbers generated
    
    volatile uint32_t *rng_base = NULL; // Register memory map
    
    uint32_t getrand() {
      while ((rng_base[RNG_STATUS] >> 24) == 0);
      return rng_base[RNG_DATA];
    }
    
    int main (int argc, char *argv[]) {
      setlocale(LC_ALL,"");
      int n = atoi(argv[1]);
      int fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC);
      CHECK(fd >= 0);
      rng_base = (uint32_t*)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE,
    			     MAP_SHARED, fd, RNG_BASE);
      CHECK(rng_base != (void*)-1);
      rng_base[RNG_STATUS] = RNG_WARMUP_COUNT;
      rng_base[RNG_CTRL]   = RNG_RBGEN /*| RNG_RBG2X*/;
    
      uint64_t t = 0; int nbits = 0;
      for (int i = 1; i <= n; i++) {
        if (nbits < 6) {
          t |= (uint64_t)getrand() << nbits;
          nbits += 32;
        }
        printf("%lc ", (int)(0x4DC0 + (t & ((1<<6)-1))));
        t >>= 6; nbits -= 6;
        if (i == n || i%16 == 0) printf("\n");
      }
      rng_base[RNG_CTRL] = 0;
    }
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: