FIA
ここまでで,ハードウェアが忠実に動作してくれるという前提を FIA によって壊すという背景を説明しました. ここでは,なぜその前提が壊れるのかを説明したいと思います
0/1 の解釈
コンピュータは 0/1 で構成されていると思えますが,実際の物理の世界には 0/1 という離散的な値は存在せず,電圧という連続的な量が存在します. ハードウェアは,ある信号の電圧を測ってこれが 0 か 1 かを判定しています. この判定はあらかじめ決めたしきい値で決定されます. つまり,0 と 1 は物理的な実体をあらわしているわけではなく,「この電圧範囲を高解釈しよう」という約束事を表現しているにすぎません. そして,あらゆる約束がそうであるように,この条件が満たされている限りにおいてのみ物事が成立します.
スイッチ
では,この電圧はどのように作られてどのように操作されるのでしょうか? その多くはトランジスタによって実現されています. トランジスタは,単純化すれば,別の電圧によって ON/OFF が切り替わるスイッチの機能をもちます(村田製作所). このスイッチを組み合わせると,論理ゲートを作ることができます. 最も簡単な例は,インバータ(NOT)です(Youtube).
- 入力が「1」のとき,出力を「0」につなぐスイッチが入る
- 入力が「0」のとき,出力を「1」につなぐスイッチが入る
こうして,「1 を入れたら 0 が出る」という論理が,物理的なスイッチの開閉として実現されます.
実際のトランジスタを観察したとき,よく言われるのは,スイッチの切り替えは一瞬では終わらないという点です. 入力信号が変化したら出力信号も素早く変化するのが理想ですが,実際には遅延が生じます. 入力信号の変化に対して,出力が変化するまでの反応時間を伝搬遅延時間といいます.
ゲートを何弾も接続すればこの遅延は積み重なります. 入力が変化してからすべての信号が伝わりきって確定(settle)するまでには,その回路の中で最も遠回りな経路の分だけ時間がかかります. この最長経路をクリティカルパスと呼びます.
例えば池に石を投げたときを想像してみます. 波紋が対岸に届く前に水面の高さを測っても,正しい値を得ることはできません. 信号が確定していない途中で結果を読み取ると,読み取れるのは中途半端な値のみです. なので,いつ信号を読み取るべきか,を全員で合意する必要があります
クロック
CPU の中では,計算結果をいったん保持しておく記憶素子が使われます(フリップフロップ). フリップフロップはクロックという周期的な合図のエッジ(立ち上がり)で入力を一度読みとり,次の合図まで値を保持します. クロックは時間を細かい区間で区切ります. 1サイクルの中で起こることは,毎回同じ順序で起こります.
ここに,新しい約束が決められています. それは,クロックの周期は,「信号がレジスタから出発し,すべてのゲートを通り抜け,次のレジスタで確定するまでの時間」よりも長くなければならないという点です. 式で書けば,以下のようになります.
クロック >= 送り出しの遅延 + クリティカルパス + セットアップ時間 + ホールド時間
セットアップ時間は,データ入力をクロックの立ち上がりエッジの前に安定させておくべき最小時間です. ホールド時間は,データ入力がクロックの立ち上がりエッジの後に安定して保持すべき最小時間です. この期間内にデータが入ってくると,正しく動作しないことがあります. こういった時間や電圧の約束事を守らなければ,出力が 0 になっても 1 になってもそれ以外になっても文句は言えません.
FIA
クロック >= 送り出しの遅延 + クリティカルパス + セットアップ時間 + ホールド時間
という関係において,攻撃者が操作できる値があります
- クロックグリッチ:正規のクロックに,異常に短いパルスを一瞬だけ入力します.すると,そのサイクルだけ計算時間が短くなり,まだ確定していない中途半端な値がレジスタに取り込まれます.これは左辺を縮める操作に該当します.
- 電圧グリッチ:電源電圧を一瞬だけ落とすと,ゲートが遅くなります.クリティカルパスの遅延が伸び,クロック周期に収まりきらなくなり,確定前に読み取られます.これは右辺を縮める操作に該当します.
そして,しきい値のちょうど境目にある信号を無理に読み取らせると,フリップフロップが不安定な状態になり,最終的にどちらへ転ぶか分からなくなります. (厳密には違いますが)このような状態をメタステーブル状態といいます.
このような流れで 1 bit が壊れるわけですが,この 1 bit の違いは,どこでそれが起きたかによって中身が変わります.
- データ:計算結果が変化する
- 命令:命令スキップや命令の変化
- 分岐・フラグ:本来は失敗と判定されるべきチェックが成功と読み替えられる
いずれも場合も,プログラムや実装自体はうまくいっているにもかかわらず,攻撃者の外乱によって「ハードウェアは命令通りに動く」という仮定を乗り越えていることになります.