Hardware-Zufallszahlengenerator des Raspberry Pi nutzen

29.10.2015 yahe administration legacy linux security

Bei Serversystemen hat man häufig das Problem, dass dem Zufallszahlengenerator nicht genug Nutzerinteraktionen zur Verfügung stehen, um ausreichend Entropie für den Zufallszahlengenerator zu sammeln. Das führt dann, je nach eingesetzter Software, zu hängenden SSH-Verbindungen, zu Timeouts bei HTTPS-Verbindungen oder anderen nicht reproduzierbaren Fehlern. Aus diesem und anderen Gründen haben CPU-Hersteller begonnen, Hardware-Zufallszahlengeneratoren direkt in ihre Prozessoren zu integrieren. Bei Intel nennt sich diese Technologie "Secure Key" (vormals "Bull Mountain"), bei VIA ist sie als "PadLock" bekannt, einige Broadcom-SOCs haben einen Hardware-Zufallszahlengenerator und auch AMD Zen unterstützt RdRand.

Auch der Broadcom-Chip des Raspberry Pi bietet einen Hardware-Zufallszahlengenerator, dessen erzeugte Zufallszahlen man in den Linux-Zufallszahlenpool einfließen lassen kann. Hierfür sind nur wenige Schritte notwendig. Als erstes muss das entsprechende Kernel-Modul geladen werden. Die Distribution Raspbian liefert zwei Broadcom-Random-Number-Generator-Module mit den Namen "bcm2708_rng" und "bcm2835_rng". Obwohl im Raspberry Pi ein Broadcom 2835 steckt, funktioniert in Raspbian nur das "bcm2708_rng"-Kernelmodul korrekt. BCM2708 ist die SOC-Familie, zu der auch der BCM2835 gehört. Überprüfen kann man das auch nochmal anhand der Ausgabe des Befehls:

cat /proc/cpuinfo

In der erscheinenden Ausgabe wird die Hardware explizit als BCM2708 benannt:

processor  : 0
model name  : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS  : 2.00
Features  : half thumb fastmult vfp edsp java tls
CPU implementer  : 0x41
CPU architecture: 7
CPU variant  : 0x0
CPU part  : 0xb76
CPU revision  : 7

Hardware  : BCM2708
Revision  : 000e
Serial    : ****************

Nun heißt es, das passende Kernelmodul zu laden. Testweise könnt ihr das mit folgendem Befehl tun:

sudo modprobe bcm2708_rng

Wenn das ohne Fehler funktioniert hat, sollte nun das Character-Device-File "/dev/hwrng" existieren. Ist das der Fall, benötigt ihr noch die "rng-tools", die ihr einfach per "apt-get" installieren könnt:

sudo apt-get install rng-tools

Nach der Installation sollten diese direkt automatisch starten. Ihr könnt zudem testen, ob diese auch ihre Arbeit verrichten. Dazu ruft ihr das "rngd" Tool im Foreground-Modus auf und beendet es nach ein wenig Warten wieder per "CTRL+C":

sudo rngd -f
^C

Euch sollten nun die verschiedensten Statistiken angezeigt werden, unter anderem, wieviele FIPS 140-2 Tests erfolgreich bestanden wurden. Mit diesen wird die Qualität der generierten Zufallszahlen ermittelt:

rngd 2-unofficial-mt.14 starting up...
entropy feed to the kernel ready
stats: bits received from HRNG source: 60064
stats: bits sent to kernel pool: 512
stats: entropy added to kernel pool: 512
stats: FIPS 140-2 successes: 3
stats: FIPS 140-2 failures: 0
stats: FIPS 140-2(2001-10-10) Monobit: 0
stats: FIPS 140-2(2001-10-10) Poker: 0
stats: FIPS 140-2(2001-10-10) Runs: 0
stats: FIPS 140-2(2001-10-10) Long run: 0
stats: FIPS 140-2(2001-10-10) Continuous run: 0
stats: HRNG source speed: (min=752.012; avg=782.220; max=807.043)Kibits/s
stats: FIPS tests speed: (min=5.249; avg=5.533; max=6.076)Mibits/s
stats: Lowest ready-buffers level: 2
stats: Entropy starvations: 0
stats: Time spent starving for entropy: (min=0; avg=0.000; max=0)us
Exiting...

Wenn das alles funktioniert hat, könnt ihr die Verwendung des Kernel-Moduls permanent machen, indem ihr in die Datei "/etc/modules" eine neue Zeile mit dem Namen des Kernel-Moduls einfügt:

bcm2708_rng

Um sicherzugehen, dass die bereitgestellten Zufallszahlen wirklich eine gute Qualität haben, habe ich den vollständigen Satz an Dieharder-Tests laufen lassen. Hierzu habe ich erst einmal Dieharder selbst installiert:

sudo apt-get install dieharder

Da der Zufallszahlengenerator nicht sonderlich schnell ist, musste ich den Dieharder-Test via "nohup" starten. Dieses sorgt dafür, dass der Prozess weiterläuft, obwohl die SSH-Session, in der der Aufruf erfolgte, bereits geschlossen wurde. Der gesamte Dieharder-Testlauf dauerte etwa einen Monat:

