IoT何をいまさら(92) ATSAMD51、TRNG、「真性」乱数ジェネレータ

Joseph Halfmoon

近代的なマイコンの多くにはセキュリティ目的の周辺回路が含まれており、Microchip社ATSAMD51マイコンも例外ではありません。本日はその中からTRNG(True Random Number Generator)、真性乱数生成器を使ってみたいと思います。乱数素人なので乱数についてどうこうできるわけではないのですが。

※「IoT何をいまさら」投稿順Indexはこちら

(末尾に実験に使ったCのコード全文を掲げました。)

セキュリティどころか乱数そのものを使おうというわけでなく、後の回でイベントと割り込みの発生源として使いたい、という邪な目的でTRNGしてみているのです。でもま、折角なのでTRNGについて簡単に調べてみました。

ご存じのとおり、乱数には算術使って生成できる「疑似」乱数と、物理現象などから値を予測しえない「真の」乱数があります。古典的なマイコンでは内蔵回路で真の乱数を発生できるようなものはまず無く、また、昔はあまり切実な要求が無かったので「なんちゃって」疑似乱数でお茶を濁していた気がします(個人の感想です。)

しかし、ネット世界に接続するIoTの世界では、「素性の確かな」乱数が必須。SAMD51のデータシートをみたところ、SAMD51のTRNGは具体的な方式は不明(どこかに説明あるのかな?)ながら真の乱数を生成するもので、以下のテストをパスしていると書かれています。乱数素人にはそのテストがどんな位置づけのものだか分からないので、該当のテストへのリンクを貼り付けておきます。

    1. American NIST Special Publication 800-22
    2. Diehard Random Tests Suites

2番目のテストは「1995年にCD-ROMで発行された」、「乱数業界」では由緒正しい古典のようです。以下のフロリダ州立大のサイトからCD-ROMの内容(テスト用のプログラムソース含む)を読むことができるようです。

The Marsaglia Random Number CDROM including the Diehard Battery of Tests of Randomness

上記の「古典」に加えて、TRNGには近代的な規格への対応ももとめられるようです。SAMD51のデータシートから1か所引用させていただきましょう。

The TRNG may be used as an entropy source for seeding an NIST approved DRNG (Deterministic RNG) as required by FIPS PUB 140-2 and 140-3.

このTRNGそのもので米国連邦政府の規格を満たせるわけではなく、規格にそうための “entropy source” に ”may be used” ということであります。なんじゃらほい。ちょうど、Microsoft社が、FIPS PUB 140-2に対応する自社製品についての説明(日本語)をだされていたので以下にリンクを貼っておきます。

連邦情報処理標準 (FIPS) 文書 140-2

これみると、FIPS PUB 140-2とか-3とかへの対応が最近の乱数生成には求められておるのだな、と納得。ほんとか。

また、真性乱数ジェネレータに関する日本語文書では以下の2つのURLをメモっておきます。

東芝レビュー2003年8月 高度情報セキュリティ向け 超小型乱数生成回路

Renesas かふぇルネ RL78で真性乱数生成器(TRNG)

「かふぇルネ」という緩いタイトルのもと、乱数素人の私にはついていけないディープな議論をWeb上で繰り広げているルネサスRL78。ルネサス奥深いのか泥縄なのか?

今回作成の実験プログラム

SAMD51のTRNGは、イネーブルにするとAPBクロックで84サイクルという一定のクロック数毎に32ビットの乱数を生成してくれます。後で、割り込みとイベント受けで書きなおそう(割り込みとイベントのテストのために)などと考えているのですが、今回は、乱数の「出来上がり」をソフトウエアでポーリングして読み取る方法であります。

操作の準備(setupTRNG)として

    1. MCLKモジュールからAPBクロックをTRNGへ供給許可
    2. とりあえずTRNGはディスエーブルにしておく(ディスエーブル状態でないと操作できない制御レジスタがある。使ってないケド)

測定開始(startTRNG)は、

    1. 割り込みフラグ(乱数出来上がりで立つ)を念のためクリアしておいて
    2. TRNGをイネーブルにする(生成開始)

結果の読み取り(pollReadTRNG)は、

    1. 生成完了で割り込みフラグが立つまで待つ(一応タイムアウトを数えて無限ループに入らないようにしている)
    2. 結果が出たらTRNGをディセーブル
    3. データを返す(データ読み出しで自動的に割り込みフラグがクリアされる)

以上のステップです。

実際の実行例は以下に

ATSAMD51 TRNG test sample.
488923966
1875932677
3303330074
2517201019
1843281578
1006022493
1818758223
1473604842
1640868516
~以下略~

この乱数の良し悪しを云々する気は毛頭ありませぬが、とりあえずTRNGは動作しておる「みたい」と。割り込みとイベントはまた次回ですな。

IoT何をいまさら(91) ATDAMD51、CCL、極小のオンチップFPGA へ戻る

IoT何をいまさら(93) ATSAMD51、内蔵ペリフェラルの割り込み受け に進む

実験に使ったソース全文(ATSAMD51P19A搭載Wio Terminalで動作確認)
#include <Arduino.h>

void setupTRNG() {
  MCLK->APBCMASK.bit.TRNG_ = 1; //Enable CLK_TRNG_APB
  TRNG->CTRLA.bit.ENABLE = 0;   //Disable TRNG 
}

void startTRNG() {
  TRNG->INTENCLR.bit.DATARDY = 1; //Clear Interrupt Flag
  TRNG->CTRLA.bit.ENABLE = 1;     //Enable TRNG 
}

int pollReadTRNG(uint32_t *datReturn) {
  int timeout = 5;
  while (!TRNG->INTFLAG.bit.DATARDY) {
    if (--timeout < 0) {
      return 0; //Error return.
    }
  }
  //Serial.println(timeout);
  TRNG->CTRLA.bit.ENABLE = 0;   //Disable TRNG 
  *datReturn = TRNG->DATA.reg;  //Reading DATA register make INT flag clear.
  return 1; //OK
}

void setup() {
  Serial.begin(9600);
  while(!Serial);
  Serial.printf("ATSAMD51 TRNG test sample.\r\n");
  setupTRNG();
}

void loop() {
  uint32_t dat;
  startTRNG();
  if (pollReadTRNG(&dat)) {
    Serial.println(dat);
  } else {
    Serial.println("TRNG timeout");
  }
  delay(2000);
}