HertzBleed
何ができたのか
OSの電力モニタリングが制限されている時,今までデバイスに接近して何とか電力測定をしないと電力に対するサイドチャネル攻撃ができなかったけどCPUの効率化の機能のおかげで実質的にタイミング攻撃に変換できてリモートからもサイドチャネル攻撃ができた.
PQCの最終ラウンドに残っているSIKEという手法に攻撃ができた.
今まで知られていた一定時間で処理をする手法では秘密情報を守り切れない.
前提知識
P State
これはCPUの電源などの管理を行うACPIと呼ばれる規格の中でCPUが動作状態のときにその性能を制御する規格.
skylake世代意向だと100MHz単位で周波数と駆動電圧が組になっているらしい.
P stateが低い時はそのCPUがサポートする最小の周波数,高いとTurbo Boost(サポートしてないときはCPUのベースの周波数)にセットされる.
消費電力とデータの依存性
一般に処理しているデータと消費電力は何らかの依存性があることが知られている.一般的な依存関係のモデルはハミング距離(HD)とハミング重み(HW)が使われる.HDは計算中の1->0/0->1のビット遷移の数,HDは1になるビット数のみに依存するものである.
電力に対するサイドチャネル攻撃
暗号アルゴリズムを処理している時に消費電力とデータの依存関係から秘密情報を取得する攻撃.
適切な対策をしていないAES, DES, RSAやPQCの実装に対して実行し秘密鍵を当てることができる.これらはFPGAなどに実装したものに対して行うものとCPU上で実行するソフトウェアへの攻撃がある.ソフトウェアの場合はデバイスに接近しなくてもOSなどの電源モニタリング機能などを使えば遠隔から実行できるがこの機能へのアクセスを制限することでリモートからの攻撃を防げた(今までは).
周波数のリークモデルの作成のための用意
2つの実験からリークモデルの作成に必要な情報を調査している.
実験はi7-8700/9700/11700/10850H/1185G7, i9-10900Kに対して行った.
Linux kernelは4.15/5.4のデフォルト設定を使用しモデル作成のための電力測定はRAPLのMSRインターフェースを使った.
(以前RAPLを使ってsgxの秘密鍵を盗むサイドチャネル攻撃が提案された.)
命令の区別
ここではどんなワークロードがP-stateに与える影響を調査している.
stress-ngコマンドで整数算術演算のみのワークロード(int32)とそこに浮動小数点演算を含むワークロード(int32-float)の2つを実行して命令ごとの周波数の変化と電力の変化を見た.図は源論文を見てほしい.
(a)はint32-floatを実行していて,(b)はint32を実行している.
どちらもはじめはP-stateが高くBoostされており,ベースの周波数を超えている.しかし,(a)では8秒後に(b)では10秒後にP-stateが変化して周波数が変化している.さらに落ちた後の状態も異なり,(a)では3.9GHzと4.0GHzを水位して(b)では4.0と4.1を推移している.これはint32のほうが電力消費が少なくより長くP-stateが高い状態を維持できていることを示唆している.
つまり,P-Stateが一番高い状態でいる時間と周波数が落ちた後のP-stateの状態がCPUの消費電力依存していることを示していて,結局P-stateの遷移と処理しているワークロードの負荷が依存していることになる.
データの区別
さっきは処理している命令との依存関係を調査したがここでは命令で処理されるデータとの依存関係を調査している.
先述したRAPLを使ったサイドチャネル攻撃により処理しているデータと消費電力が依存していることがわかっていた.よって,ここではデータとP-stateの分布が依存しているかを調査する必要がある.
やっていることはシンプルで同じ命令に異なるデータを入れてCPUの状態を観測するだけ.
結果として入力データのHWと周波数が4.4/4.3GHzになっていたがHWが大きいほど低いP-stateにいる時間が長いくより早く低い状態に落ちることが分かった.
上記の2つの実験からデータ,命令のそれぞれがP-stateの状態と依存していることが分かった.本論文では定常状態に落ちた時のP-stateの情報をうまく使っていくことになる.
リークモデルの作成
実質的にIntel x64のALUにおける周波数とデータの依存関係を解析している.
CPUの消費電力をデータなどの関数として示すのは文章化されていない部分が多く複雑すぎるから非常に困難.
しかし,ここで焦点を当てたいのはALUの部分.なぜかというと一般的にタイミング攻撃から守られている暗号アルゴリズムはALUで主な演算を実施するからである.ここでの実験では以下の点に注意している.
- ALUの電力をできるだけ正確に取りたいのでメモリやキャッシュを使用す内容にレジスタ間の命令を使用していることに注意.(メモリやキャッシュにアクセスするとCPUのその他の部分が動作して電力のノイズが増える.)
- データパスにほかのデータが入るとパスが汚染されるので(datapath contamination effectsがいまいち理解できていない )無限ループで実行して手動で止める.
- いまいち理解できていないが想定外のHDの変化を抑制している?(to avoid introducing unintended HD effects, we inter- leave different instructions in such a way that encourages full throughput on all available ports )
さらに各実機において,以下の2つの状態で実験をしている.サンプリング周波数は1msでそれぞれ30000ポイントを取得して平均化している.
- デフォルト設定で周波数が定常状態になるまで監視しながら動かす.
- SpeedStep/HWP(P-stateを調整して最適化をするCPU上のハードウェア)を無効にして電力をはかる
HDによる影響
HDが周波数や電力とどう影響しているかを調査している.shrx, shlx命令を使って実験をしている.
これが実験のコード.
rax = COUNT
rbx = 0x0000FFFFFFFF0000
loop:
shlx %rax,%rbx,%rcx // rcx = rbx << rax
shlx %rax,%rbx,%rdx // rdx = rbx << rax
shrx %rax,%rbx,%rsi // rsi = rbx >> rax
shrx %rax,%rbx,%rdi // rdi = rbx >> rax
shlx %rax,%rbx,%r8 // r8 = rbx << rax
shlx %rax,%rbx,%r9 // r9 = rbx << rax
shrx %rax,%rbx,%r10 // r10 = rbx >> rax
shrx %rax,%rbx,%r11 // r11 = rbx >> rax
jmp loop
x64 cpuでこれらの命令は2つのポートで実行されるから2つずつの組で実行している(よくわからない)
やっていることはCOUNTの回数分rbxを左右にシフトしている.つまり,ALUの出力は変化しないが内部では0/1->1/0遷移をしている.
これをCOUNTを変えつつHDがどのくらい影響しているかを実験するコードになっている.
結論としてはCOUNTが大きい,つまりHDが大きいほど消費電力が大きく周波数が低下することがわかった.
HWによる影響
前節と同じようにHWの影響を調査している.0/1->1/0遷移をさせないようにコードを組む必要がある.
rax = LEFT
rcx = ... = r11 = RIGHT
loop:
or %rax,%rcx // rcx = rax | rcx
or %rax,%rdx // rdx = rax | rdx
or %rax,%rsi // rsi = rax | rsi
or %rax,%rdi // rdi = rax | rdi
or %rax,%r8 // r8 = rax | r8
or %rax,%r9 // r9 = rax | r9
or %rax,%r10 // r10 = rax | r10
or %rax,%r11 // r11 = rax | r11
jmp loop
or演算のソースを左,宛先を右に固定している.例えばraxにHWに対応した値をいれてrcx~r11を固定させることでそのHWに対応するときの電力を見ることができる.こうするとALUの出力は変化せず,raxのHWの変化による影響を調査できる.
初めにLEFT=RIGHTとして値を連続する1を入れてそれぞれのHWの影響を調査したところ先頭/末尾の1が長く連続するほど消費電力が増大し周波数が低下した.また,図を見るとわかるが明らかに結果が線形ではなく上位bitのほうが影響が大きいことがわかる.つまり同じHWでも1の位置の違いを判別できる可能性があることを示唆している.
次に不連続な1について調査をしている.これは64bitを8bitごとに分けて実験をしている.その結果としては連続しなくとも1の数が多いほど消費電力が大きく周波数が低下していた.
最後に1の位置による影響を調査する必要がある.