sudo nohup sh -c "cat /dev/hwrng | dieharder -g 200 -a"

Die Ergebnisse der Dieharder-Tests sind aus meiner Sicht vielversprechend. Fast alle Testläufe wurden ohne Probleme bestanden. Lediglich zwei Testläufe zeigen ein "weak"-Ergebnis, was bei einem echten Zufallszahlengenerator durchaus mal vorkommen kann:

#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
   rng_name    |rands/second|   Seed   |
stdin_input_raw|  2.49e+04  |1848243654|
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
   diehard_birthdays|   0|       100|     100|0.80754184|  PASSED
      diehard_operm5|   0|   1000000|     100|0.46154223|  PASSED
  diehard_rank_32x32|   0|     40000|     100|0.24741511|  PASSED
    diehard_rank_6x8|   0|    100000|     100|0.98544914|  PASSED
   diehard_bitstream|   0|   2097152|     100|0.74214657|  PASSED
        diehard_opso|   0|   2097152|     100|0.62926414|  PASSED
        diehard_oqso|   0|   2097152|     100|0.65459762|  PASSED
         diehard_dna|   0|   2097152|     100|0.05329859|  PASSED
diehard_count_1s_str|   0|    256000|     100|0.93984253|  PASSED
diehard_count_1s_byt|   0|    256000|     100|0.73264960|  PASSED
 diehard_parking_lot|   0|     12000|     100|0.82688871|  PASSED
    diehard_2dsphere|   2|      8000|     100|0.81340970|  PASSED
    diehard_3dsphere|   3|      4000|     100|0.81943245|  PASSED
     diehard_squeeze|   0|    100000|     100|0.20437793|  PASSED
        diehard_sums|   0|       100|     100|0.01259559|  PASSED
        diehard_runs|   0|    100000|     100|0.40514608|  PASSED
        diehard_runs|   0|    100000|     100|0.83339986|  PASSED
       diehard_craps|   0|    200000|     100|0.11679660|  PASSED
       diehard_craps|   0|    200000|     100|0.42675629|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|     100|0.96356183|  PASSED
 marsaglia_tsang_gcd|   0|  10000000|     100|0.84443650|  PASSED
         sts_monobit|   1|    100000|     100|0.86875820|  PASSED
            sts_runs|   2|    100000|     100|0.76068017|  PASSED
          sts_serial|   1|    100000|     100|0.44501629|  PASSED
          sts_serial|   2|    100000|     100|0.08213384|  PASSED
          sts_serial|   3|    100000|     100|0.40056497|  PASSED
          sts_serial|   3|    100000|     100|0.84781124|  PASSED
          sts_serial|   4|    100000|     100|0.67540322|  PASSED
          sts_serial|   4|    100000|     100|0.67479165|  PASSED
          sts_serial|   5|    100000|     100|0.93910920|  PASSED
          sts_serial|   5|    100000|     100|0.78108786|  PASSED
          sts_serial|   6|    100000|     100|0.36072231|  PASSED
          sts_serial|   6|    100000|     100|0.10943079|  PASSED
          sts_serial|   7|    100000|     100|0.33454672|  PASSED
          sts_serial|   7|    100000|     100|0.84662732|  PASSED
          sts_serial|   8|    100000|     100|0.56239211|  PASSED
          sts_serial|   8|    100000|     100|0.85989154|  PASSED
          sts_serial|   9|    100000|     100|0.09053360|  PASSED
          sts_serial|   9|    100000|     100|0.76921152|  PASSED
          sts_serial|  10|    100000|     100|0.65164012|  PASSED
          sts_serial|  10|    100000|     100|0.98802936|  PASSED
          sts_serial|  11|    100000|     100|0.16490199|  PASSED
          sts_serial|  11|    100000|     100|0.43350451|  PASSED
          sts_serial|  12|    100000|     100|0.97347736|  PASSED
          sts_serial|  12|    100000|     100|0.35755776|  PASSED
          sts_serial|  13|    100000|     100|0.61727927|  PASSED
          sts_serial|  13|    100000|     100|0.70426071|  PASSED
          sts_serial|  14|    100000|     100|0.96653473|  PASSED
          sts_serial|  14|    100000|     100|0.72003802|  PASSED
          sts_serial|  15|    100000|     100|0.33951664|  PASSED
          sts_serial|  15|    100000|     100|0.65324653|  PASSED
          sts_serial|  16|    100000|     100|0.79539647|  PASSED
          sts_serial|  16|    100000|     100|0.29465210|  PASSED
         rgb_bitdist|   1|    100000|     100|0.29377788|  PASSED
         rgb_bitdist|   2|    100000|     100|0.26581318|  PASSED
         rgb_bitdist|   3|    100000|     100|0.68619130|  PASSED
         rgb_bitdist|   4|    100000|     100|0.65469598|  PASSED
         rgb_bitdist|   5|    100000|     100|0.94194728|  PASSED
         rgb_bitdist|   6|    100000|     100|0.06186682|  PASSED
         rgb_bitdist|   7|    100000|     100|0.99989483|   WEAK
         rgb_bitdist|   8|    100000|     100|0.94851172|  PASSED
         rgb_bitdist|   9|    100000|     100|0.55403191|  PASSED
         rgb_bitdist|  10|    100000|     100|0.42372957|  PASSED
         rgb_bitdist|  11|    100000|     100|0.69930031|  PASSED
         rgb_bitdist|  12|    100000|     100|0.10435458|  PASSED
