OneRNG: Installation und Test

by Niklaus 'vimja' Hofer on 2017-03-13

OneRNG ist ein Open Hardware Zufallszahlengenerator. Da als USB Gerät aufgebaut, lässt er sich an nahezu jedem Computer nutzen. Allgemeine Informationen zum OneRNG findest du auf der Website des Projektes, auf deren Kickstarter Kampagne oder in einem LWN.net Artikel von 2015. Das Projekt hat auch eine etwas technischere Dokumentation.

Nachdem der OneRNG lange Zeit nicht geliefert werden konnte, startete in Januar dieses Jahres der Verkauf erneut. Jenix hat eine Gruppenbestellung organisiert. Vor etwa zwei Woche dann sind unsere Einheiten eingetroffen. In diesem Artikel möchte ich mit euch teilen was ich gelernt habe.

Installation

Auf der Verpackung des OneRNG ist eine URL abgedruckt die zu der offiziellen Installationsanleitung führt. Diese enthält neben den nötigen Schritten zum Einrichten der Software auch Instruktionen um die Hardware auf etwaige Manipulationen zu prüfen. Für Nutzer von Debian basierten Distributionen sowie Distributionen welche das rpm Paketformat verwenden, stehen fertige Software Pakete zum Download bereit. Für alle anderen sind die vorhandenen Instruktionen leider etwas dürftig. Das gilt insbesondere, wenn man seine eigenen Kernel kompiliert.

Im Grunde werden nur einige wenige Skripte installiert:

  • /lib/udev/rules.d/79-onerng.rules ist eine udev Regel welche entsprechende Aktionen auslöst sobald der OneRNG angeschlossen oder vom Computer entfernt wird.
  • /sbin/onerng_verify.py ist ein Python Script welches die Firmware des OneRNG prüft. Zu diesem Zweck enthält das Script den öffentlichen GnuPG Schlüssel des Projektes.
  • /sbin/onerng.sh wird von der oben erwähnten udev Regel aufgerufen. Grob tut es diese vier Dinge:
    • Die Hardware initialisieren
    • Die Firmware überprüfen (mit Hilfe des oben erwähnten Python Script)
    • Die Zufallszahlen des OneRNG nutzbar machen. Dazu verschlüsselt es die rohen Daten des OneRNG mit OpenSSL und gibt sie dann weiter an den rngd. Dieser wiederum gibt diese an den Kernel weiter um dessen Entropie-Pool zu befüllen.
    • OpenSSL sowie den rngd stoppen wenn der OneRNG vom Computer entfernt wird.

Zwar verwende ich persönlich Gentoo, ich habe aber auch geholfen, den OneRNG auf einem Arch Linux System zu installieren. Die einzelnen Schritte sollten sich von Distribution zu Distribution nicht allzu sehr unterscheiden.

Kernel

Das Gerät braucht den CDC ACM Treiber. Die Kernel Konfiguration Option dazu heisst CONFIG_USB_ACM. Im menuconfig findet sich die Option wie folgt:

    Device Drivers  --->
       [*] USB support  --->
           <M>     USB Modem (CDC ACM) support

Persönlich rate ich dazu, den Treiber als nachladbares Modul zu kompilieren. Das Modul heisst dann cdc_acm.

Abhängigkeiten

Die OneRNG Software hat einige Abhängigkeiten:

  • rngd - ein Daemon um Entropie an den Kernel zu übergeben. In den meisten Distributionen ist er in einem Paket namens "rng-tools" enthalten.
  • at
  • python-gnupg - ein Python Interface zu GnuPG

Unter Gentoo können die Pakete wie folgt installiert werden:

emerge -av \
    sys-process/at \
    dev-python/python-gnupg \
    sys-apps/rng-tools

Der Dienst atd muss gestartet sein wenn der OneRNG mit dem Computer verbunden wird. Damit der Dienst nicht jedes Mal manuell gestartet werden muss, kann er einfach zum default runlevel hinzugefügt werden:

# OpenRC
rc-update add atd
/etc/init.d/atd start
/etc/init.d/atd start

# Systemd
systemctl enable atd
systemctl start atd

Leider hat die in Gentoo paketierte Version von python-gnupg (0.3.8) nicht funktioniert. Offenbar ist das mitgelieferte Script zum Prüfen der Signatur für eine neuere Version ausgelegt welche die Ausgabe anders formatiert. Dadurch ist die Firmware Prüfung fehlgeschlagen und der OneRNG liess sich nicht nutzen. Um das Problem zu lösen, habe ich dem Nutzer root per pip eine neuere Version der Bibliothek installiert:

