Hardware-Zufallszahlengenerator des Raspberry Pi nutzen

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 soll einen bekommen.

Spannenderweise enthält auch der Broadcom-Chip des Raspberry Pi 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 aus: "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:

1
cat /proc/cpuinfo

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
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:

1
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 wieder per CTRL+C:

1
2
sudo rngd -f
^C

Euch sollten nun die verschiedensten Statistiken angezeigt werden, unter anderen, wieviele FIPS 140-2 Tests erfolgreich bestanden wurden (mit diesen wird die Qualität der Zufallszahlen ermittelt):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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:

1
bcm2708_rng

Na dann wünsche ich euch viel Spaß mit eurem eigenen Hardware-Zufallszahlengenerator. 🙂

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

1
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 den gesamten November über:

1
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 jedoch durchaus mal vorkommen kann:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#=============================================================================#
#            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

Zufällige Grüße, Kenny

Schreibe einen Kommentar

Um Ihnen beim weiteren Kommentieren auf dieser Webseite die erneute Eingabe Ihrer Daten zu ersparen, wird beim Absenden Ihres Kommentars ein Cookie an Ihren Browser gesendet und von diesem gespeichert. Mit dem Absenden eines Kommentars auf dieser Webseite stimmen Sie der Speicherung und Übertragung dieses Cookies explizit zu.

Pflichtfelder sind mit * markiert.