rgb_minimum_distance|   2|     10000|    1000|0.06686667|  PASSED
rgb_minimum_distance|   3|     10000|    1000|0.73245892|  PASSED
rgb_minimum_distance|   4|     10000|    1000|0.21902555|  PASSED
rgb_minimum_distance|   5|     10000|    1000|0.98142677|  PASSED
    rgb_permutations|   2|    100000|     100|0.52202354|  PASSED
    rgb_permutations|   3|    100000|     100|0.01765637|  PASSED
    rgb_permutations|   4|    100000|     100|0.54444953|  PASSED
    rgb_permutations|   5|    100000|     100|0.98885119|  PASSED
      rgb_lagged_sum|   0|   1000000|     100|0.19012074|  PASSED
      rgb_lagged_sum|   1|   1000000|     100|0.52956823|  PASSED
      rgb_lagged_sum|   2|   1000000|     100|0.95958846|  PASSED
      rgb_lagged_sum|   3|   1000000|     100|0.95145243|  PASSED
      rgb_lagged_sum|   4|   1000000|     100|0.13284355|  PASSED
      rgb_lagged_sum|   5|   1000000|     100|0.50651321|  PASSED
      rgb_lagged_sum|   6|   1000000|     100|0.67578443|  PASSED
      rgb_lagged_sum|   7|   1000000|     100|0.28159075|  PASSED
      rgb_lagged_sum|   8|   1000000|     100|0.70439598|  PASSED
      rgb_lagged_sum|   9|   1000000|     100|0.95701984|  PASSED
      rgb_lagged_sum|  10|   1000000|     100|0.11591970|  PASSED
      rgb_lagged_sum|  11|   1000000|     100|0.79622842|  PASSED
      rgb_lagged_sum|  12|   1000000|     100|0.30363114|  PASSED
      rgb_lagged_sum|  13|   1000000|     100|0.66673746|  PASSED
      rgb_lagged_sum|  14|   1000000|     100|0.08939797|  PASSED
      rgb_lagged_sum|  15|   1000000|     100|0.15096120|  PASSED
      rgb_lagged_sum|  16|   1000000|     100|0.31977071|  PASSED
      rgb_lagged_sum|  17|   1000000|     100|0.27180216|  PASSED
      rgb_lagged_sum|  18|   1000000|     100|0.69988188|  PASSED
      rgb_lagged_sum|  19|   1000000|     100|0.47622405|  PASSED
      rgb_lagged_sum|  20|   1000000|     100|0.69420826|  PASSED
      rgb_lagged_sum|  21|   1000000|     100|0.99297760|  PASSED
      rgb_lagged_sum|  22|   1000000|     100|0.60131473|  PASSED
      rgb_lagged_sum|  23|   1000000|     100|0.62287604|  PASSED
      rgb_lagged_sum|  24|   1000000|     100|0.70013973|  PASSED
      rgb_lagged_sum|  25|   1000000|     100|0.65860222|  PASSED
      rgb_lagged_sum|  26|   1000000|     100|0.93448843|  PASSED
      rgb_lagged_sum|  27|   1000000|     100|0.99635422|   WEAK
      rgb_lagged_sum|  28|   1000000|     100|0.29584189|  PASSED
      rgb_lagged_sum|  29|   1000000|     100|0.81313054|  PASSED
      rgb_lagged_sum|  30|   1000000|     100|0.64124408|  PASSED
      rgb_lagged_sum|  31|   1000000|     100|0.94116582|  PASSED
      rgb_lagged_sum|  32|   1000000|     100|0.96364896|  PASSED
     rgb_kstest_test|   0|     10000|    1000|0.13971491|  PASSED
     dab_bytedistrib|   0|  51200000|       1|0.65378962|  PASSED
             dab_dct| 256|     50000|       1|0.86099385|  PASSED
Preparing to run test 207.  ntuple = 0
        dab_filltree|  32|  15000000|       1|0.80254877|  PASSED
        dab_filltree|  32|  15000000|       1|0.56933154|  PASSED
Preparing to run test 208.  ntuple = 0
       dab_filltree2|   0|   5000000|       1|0.71661701|  PASSED
       dab_filltree2|   1|   5000000|       1|0.34205581|  PASSED
Preparing to run test 209.  ntuple = 0
        dab_monobit2|  12|  65000000|       1|0.80589488|  PASSED

Search

Categories

administration (40)
arduino (12)
calcpw (2)
code (33)
hardware (16)
java (2)
legacy (113)
linux (27)
publicity (6)
review (2)
security (58)
thoughts (21)
windows (17)
wordpress (19)