pip install --user python-gnupg

Die so installierte Version landet im Verzeichnis /root/.local/lib64/python3.4/site-packages/ und wird von Python automatisch genutzt.

Software

# Lade den Tarball von Github runter
cd /usr/src
wget https://github.com/OneRNG/onerng.github.io/raw/master/sw/onerng_3.5.orig.tar.gz

# Entpacke den Tarball
tar xzvf onerng_3.5.orig.tar.gz
cd onerng_3.5

# Installiere die Software
./configure
make install

# Lade alle udev Regeln neu damit die soeben installierte aktiv wird
udevadmin control --reload-rules

Testen

Um zu evaluieren ob der OneRNG funktioniert, lohnt sich ein Blick auf den Zufälligkeits- / Entropie-Pool des Linux Kernels. Zu Beginn hat der Pool einen gewissen Wert. Wir werden den Pool leeren und dann beobachten wie schnell er sich wieder füllt.

Um sicher zu gehen, dass die beobachteten Effekte auch tatsächlich durch den OneRNG hervorgerufen werden, ist es wichtig, dass wir vorher alle anderen eventuell aktiven Instanzen des rngd stoppen:

# Auf Systemen die SysV-init oder OpenRC verwenden
/etc/init.d/rngd stop

# Auf Systemen welche systemd verwenden
systemctl stop rngd

# Stoppen manuell gestarteter rngd Prozesse
until ! killall rngd; do continue; done

Um einen neutralen Vergleichswert zu haben, sollten die ersten Tests ausserdem durchgeführt werden, während der OneRNG nicht mit dem Computer verbunden ist.

Du kannst den Wert des Entropie-Pool des Kernels mit dem folgenden Kommando abfragen. In der Regel steigt der Wert bis auf etwas über 3800.

cat /proc/sys/kernel/random/entropy_avail

Um den Pool zu leeren, benutze untenstehendes Kommando. Nach wenigen Sekunden kannst du den Prozess abbrechen durch drücken von ctrl+c.

cat /dev/random > /dev/null

Anschliessend prüfe den Wert des Entropie-Pools erneut. Er sollte nun viel tiefer sein. Wenn du ihn jetzt noch einmal misst, kannst du sehen, dass er stetig aber langsam ansteigt.

Schliesse nun den OneRNG An und wiederhole das Experiment. Falls der OneRNG korrekt funktioniert, sollte sich der Pool innert Sekunden wieder füllen.

Hier ist ein kurzes Script welches du als Ganzes in eine frische Shell kopieren kannst. Es führt alle oben genannten Schritte aus:

cat << EOF | bash
echo -n "Randomness avialable at the start: "
cat /proc/sys/kernel/random/entropy_avail

echo "Emptying randomness pool"
cat /dev/random > /dev/null &
sleep 1
kill %1

echo -n "Randomness just after depletion: "
cat /proc/sys/kernel/random/entropy_avail
sleep 1
echo -n "Randomness one second after depletion: "
cat /proc/sys/kernel/random/entropy_avail
EOF

Hier die Werte von meinem System zum Vergleich:

# Ohne OneRNG
Randomness avialable at the start: 2554
Emptying randomness pool
Randomness just after depletion: 22
bash: line 10: 10318 Terminated              cat /dev/random > /dev/null
Randomness one second after depletion: 143

# Mit OneRNG
Randomness avialable at the start: 3116
Emptying randomness pool
Randomness just after depletion: 7
bash: line 10: 10381 Terminated              cat /dev/random > /dev/null
Randomness one second after depletion: 3100

Anhand des Entropie-Pool Wertes eine Sekunde nach dem leeren Desselbigen ist klar ersichtlich, wie viel schneller sich der Pool füllt wenn der OneRNG mitwirkt.

Fehlersuche

