JCMVP観察していた日記

my thoughts to JCMVP

ソフトウェアライブラリにおける鍵生成のあれとこれと/dev/random

ソフトウェアライブラリで毎回頭を悩まされるのが、鍵生成のためのSEEDの確保です。HSMを初めとする、物理的な暗号モジュールの場合はTRNGのチップを用意することや、工場出荷時の段階でSEEDを書き込んでおいてそれを使用する、という逃げ道があるのですがソフトウェアライブラリではそうはいきません。
一方、FIPS 140-2においては、鍵生成を行う際には生成する鍵と同等レベルの強度を要するSEEDを用意する、という要件があります。ですので、256ビットのAES鍵を生成する場合は、SEEDも256ビットの強度を用意していなければなりません*1。実際には、SP 800-57で求められる強度を保有していれば良いのですが、それでも112ビットの強度をどうやって用意するの?という問題は永遠につきまといます。そこで逃げ道がいくつかあります。
1. SEEDの用意は暗号境界の外です、と利用者に責任をなすりつける
これが一番簡単な方法です。ライブラリとしては入力されたSEEDをそのまま信じるので、利用者が適切な強度を保有するSEEDを用意してね、となります。時間とか、時間とか、時間とか、時間とかを誤って利用者がSEEDとして使っても知らんぷりです。ソフトウェアライブラリが取得可能なFIPS 140-2の最高レベルは2であり、そのなかではモジュールがFIPS modeで動いているかどうかを確認できるようにする、という要件はないので、うっかり利用者が時間とか、時間とか、時間とか、時間とかをSEEDとして使用していて、non FIPS modeでモジュールが動いていても分かりようがありません。親切ですね。
2. 自前のTRNGもどきのDRNG*2を用意する
いくつかのライブラリではあるのですが、決定的な関数を使ってなぜか非決定的な値を作れるDRNGを開発します。この時に試験機関はそのDRNGがちゃんとしたセキュリティかどうかを試験しないといけないないのですが、そこは緩い試験機関を使えば大丈夫です。今は知りませんが、昔、とある試験機関*3ではSEEDは80ビット以上の長さであれば何でもいいんだよ、と言われて計りきれない衝撃を受けました。
3. OSが用意してくれているDRNGを利用する
Windowsの場合はCryptGenRandom、*NIXの場合は/dev/randomを使います。OSがアクセス可能な処理できっと乱数性があるであろうものをエントロピープールにいれておいて、そこである程度乱数っぽくなったら加工して吐き出してくれます。2点目のDRNGよりも深い領域でOSはアクセスできますし、アクセスする情報は通常のAPIではコールできないものも含まれます*4ので、信頼性はこちらの方が増すのかな、と思います。ただ、/dev/randomってどうなのよ感が定期的に沸き上がります。

/dev/randomですと、エントロピープールに情報をため込んでおいて、SHA-1で最後にハッシュして値を吐き出します。

The random number generator gathers environmental noise from device drivers and other sources into an entropy pool. The generator also keeps an estimate of the number of bits of noise in the entropy poo. From this entropy pool random numbers are created.

という記述がManページにはあります。この記述を利用者は信じて多くの利用者は256ビットの値を/dev/randomから吐き出したら256ビットの強度だよ!やったね!、という理論を作ります。その気持ちは分かるのですが、果たしてソフトウェアだけのDRNGでエントロピーが担保されている高品質の乱数を生成できるのでしょうか…*5。さらに、/dev/randomは吐き出す際にSHA-1でハッシュした値を出力します。そうすると、SHA-1の強度って?うんうん?と思わずにはいられません。いくつかのSecurity PolicyにはSHA-1で加工した値になるから160ビットの強度に限定されるよ、と書いてありますし、2030年までは128ビットの強度で問題ないとNISTが認めているので、160ビットの強度で十分なのかとも思いますが。
いずれにしろ、ソフトウェアライブラリにおいて、鍵生成は困難なのは変わりませんし、おなじFIPS 140-2を取得している、といっても程度の差は顕著です。個人的には、ソフトウェアライブラリ単体で高品質の乱数を生成するのは困難ですのでOSに任せてしまうのがベストかとも思います。その点ではMSはCSPも基本的にはFIPS 140-2認証を取得しているので未だ信用できる感があるのですが/dev/random自体の第三者評価ってどこもやっていないですよね…*6

*1:この要件にはさんざん泣かされました…。

*2:Deterministic Random Number Generator。SP 800-90ではDRBG:Deterministic Random Bit Generatorと定義していますが、好き好きの問題と思い込んでいます

*3:いまはどこかに買収されています

*4:むかーーーーし、MSの方にその様に回答頂きました。*NIXは知りません

*5:むかし、MSのCryptGenRandomの乱数を調べた際には、ある程度の品質は認められたものの、フルエントロピーの乱数とは認められない、と第三者に評価されました

*6:いや、組み込み機器でLinuxベースの場合はそこに含まれるとは思いますがLinuxが用意している暗号周りの機能に関するFIPS 140-2認証は知りません。あるのなら教えてください…。