1. NeuG True RNGの使い方

NeuGとはTrue RNG (Random Number Generator)の実装で、STM32F103で動きます。ADC(A/D変換器)のノイズを乱数の源(エントロピー源)として使います。

狭義には、NeuGはTrue RNGのためのルーチンを指し、Gnukにも採用されて使われています。

NeuGスタンドアロン・デバイスは、USBデバイスとして “NeuG True RNG” という文字列を持ちます。この、スタンドアロン・デバイスは、狭義のNeuGのルーチンを組み込んだデバイスのことです。これは、OSからはUSBのCDC(Communication Device Class)として見え、たとえばGNU/Linuxでは /dev/ttyACM0 としてアクセスできます。

1.1. NeuGの諸元

以下に、NeuGの諸元を示します。

  • STM32F103で動く。FST-01をはじめとしたボードで実績がある。
  • 70KiB/secで乱数を生成できる。
  • SHA-256のコンディショニング・コンポーネントを持つTrue RNGである。
  • エントロピー源は、ADCのVref(電圧リファレンス)、温度センサ、接続されていないアナログ入力(IN0, IN1)を使用。
    • 量子化誤差と電源電圧の揺れなどが、エントロピーの源と考えられる。
    • STM32F103のADCの解像度は12-bitである。
  • NIST SP 800-90B (draft)を参考に設計した、”Full Entropy Source”である。
  • 生成された乱数列は、NIST STS 2.1.1, Dieharder 3.31, Test U01 1.2.3, PractRand 0.90で評価し、良い成績を出している。

1.2. 利用の仕方

CDCデバイスの出力として、乱数のバイト列が生成されます。また、設定により、生のADC出力データ、SHA-256処理前のデータ、および、SHA-256処理後のデータの3種類のバイト列を選択できます。

デバイスから出力される乱数のバイト列を、OSのカーネルにフィードすることで、システムが必要とするエントロピーを供給することができます。

以下では、各システムについて、カーネルへのエントロピー供給の方法を述べます。GNU/Linuxについて説明します。同様にGNU/Hurdでも使えると考えられます。

FreeBSDやMac OS Xでも使えると考えられます(まだ試した方はいないようです)。

1.2.1. GNU/Linux

CDCデバイスとして /dev/ttyACM0 としてアクセスすることになります。

カーネルへのエントロピー供給には、ソフトウェアrng-toolsを使います。

通常、rng-toolsはinit scriptから起動されるようになっていますが、ここでは、プラグ・アンド・プレイで起動する設定を説明します。

下記のように、udevの設定ファイルを作り、たとえば、/etc/udev/rules.d/90-neug.rulesとします。

KERNEL=="ttyACM[0-9]*", SUBSYSTEMS=="usb", ACTION=="add", \
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0001", \
RUN+="/etc/udev/ctrl_rng.sh"

KERNEL=="ttyACM[0-9]*", SUBSYSTEMS=="usb", ACTION=="remove", \
ATTRS{idVendor}=="234b", ATTRS{idProduct}=="0001", \
RUN+="/etc/udev/ctrl_rng.sh"

これは、CDCデバイスとして認識された時と、CDCデバイスがなくなった時に、スクリプトを実行する設定です。(この他にUSBデバイスが検出された時、USBデバイスが抜かれた時のイベントがあります。)

実行するスクリプトは、/etc/udev/ctrl_rng.shとしてファイルを作成します。

#! /bin/sh

PIDFILE=/var/run/rngd.pid

case "$ACTION" in
add)
  stty -F $DEVNAME raw -echo -parenb
  /usr/sbin/rngd --fill-watermark=90% --feed-interval=1 --rng-device=$DEVNAME
  ;;
remove)
  # This will be called twice, since there are two interfaces for the device.
  # Called once for 10/0/0, another for 2/2/1.
  if [ x$INTERFACE = x"2/2/1" -a -f $PIDFILE ]; then
      kill -TERM `cat $PIDFILE`
      rm -f $PIDFILE
  else
      exit 0
  fi
  ;;
esac

exit 0

ファイルを作成したら、実行権限を付加してください。

この設定で、NeuGスタンドアロン・デバイスがUSBポートに挿入されると、自動的にrngd (rng-toolsのデーモン)が起動します。

マニュアルには、SIGTERMでrngdは終了すると書いてありますが、現行の実装では実際は(すぐに)終了しないこともあるようです。いずれにしろ/dev/ttyACM0がなくなれば結局はrngdは終了するので、上記のスクリプトのままで問題ありません。

カーネルに十分なエントロピーが供給されているかどうかは、たとえば、watchコマンドを下記のように実行し、確認できます。

$ watch cat /proc/sys/kernel/random/entropy_avail

この値が、一桁や二桁の数字の場合、十分なエントロピーはカーネルにありません。十分なエントロピーが供給されていて、システムでのエントロピーの消費が激しくなければ、これは3840などの値になるでしょう。

1.3. どのような場合にNeuGスタンドアロン・デバイスは有用か

暗号化/復号化、電子署名、認証など、暗号に関する処理にはさまざまなものがありますが、アプリケーションが品質の高いエントロピーを必要とする場合が、まま、あります。

たとえば、一般に、暗号の鍵生成では、品質の高いエントロピーが求められます。これは、十分なエントロピーが得られない場合では、暗号の安全性に問題が生じる可能性があるからです。(問題としては、たとえば、生成される鍵のビットパターンに偏りが生じ、実質的な鍵の空間が狭まってしまうことが考えられます。)

また、nonceと呼ばれる一度だけ使うバイト列が、暗号化、電子署名、認証で使われることが、よくあります。これに関しても、品質の高いエントロピーが求められます。

量の観点でみると、暗号処理を多く利用するシステムでは、システムがアプリケーションに十分な量のエントロピーを供給できることが求められます。

たとえば、GnuPGの鍵をたくさん生成する場合、あるいは、多くのSSL/TLSの暗号通信を行う場合、NeuGスタンドアロン・デバイスを用いて、品質の高い十分なエントロピーをカーネルに供給することが有用でしょう。