Es kann frustrierend sein wenn Hard- oder Software nicht funktioniert, insbesondere wenn man nicht weiss woran es liegt und wo man mit der Fehlersuch ansetzen soll. Deshalb möchte ich hier einige einfache Mittel zeigen um den OneRNG und die gelieferte Software zu debuggen. Die folgenden Kommandos werden am besten als Root ausgeführt.

  • Wenn die Software funktioniert, leuchtet am OneRNG nach dem Einstecken eine orange LED auf die für die gesamte Betriebsdauer weiter leuchtet
    • Während intensiv Entropie vom OneRNG gezogen wird, leuchtet die LED weniger hell. Das lässt sich mit dem folgenden Kommando ganz einfach testen cat /dev/random > /dev/null
  • Stelle sicher, dass das Kernel Modul geladen ist. Das Modul heisst cdc_acm. Die geladenen Module kannst du dir mit dem Kommando lsmod anzeigen lassen. Das Modul sollte automatisch geladen werden sobald der OneRNG eingesteckt wird. Sollte das nicht der Fall sein, kann das Modul mit modprobe cdc_acm auch manuell geladen werden.
  • Nachdem der OneRNG mit dem Computer verbunden wurde, kann mittels dmesg überprüft werden, ob er vom Kernel korrekt erkannt worden ist:
[105837.526045] usb 1-1.2: new full-speed USB device number 8 using ehci-pci
[105837.609531] usb 1-1.2: New USB device found, idVendor=1d50, idProduct=6086
[105837.609535] usb 1-1.2: New USB device strings: Mfr=1, Product=3, SerialNumber=3
[105837.609537] usb 1-1.2: Product: 00
[105837.609539] usb 1-1.2: Manufacturer: Moonbase Otago http://www.moonbaseotago.com/random
[105837.609541] usb 1-1.2: SerialNumber: 00
[105837.610312] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device
  • In der letzten Zeile ist der Name des Devices ersichtlich. Dieser kann genutzt werden um das Gerät im Dateisystem zu finden:
ls /dev/ttyACM0 && file /dev/ttyACM0
/dev/ttyACM0
/dev/ttyACM0: character special (166/0)
  • Mit dem Kommando lsusb (meistens aus dem Paket "usbutils") können alle verbundenen USB Geräte aufgelistet werden. Darunter sollte sich auch der OneRNG finden. Die Bus- und Device-Nummern sind von Computer zu Computer unterschiedlich wohingegen die ID immer dieselbe ist:
[...]
Bus 001 Device 008: ID 1d50:6086 OpenMoko, Inc.
[...]
  • Das Script startet zwei Prozesse:
    • rngd -f -n 1 -d 1 -r /dev/stdin
    • openssl enc -aes128 -nosalt -in /dev/ttyACM0 -pass file:/dev/ttyACM0 -out /dev/stdout

Sie sollten beiden im Output dieses Kommandos erscheinen: ps -faux | grep -e openssl -e rngd. Hier die Ausgabe von meinem System:

root     10947  0.0  0.0  11516   884 pts/1    S+   01:09   0:00              \_ grep --colour=auto -e openssl -e rngd
root     10376  0.0  0.0  15896  3732 pts/1    S    00:58   0:00 openssl enc -aes128 -nosalt -in /dev/ttyACM0 -pass file:/dev/ttyACM0 -out /dev/stdout
root     10377  0.0  0.0   9488   836 pts/1    S    00:58   0:00 rngd -f -n 1 -d 1 -r /dev/stdin
  • Das Resultat der Signaturprüfung der Firmware wird in die System-Logs geschrieben. Auf meinem System landet die Nachricht in /var/log/messages. Hier sind Beispiele für erfolgreiche und fehlgeschlagene Firmwareprüfungen:

Erfolgreich verifizierte Firmware

Mar 12 00:58:17 pcsm1501 OneRNG[10341]: firmware verification passed OK - version=3

Invalide Firmware / erfolglose Firmware Prüfung

Mar  9 19:25:45 pcsm1501 OneRNG[14816]: firmware verification failed: Invalid firmware signature: 3
  • Es kann helfen das Script zum Initialisieren der Hardware manuell aufzurufen, da dabei Informationen ausgegeben werden die bei der Fehlersuche hilfreich sein können. Damit der Aufruf funktioniert, muss das korrekte ttyACMn Device an das Script übergeben werden. Das korrekte Device kann mit Hilfe von dmesg ermittelt werden. Nachfolgend ein erfolgreicher Aufruf als Beispiel:
/sbin/onerng.sh daemon ttyACM0
/sbin/onerng.sh: line 192: 11415 Terminated              dd if=/dev/$2 iflag=fullblock of=$t bs=1
/sbin/onerng.sh: line 192: 11420 Terminated              dd if=/dev/$2 iflag=fullblock of=$t bs=4
nohup: redirecting stderr to stdout