本発明は、例示的な実施形態に関して説明される。当業者は、本発明が多くの異なる用途及び実施形態で実装され得、特に本明細書に図示される特定の実施形態にその応用が制限されていないことを理解する。
本発明の例示的な実施形態は、標準的な(非ホワイトボックス)実装のソースコードから直接的に任意の暗号アルゴリズムのホワイトボックス実装を自動的に生成するためにホワイトボックス実装を生成する方法に関する。
別の例示的な実施形態は、秘密データが動的である、つまり実行時にだけ知られるホワイトボックス実装を生成する方法に関する。
別の例示的な実施形態は、ホワイトボックス実装がアウトオブコンテキストで使用される、つまりその使用目的のためにアプリケーションによってよりむしろ、悪意のある目的のために攻撃者によって直接的に呼び出されるのを防ぐ方法に関する。これらのそれぞれは以下に同様に説明される。
図1は、本発明の例示的な一実施形態を実践するために適した環境を示す。電子装置CMPは、本発明の一実施形態に係るソフトウェアが記憶されるメモリMEM、メモリMEMに記憶されているソフトウェアを実行するためのプロセッサ(CPU)PRC、及びシステムハードウェアを制御するための他のプログラムを含む。通常、電子装置CMPと人間のユーザとの相互作用は、ユーザインタフェース等の入力/出力(I/O)装置を通して発生する。I/O装置は(モニタ等の)表示装置DSP、並びにマウスMS及びキーボードKEYB等の1台又は複数の入力装置、並びに/又はタッチスクリーン及びネットワークインタフェース等の他の適切な従来のI/O周辺機器を含んでよい。
メモリMEMは、アルゴリズムの実装の標準ソースコードPGSCから直接的にアルゴリズムのホワイトボックス実装を自動的に生成できるアプリケーションWBGNを保持する。
電子装置は、コンピュータ、又はスマートフォン、デジタルタブレット、もしくは接続されたオブジェクト等の任意の他の計算装置であってよい。
代替的な実施形態では、電子装置CMPは、さらにインターネット等のネットワークとインタフェースで接続される。当業者は、プログラムソースコードPGSCが電子装置CMP上でローカルに又はネットワーク上で電子装置とインタフェースで接続される遠隔位置のどちらかに記憶されてよいことを認識するだろう。同様に、ホワイトボックス生成アプリケーションWBGNは、ネットワーク化されたサーバ又は遠隔ピアに記憶されてよい。
1. ホワイトボックス実装の生成
一実施形態に従ってホワイトボックス実装を生成する方法は、それぞれが図2に示されるように複数の段階に分割される2つの主要なプロセスP1、P2を含む。プロセスP1、P2は実装コア生成P1及び実行マシン生成P2である。実装コア生成P1のプロセスは、暗号アルゴリズムであってよい入力アルゴリズムの初期のホワイトボックスバージョンを実装する低レベル演算のセットを生成する。この演算のセットは入力アルゴリズムよりもはるかにより複雑であり、鍵抽出攻撃に抵抗するための多くの技法を利用してよい。
実行マシン生成のプロセスP2は、まだ容易に実行可能な形式ではない上記に生成された演算のセットを鍵抽出攻撃に対する追加の保護を提供してよい実行可能な形式に変換する。このプロセスの出力は、既存のプロジェクトにコンパイルし、直接的に実行できるスタンドアロンソースコードである。スタンドアロンソースコードは通常、Cソースコードであるが、Java等の他の実装言語も使用できる。
方法のプロセスP1、P2は、アルゴリズムソースコードを解析することによって生じる中間表現(IR)として入力アルゴリズムを受け取る。暗号アルゴリズムはCで最も一般的に実装されるが、方法はコンパイルされたプログラミング言語及び解釈されたプログラミング言語の両方に適用可能である。方法によって生じるコードは、コンピュータ、スマートフォン、もしくはデジタルタブレット等の任意の計算装置、又は任意の接続されたオブジェクトによって実行されるように適応されてよい。保護されるアルゴリズムを実行することを目的とした装置がオープンプラットフォームの周りに設計される、及び/又は公衆網に接続されるときに、方法はいっそう有用である。
プロセスP1、P2はより詳細に以下に説明される。実装コア生成P1のプロセスは、入力アルゴリズムの初期のホワイトボックスバージョンを実装する低レベル演算のセットの生成を担う。一実施形態によると、プロセスP1は秘密の爆発及び融合、並びにデコイ生成の2つの段階S11、S12を含む。秘密の爆発及び融合の第1の段階S11は、低レベル演算の大きなセットにアルゴリズムを拡大し、各演算が使用する任意の秘密データと各演算を結合する。演算及び秘密データの組合せは、実際の秘密データフラグメントをその元の形式で使用しない方法で表される。
デコイ生成の第2の段階S12は、プロセスP1によって提供される実演算に沿って存在し、実演算とともに実行する、複製および変異されたデコイ演算の大きなセットを生じさせる。これらのデコイは、実装によるデータの信頼できる流れの確立を極めて困難にする方法で、実演算とおよび処理されるデータに相互に作用する。
一実施形態によると、段階S11は、図3に表されるように以下の4つのステップを含む。
‐アルゴリズム拡大(S31)、
‐部分的な評価(ステップS32)、
‐秘密の爆発(ステップS33)、及び
‐秘密の融合(ステップS34)
アルゴリズムの拡大のステップ31で、アルゴリズムは、使用可能な静的入力データ(例えば、秘密データ)が与えられると、アルゴリズムを実装するために使用される演算の完全なセットに拡大される。これらの演算はその最もインライン化され、展開された形式でアルゴリズムを表す。このステップは、演算間を流れるデータの値とともに、演算間のすべての知り得るデータ依存性をモデル化するデータ依存性グラフも生じさせる。
部分的な評価のステップ32では、演算は、統計的に既知の値を生じさせる演算を排除する部分的な評価を受ける。このステップの主要な目的は、秘密データがその最も導き出された形式で、及び秘密データが非静的データ(例えば、暗号化/解読データのブロック)と相互作用を開始する点でのみ存在するように、秘密データに対する中間演算を排除することである。
秘密の爆発のステップ33で、導き出された秘密データを含んだあらゆる残りの演算は、それぞれの新しい演算が元の演算よりも導き出された秘密データのより小さい部分を使用するように複数の演算に分割される。このプロセスは、導き出された秘密データの特定数のビットよりも多くを使用する演算がなくなるまで繰り返し適用される(単一ビットと同じ程度に低いことがある)。
秘密の融合のステップ34で、秘密データの導き出された部分のすべては、データを記憶するよりむしろデータを生じさせる演算の一意のセットに変換される。演算のこれらの一意のセットは(以下に説明されるように)シーケンスに影響を受ける。つまり、演算が生じさせるデータは、その点まで実装によって実行される以前の演算のほぼすべてに依存する。これらのデータを生じさせる演算は、次いでデータの生成及びデータの使用がほぼ区別ができないように、データを使用する演算と結合される。
アルゴリズムの拡大のステップS31で、アルゴリズムは、使用可能な静的入力データ(例えば、静的鍵データ)が与えられると、アルゴリズムを実装するために使用される演算の完全なセットに拡大される。これらの演算は、アルゴリズムをその最もインライン化され、展開された形式で表す。単純な例として、拡大プロセスは以下の疑似コードに適用される。
この疑似コードは、単純なループ及びこのループに対する入力「a」及び「I」を含む。この疑似コードの拡大は、まず、以下の演算を生じさせる。
この拡大された疑似コードでは、ループは展開され、条件(「if」)文は排除された。
関数呼出し及びより多くのプログラムの流れの制御を含んだより複雑な例は、インライン化される関数及び排除されている非到達コードも示すが、この単純な例はプロセスの残りに取り組むときに明瞭さを補助する。また、この拡大ステップは、演算間を流れるデータの値とともに演算間のすべての知り得るデータ依存性をモデル化するデータ依存性グラフも生じさせる。上記の簡略な例のこのグラフの表現は以下の通りである。
上記の表現では、別の演算に対する依存性を有する各値は、以下の形式で中括弧内の依存性情報で修飾される。
{値:#ソース:状態}
「値」が(その時点での)その値の実行時の内容である場合、「ソース」はその値を生じさせた演算であり、「状態」は、値が(「c」で示される)一定の入力だけから導き出されるのか、それとも(「v」で示される)少なくとも1つの可変入力だけから導き出されるのかを示す。例えば、行7で、修飾されたメモリ位置「a」は行5の演算によって生じた20の実行時値を有し、値は一定の入力データだけから導き出される。注目されるのは、ここに示される例がプロセスの表現にすぎず、プロセスを実装するために使用される物理的表現に直接的に対応しないことがある点である。例えば、本発明の現在の実施形態では、演算はここに示される疑似コードよりも低いレベルに存在し、「for」ループ等の構成体を有さない。また、現在の実施形態は実施形態自体を、わずか1つの出力を有する演算に制限し、このことが依存性モデルを簡略化する。ただし、プロセスは幅広い範囲の物理表現に適用できる。
アルゴリズムの拡大ステップS31は、以下を含む、アルゴリズムを実行し、実行中に起こることを記録するシミュレータを生成することによって達成される。
‐実行される各演算は、そのパラメータの実際値及び該値の一定状態/可変状態とともに記録される、
‐関数呼出し、関数終了、条件分岐、及び無条件分岐を含んだすべての制御フロー変更が記録されるが、すべての制御フロー変更の影響は記録されている通常の演算にすでに存在するため、通常の演算とは異なるとして記される。例えば、関数が呼び出される場合、次いで記録は以下のシーケンスを含む。1)呼出し演算、2)呼び出された関数の中の演算、3)関数終了、及び4)呼出し側の関数の残りの演算、並びに
‐演算により書き込まれるすべてのメモリ位置の状態は、その位置に書き込むための最後の演算、及びその演算の結果としてのその位置の一定状態/可変状態を(それぞれについて)記憶するマップに記録される。演算の入力値がすべて一定である場合、次いで書き込まれたメモリ位置は一定として記録されるだろう。それ以外の場合、メモリ位置は可変として記録される。
例のコードについてメモリ状態マップの更新方法は以下の表1に示される。
表1のそれぞれの表の行は実行中の各演算、及びその演算が実行された後のあらゆるメモリ位置の状態を表す。各メモリ位置「a」及び「i」はその位置の値、その位置に書き込むための最後の演算、及び位置の一定/可変(c/v)状態を示す3つの列によって表される。位置「a」及び「i」は演算1から12に交互に変更される。再び(行7の)演算7を見ると、演算が(行6からの読取りを)実行する前に、「a」の位置が20の値を有し、上記のデータ依存性グラフに記録される依存性情報に相当する演算5によって最後に書き込まれたことが分かる。演算7が(行7の後に)実行した後、分かるように、位置「a」は変化し、ここでその最後の演算が現在7に設定された状態で30の値を有する。
この単純な例コードを用いると、メモリ状態マッピングの使用が過剰に見える可能性がある。状態データは単に各変数(a及びi)に関連付けられ、同じ結果を達成できるだろう。ただし、実際のプログラムはアレイ、構造、割り当てメモリ、及びポインタエイリアシングを含んだはるかに複雑なメモリアクセスパターンを有する。メモリ状態マッピングは単一の機構ですべてのメモリアクセスパターンをサポートすることを可能にする。
シミュレータがアルゴリズムを実行するとき、いくつかのコードが実際には実行されないことがある。これが望ましい場合もある。アルゴリズムが決して実行されない非到達コード又は条件付きコードを含む場合があり、これは当然シミュレーションプロセスで廃棄される。ただし、アルゴリズムに応じて、シミュレーション中にコードが実行されないが、異なる条件下にあるだろう場合がある。これが発生するとき、コードが既知の静的データだけに基づいた決定のために実行されなかったのかどうかが確証される。これが当てはまる場合、コードは単に未使用のコードとして分類される。当てはまらない場合、次いでコードは入力依存コードとして分類される。入力依存コードは、代替的な決定を下させるだろう入力のセットを所与として、シミュレーション中に実際に実行された演算の代わりに決定論理を実行できるようにする決定論理とともに、演算の拡大されたセットに元の欠損コードを注入することによって処理できる。これにより、結果として生じる実装は、未知の入力に直面するときに機能できるが、再注入されたコードは完全な依存性情報を有しておらず、このことは以降のステップでのそれについて推測する能力を制限する。
多くの場合、入力依存コードは存在しないか、又はコードの小部分を表すにすぎないかのどちらかであり、したがって重要な問題とはならない。入力依存コードがより普及している場合、上記の解決策は以降の処理ステップを適切に実行する能力を制限し、このことは同様にホワイトボックスプロセスによって提供される保護を全体として制限するため、解決策は理想とは程遠い。これを軽減するために、シミュレーションは、異なる実行時入力で複数回実行され、これらのシミュレーションの結果をいくつかの実行時決定論理で演算の単一の拡大されたセットに結合することを可能とされる。シミュレータがすべての可能な実行パスを見ることができるように入力が選択される場合、次いで演算の完全な拡大されたセットが構築できる。各入力依存コードパスであるが、そのすべてのインスタンスではない、少なくとも1つの実行が検出される場合でも、実行時の値情報を伴わない依存性グラフが構築できる。
部分的な評価ステップS32で、演算は、統計的に既知の値を生じさせる演算を排除する部分的な評価を受ける。このステップの主な目的は、秘密データがその最も導き出された形式で、及び秘密データが非静的データ(例えば、暗号化する/解読するデータのブロック)と相互作用を開始する点でのみ存在するように、秘密データに対する中間演算を排除することである。このステップはアルゴリズムのインライン化され、展開されたモデルに作用するため、及び秘密データは静的入力データとして取り扱われるため、この結果、演算の大きな部分が排除される。これを示すために、単純な例のプログラムに適用されるときのこのステップの結果が以下の行に削減できる。
この結果は、メモリ位置「a」及び「i」に対する演算のすべてが統計的に既知の値を生じさせるために発生する。両方とも定数値で初期化され、次いでその現在の値を別の定数値と結合することによって連続的に修正される。つまり、その出力はつねに統計的に既知である。現実には、これらの2行のコードでさえ実際には存在しないだろう。プログラムが変数「a」及び「i」を使用した他のコードで拡大された場合、それらの演算は、定数及び変数「a」及び「i」が存在しないため、値50及び5を直接的に使用するだろう。変数「a」及び「i」が後のコードによって使用されなかった場合、次いで該変数は単に存在しないだろう。完全な部分的な評価プロセスは相対的に複雑であるが、基本的なプロセスは単純な例のプログラムを使用して示すことができる。データ依存性グラフからの依存性情報とともに拡大された形式で開始すると、演算1で開始し、演算1は演算2が行うように統計的に既知の値を明確に生じさせるため、演算1を排除できる。また、演算3は、演算3が、依存性情報が一定であると示す値「a」をリテラル値(10)に結合するため統計的に既知の値も生成し、したがって、演算3も排除できる。同じことは残りの演算にも当てはまる。つまり、残りの演算のすべてを排除できる。これにより、50の値を有する変数「a」及び5の値の変数「i」が残されるが、それらの値を生じさせるための演算は必要としない。論理的には、上記に示されている2つの代入が存在するが、2つの代入は実際の代入として絶対に存在しない。
変数(統計的に既知ではない)値及び演算の完全にインライン化され、展開された性質が検討されるとき、プロセスはより複雑化する。多くの場合、完全にインライン化され展開された演算でホワイトボックス実装を生成することは実際的ではない。結果として生じる実装は大きすぎて実用的ではないだろう。実用的な実装を生じさせるため、インライン化及び/又は展開のいくらかは排除される必要がある。これらのことを排除する問題は、演算の中の統計的に既知のデータの量に大きく寄与する点である。簡単な例のプログラムを見ることによって、なぜかが分かる。展開されたコードがループに戻されなければならない場合、次いで「a」及び「i」の両方とも(一定の入力だけから導き出されているにも関わらず)変数になり、同様にそれらの変数を使用した任意の後続コードを「汚染し」、その出力を可変にするだろう。同様の影響は、インライン化が排除されると発生する。これに関する問題は、主要な目標が、秘密データをその最も導き出された形式で可能な限り遠くまで実装の中に伝搬することであり、この伝搬は、秘密データが任意の可変データに出会うときに終了する。
したがって、部分的な評価ステップS32の目標の1つは、ステップが実装を通して導き出された秘密データの伝搬に対して与える影響を最小限に抑えつつ、該部分的な評価ステップができる限り多くのインライン化及び展開を排除することである。これを行うために、決定モデルが確立され、秘密データ伝搬の損失におけるコストに対する、インライン化/展開を排除することにより獲得される利益のレベルを表す、関数及び基本ブロックに対するスコアが割り当てられる。スコアの利益構成要素は、排除が提供するだろうコード削減の量に比例する。コスト構成要素は、排除によって影響を及ぼされる秘密データのすべての部分の伝搬損失を合計することによって計算される。個々の伝搬損失は、秘密データの部分その最も導き出された形式であっただろうものに到達する前に秘密データの部分が関与する追加の演算数を測定することによって計算される。コスト構成要素の当然の結果は、呼出しグラフの上部に近いコードが、呼出しグラフの終わりにあるコードよりもはるかに高いコストを有する傾向がある点である。このため、決定プロセスは下から上に作用し、十分なコード削減が達成されると終了する。この簡略化された例は図5に示される。
図5の上部の列番号はグラフの部分を指し、呼出しグラフは下に示され、各ボックスは関数の部分(ボックス内側に示される関数名)を表している。より幅広いボックスはそれらの中のより多くの演算を伴う関数の部分を表している。実行の開始は左上部にある。呼出しは下向き矢印で示され、関数終了は上向き矢印で示される。すべての呼出しは親関数のループの中で実行され、呼出しカウントが下向き矢印に示される。
呼出しグラフの下方に、2行の情報「H」及び「CTS」が示され、それぞれの列はそのすぐ上にある呼出しグラフ要素と関連付けられている。「H」行は、対応する列内の各要素が実行される合計数を示す。呼出しグラフの下部の関数「e」及び「f」は、ループ化された呼出しのいくつかのレベルのため、多くの回数にわたり実行される。「CTS」行は、対応する列のどのくらいの数の演算が一定の導き出された秘密データを生じさせるのかを示す。
これは簡略化された例であるため、インライン化/展開を排除するコストは、影響を及ぼされる領域の中で一定の導き出された秘密データを生じさせる演算の数に比例しているとしてモデル化される。上述されたように、実際のコストは秘密データの伝搬損失を測定することにより計算される。これに対して、この例は伝搬損失がつねに1である、つまり、例示的な目的にとって妥当な概算であるとみなされる。
図5の例から取得されるスコア計算は、以下の表2に提示される。
「利益」の列の結果は「サイズ*H」として計算され、「自己コスト」の列の結果は「CTS*H」として計算される。「子コスト」の列の結果は関数の子供(関数が呼び出す関数)の「自己コスト」数を加算することによって計算される。「コスト」の列の結果は「自己コスト+子コスト」として単純に計算される。子コストを含む理由は、コードの領域に対するインライン化/展開が排除される場合、この排除はインライン化/展開に依存するほぼすべてのものに影響を及ぼすだろうという点である。関数の場合、その関数が呼び出す関数を意味する。最後に、列「スコア」の結果は「利益/(コスト+1)」として計算される。表2から分かるように、関数「b」は最高スコアを有するとして第1の候補となるだろう。関数「b」かなり小さい利益を有するが、ゼロコストを有すため良好な選択肢になる。次の候補は、かなり高いコストを有するが、非常に大きい利益も有する関数「e」となる。この関数「f」が使用されると、関数「f」の利益とコストの両方とも非常に大きいが、依然として利益が勝る。関数「a」、「c」、及び「d」は、特に悪い候補となるだろう。つまり、呼出しグラフの上部にあることは、非常に大きいコストを有し、呼出しグラフの上部の関数のいずれも大きな利益を有さないことを意味する。
注目されるのは、実際には、スコア計算は各選択がなされるたびに実際に変化する点である。特に、選択と関連付けられたコストは一度しか発生せず、したがって、やはりそのコストを含んだ任意の他の選択はそれらのコストを相応して削減させる。
ステップS33で、導き出された秘密データを含んだあらゆる残りの演算は、それぞれの新しい演算が元の演算よりも、導き出された秘密データのより小さい部分を使用するように、複数の演算に分割される。各タイプの演算は多くの異なる方法で分割できる。例えば、「s」が秘密データであり、「t」が(おそらく可変)データの別の部分である32ビットの乗算演算「s*t」を考える。この演算は、各シフト演算が「s」からの単一のビットを表すシフト演算及び加算演算のシーケンスに分割できる。代わりに、乗算演算は、各乗算が「s」の少数のビットしか使用しない乗算及び加算のシーケンスに分割できるだろう。より簡略な例の場合、以下のXOR演算を検討する。
上記の例と同様に、「s」は秘密データであり、「t」は(おそらく可変)データの別の部分である。明確にするために、両方の変数「s」及び「t」はそれらの値を代入して示されている。実際には「s」の値はXOR演算の中で「リテラル値」として直接的に使用され、「t」はいくつかの可変値を伴い既に存在する。この演算は、以下に示すように、2つのXOR演算及び1つのOR演算から成るシーケンスに分割できる。
この場合、分割は「s」及び「t」の上部16ビットに対してXORを実行し、下部16ビットにXORを実行し、次いでOR演算と結果を結合することによって達成された。さらに小さい部分に構成要素を分割することは、本方式の自明の拡張である。例えば、構成要素は4つのXOR及び3つのORを使用し、4つの8ビット部分に分割できる。
ここに示す例は単一の演算に関して秘密データを分割することしか含んでいない。しかしながら、実際には、秘密データを含んだ演算を第1の演算の結果に(したがって秘密データに)依存する後続の演算と結合することによって演算のシーケンスで行われる。
この例は、以下に示される。
この例で、秘密データ「s」は「t」とXORされて、「u」を生じさせ、「u」は後続の行4で使用されて「w」を生じさせる。「s」に全く依存していない行3の存在は、「s」の従属物が連続しない可能性を示すのに役立つ。実際に、従属物は多くの関連していない演算によって分離されてよい。複数の演算に関して秘密データを分割するために、この例は以下に示されるように書き直すことができ、
この場合、行3はその値(「s XOR t」)を生じさせる演算で元のコードの「u」を置換する式である。
「s XOR t」のために分割演算を生じさせる代わりに、分割演算は「s」に対する2つの従属演算のシーケンスを表す式「(x XOR t)*v」のために作成される。これは、導き出された秘密データから従属物の任意の深さに拡張できる。この爆発プロセスは、導き出された秘密データの特定数より多いビットを使用する演算がなくなるまで繰り返し演算のセット全体で適用される。また、導き出されたデータの各部分が分割されるビット数は、導き出されたデータがどのようにして元の秘密データに関係するのかにも依存する。導き出されたデータと元の秘密データが相互に強く関連している場合、より少数のビットに分割される傾向がある。
秘密の融合のステップS34で、秘密データの導き出された部分のすべて(多くは単一ビットほど小さくてよい)が、データを記憶するよりむしろデータを生じさせる演算の一意のセットに変換される。演算の一意のセットは(以下に説明されるように)シーケンスに影響を受ける。つまり、演算が生じさせるデータはその点までに実装によって実行された以前の演算のほぼすべてに依存している。これらのデータを生じさせる演算は、次いでデータを使用する演算と結合され、これによりデータの生成及びデータの使用はほぼ区別ができない。
一実施形態によると、デコイ生成の段階S12は、図4に示されるように以下のステップを含む。
‐複製及び変異のステップS41、
‐演算インタリーブのステップS42、及び
‐データフロー融合のステップS43
複製及び変異のステップS41で、秘密の爆発及び融合の段階は多数回繰り返され、無作為なデータが秘密データを置き換えて、選ばれたアルゴリズムの代替のデコイ実装を表す演算のセットを生じさせる。
演算インタリーブのステップ42で、生成された演算(実及びデコイ)のすべてが、各セットからの演算が他のセットのすべてからの演算とインタリーブされる、演算の単一の大きなセットに結合され、これによって結合されたセットが実行されると、該結合されたセットは演算のすべてのセットを効果的に実行している。
データフロー融合のステップS43はインタリーブの後に実行される。このステップを実行する前に、演算の結合されたセットはまだ演算の関連のないセットから成り、互いの間に単に位置する。この最終ステップで、これらの関連のない演算は、演算の全体の組み合わされたセットを通るデータフローを決定するのが困難になるように互いと融合される。
複製及び変異のステップS41で、秘密の爆発及び融合の段階は無作為なデータで多数回繰り返されて、選ばれたアルゴリズムの代替のデコイ実装を表す演算セットを生じさせる。生成プロセスは秘密データの値に依存しているため、生成された演算の各セットは一意となる。結果は実質的に変異されているので、これを変異と呼ぶが、実際のプロセスは異なる開始シードで演算を生成することである。デフォルトにより、無作為に生成されるデータは単に実際の秘密データの代わりに使用される。これは、秘密データが無作為データと区別ができないときにはよいが、秘密データのいずれかがこの特性を有していない場合、デコイデータは秘密データの性質によりよく一致する使用法に必要とされる。これは、無作為に生成されたデータをデコイ秘密データとして適切にするために、アルゴリズムが無作為に生成されたデータを調整するアルゴリズム特有フィルタを提供できるようにすることによって解決される。
演算インタリーブのステップS42で、生成された演算(実及びデコイ)のすべてが、図6に示されるように演算の単一の大きなセットに結合される。図6は、インタリーブされて演算の単一の大きな結合されたセットC1を取得するデコイ演算セットDI1、DI2、DI3、DI4、及び実演算セットR1を示す。演算セットCIでは、各演算セットDI1からDI4及びR1の演算が、(セットの上下の矢印に従って)他のセットのすべてからの演算でインタリーブされ、これにより、結合されたセットC1が実行されるとき、実質的にすべての演算セットDI1からDI4及びR1を実行している。インタリーブは、たまたま互いに近い異なるセットからの演算間に直接的な対応がないように、部分的に重複するように特に設計される。特に、演算RIの実セットは結合されたセットC1のまさに開始及びまさに終了から常に離れて位置する。
インタリーブがステップS42で発生した後も、演算の結合されたセットは、単に互いの間に位置する演算の関連のないセットから成る。データフロー融合の最終ステップS43で、これらの関連していない演算は、全体的な、演算の結合されたセットを通って流れるデータが決定するのが困難になるように互いと融合される。これは、発信データフローのある演算のグループを漸次的に選択し、その出力データのすべてを、その出力データを正しい受入れ演算に送る新規に生成された演算を通してプッシュすることによって達成される。このルーティング演算は、(以下に説明されるように)シーケンスに影響を受ける融合をさらに使用する一意に生成された不明瞭な式を使用して構築される。これがどのように機能するのかを見るために、図7Aの例は、データフロー融合を使用して結合する演算の2つの個別のセットを示す。図7Aは左側に演算「a1」、「a2」、右側に演算「b1」、「b2」を示す。演算「a1」は2つの入力「I1a1」及び「I2a1」を有する。演算「b1」は2つの入力「I1b1」及び「I2b1」を有する。演算「a2」は変数「I1a2」及び演算「a1」の出力を受け取る。演算「b2」は変数「I1b2及び演算「b1」の出力を受け取る。データフロー融合を使用して演算「a1」、「a2」及び演算「b1」、「b2」を結合するために、追加の演算は演算「a1」と「a2」との間、及び演算「b1」と「b2」との間でも追加されるため、これらの演算は、演算「a1」及び「b1」がともに、演算「a2」又は「b2」のどちらかが実行される前に実行するように位置決めされる。これらの演算に対してデータフロー融合を実行することの結果は、図7Bに示される。図7Bでは、ルーティング演算ROPは、演算「a1」及び「b1」を実行した後であるが、演算「a2」又は「b2」を実行する前に実行するように挿入される。図示の通り、演算「a1」及び「b1」はそれぞれ演算「a2」及び「b2」にその出力を渡すよりむしろ、演算「a1」及び「b1」はルーティング演算ROPに出力を渡し、ROPが次いで出力を正しい受取人、つまり演算「a2」及び「b2」に渡す。ルーティング演算ROPによって使用される不明瞭な式は、どの出力がどの受取先に行くのかを決定するのを非常に困難にする。特に、静的分析を介して決定するのはほぼ不可能である。データフロー融合プロセスは、演算の結合されたセットのデータフローのすべてが十分に融合されるまで進む。
実装コア生成プロセスによって生じる演算のセットはその形式では実行できないため、該演算は、実際に使用できる実装を生じさせるために実行可能な形式に変換される。実行マシン生成プロセスP2はこの変換を実行し、ソフトウェアプロジェクトの中に含まれ、所望される暗号演算を実行するために直接的に呼び出すことができるソースコードを生じさせる。ただし、一実施形態によると、演算のコードへの単純で直接的な変換を実行するよりむしろ、プロセスP2は、鍵抽出攻撃に対する重要な追加の保護を提供する演算を実行するための専用マシンを生成する。
概念レベルでは、生成されたマシンは、バーチャルプログラムを処理し、バーチャルマシンモデルとの関連でそのプログラムによって指定される演算を実行する実行エンジンがあるという点で、バーチャルマシン(VM)にほぼ類似している。ただし、実装レベルでは、多くの重要な相違点がある。
それぞれの生成されたマシンは一意である。つまり、該マシンが実行できる演算、該マシンの演算の実行方法、演算が表される方法、及び演算を実行する機構はマシンごとに一意であり、
マシンは命令セットを有していない。つまり、所与のマシンが実行できる演算のセットは命令セットであると見なすことができるだろうが、該演算は、該演算が名称を与えられ、係るように使用できるようにするだろう識別できる概念上の意味を有しておらず、
マシンはプログラムを実行しない。つまり、所与のマシンは1つの特定のプログラムを実行できるにすぎず、そのプログラムはマシン自体の一体部分であり、多くの場合、マシンの実行側とプログラム側との間に境界はなく、
マシンには実行エンジンはない。つまり、各マシンは演算を実行することを担う多数の実行要素から成り、これらのそれぞれも実行する次の演算を決定することを担い、すべての実行ステップに関与する「中心的なエンジン」はなく、
マシンはバーチャルマシンモデルを有していない。つまり、任意の所与の演算の実装は特定のバーチャルCPU又はその実装方法に関して何らかの制限を課す任意の他の構造と関連付けられておらず、これに対する唯一の例外は、関数呼出しを実装するために使用されるプログラムスタックはあるが、マシン内部呼出しに使用される所定の呼出し規則はなく、
マシンは統計的に分析できない。つまり、命令セットなし、識別可能なプログラムなし、及びマシンモデルなしで一意のマシンを静的に分析する上での固有の困難さは別として、マシンを実行するプロセスは(以下に説明する)シーケンスに影響を受ける融合演算に完全に依存し、マシンのどの部分も、実行がその部分に達するまで(マシン自体によってでさえ)理解できない。
一実施形態によると、マシンを生成するプロセスは、図2に示されるように、以下のステップを含む。
小さい均一な命令セットに関して表される実装コア生成プロセスP1によって生じる演算のセットを、はるかに大きい不均一の命令セットに関して表される演算に変換する演算再表現のステップS21、
ステップS21から取得される再表現された演算の実装を生じさせる演算実装のステップS22、
シーケンスに影響を受ける融合を利用するための演算実装を変換して、静的分析に耐えるシーケンス融合のステップS23、及び
シーケンス融合ステップS23によって生じる実装の構成要素のすべてに適用され、実行可能な形式での出力される準備が完了しているコード生成のステップS24。
演算再表現のステップ21の出力は命令セットを有するものとして参照されるが、各命令の中に含まれる副演算は、副演算が従来の意味で命令のように使用するために集合的な名前を与えられることを可能にする有意義で概念的な関係性を互いに対して有さないため、厳密に命令セットとしての適性はない。例えば、「関数呼出し」命令は通常、個々の意味(例えば、スタック上に値をプッシュし、別のプログラム位置にジャンプする等)を有する副演算のシーケンスから成るが、個々の意味を「関数呼出し」という名称の単一命令としてともに表現できるようにする結合された意味も有する。ここで、レジスタr0に1234を追加して新しい命令を作る命令と結合されたこの関数呼出しシーケンスを検討する。この新しい命令は、何をするのかを表すために、「呼出し関数及び1234追加、r0」(又は何か類似するもの)と呼ばれなければならないだろう。例えば、10以上の命令がこのような方法で結合される場合、新しい命令の結果として生じる名称は複雑且つ特有すぎて、概念的に意味を持ち得ない。
所望される変換を達成するために、ステップS21は2つのステップ、つまり、演算書直しの第1のステップ、及び演算結合の第2のステップで実行される。演算書直しの第1のステップは、演算のシーケンスを、不明瞭な式、算術/論理書直し、及び総当たりの同等コード生成等の周知の難読化変換を使用し、意味的に同等な代替形式に変換する。演算のシーケンスは無作為に選択され、無作為に選ばれた難読化変換で変換される。このプロセスは、十分なレベルの変換が発生するまで繰り返す。それぞれの個々の演算はこのプロセスの間に複数回変換されてよい。このステップの主要なプロセスは第2のステップのためにコードの均一性を削減することである。難読化変換の使用は、結果として生じるコードを理解するのをより困難にさせるのにも役立つが、これは全体的なプロセスの重要な部分ではない。
演算結合の第2のステップは、演算のシーケンスを結合して、各命令が命令を生じさせるために結合された演算のシーケンスを表す、新しい命令セットを生じさせる。結合プロセスは、第1の演算で開始し、無作為な数の後続の演算を選んで、結合することによって(関数ごとに)機能する。演算のシーケンスは結合され、新しい命令インデックスと関連付けられる。このプロセスは、次いで、次に使用可能な(結合されていない)演算に移動し、すべての演算が処理されるまで、演算を無作為な数の後続の演算等と結合する。このステップの目的は、各命令を構成する演算間に概念上の関係性がない新しい命令セットを生じさせることである。これは、結合プロセスだけで達成できるが、書直しステップの不均一な結果に結合プロセスを適用することははるかにより効果的な結果を生じさせる。
上述された演算結合ステップは多様な点で改善できるだろうが、単純且つ効果的である。例えば、プロセスが関数の終わりに到達すると、結合されるために使用できる演算数は、最後の新しい命令が単一演算から形成される最悪のシナリオで削減される。この段階でのコードのかなり展開され、インライン化された性質は、コードの相対的に小さい部分に影響を及ぼすことを意味するため、これが実際に重要な問題を提起する可能性は低い。これが問題になると、問題は結合シーケンスを事前に計算し、すべてのシーケンスが十分に最小のサイズになるまでその境界を無作為に再分配することによって排除できるだろう。
演算実装のステップS22は、前のステップS21から再表現された演算の実装を生じさせる。演算実装は以下の部分を含む。
1.新しい命令を生成するために結合された演算の副演算実装部分、
2.パラメータ解読論理‐いくつかの演算は複数のコンテキストで実行されてよい(プログラムを実行することにほぼ同等)。これらの演算は、演算ごとに一意に符号化されるパラメータの形式でコンテキスト特有の入力及び出力を受け取り、
3.実行継続論理‐各演算実行後、次の演算及びそのコンテキスト(演算がコンテキストを有する場合)が解読され、実行は次いでその演算の実装によって継続される。
シーケンス融合のステップS23は、静的分析に抵抗するために(以下に説明される)シーケンスに影響を受ける融合を利用するための演算実装を変換する。この段階の前に、演算実装は互いの上に直接的にチェーンを作り、各演算実装は静的に独自の入力/出力及び連続パラメータを解読する。この段階の後、各演算実装は、同様に次の演算実装の上にチェーンを作るデコーダ実装の上にチェーンを作る。デコーダ実装は、次の演算実装の位置及びそのパラメータの解読を担い、これらはシーケンスに影響を受ける融合値を使用してデコーダ実装ごとに一意に符号化される。
演算実装によってチェーンが作成される特定のデコーダ実装はコンテキストに特有である。つまり、演算実装はパラメータとして特定のデコーダ実装を受け取り、特定のデコーダ実装がどのデコーダにチェーンを作成するのかの静的な知識を有していない。この変換の結果は、演算実装が、使用の時点でのみ解決され、演算シーケンスの静的分析を極めて困難にするデコーダのコンテキストに特有の動的なセットを通して互いから分離されることである。
シーケンス融合ステップS23が完了後、実装の構成要素のすべては実行可能な形式で出力される準備ができている。コード生成の最終ステップS24で、演算実装のすべては、既存のプロジェクトの中にコンパイルし、直接的に実行できるスタンドアロンソースコード部分としてともにレンダリングされ、通常Cソースコードであるが、他の実装言語も使用できる。
プロセスP2は、ホワイトボックス実装を実行できる実行マシンを生成することを含む。このマシン生成は、プロセスP1で実行される他のホワイトボックス生成ステップによって使用される技法に加えて、ステップS21、S22、S23の難読化技法を使用する。
実行マシンの生成は、これらの追加の難読化のすべてが実行マシン内のどこかで利用されることを仮定している。これは依然として特定の場合には当てはまることがあるが、経験は、これらの難読化が、プロセスP1の他のホワイトボックス生成ステップによって使用される難読化よりも(暗号アルゴリズムを保護することに関して)効果がより少なく、性能影響及びコードサイズに関して最も高価な難読化であることが実験により分かった。
一実施形態によると、最も効果的な難読化の使用を最大限にし、全体的な性能/サイズの影響に対するより多くの制御を提供するために、実行マシンは、複雑度を最大制御のための演算ごとのレベルで変えることができる可変難読化複雑度により生成される。最低レベルの複雑度では、演算のために生成されたコードは、本来、演算と演算が作用しているデータとの間の(たとえあったとしても)リダイレクション機構のほとんどない演算の単純なC実装である。このレベルの複雑度で生成されるコードは通常、最大複雑度で生成されるコードよりも10倍から100倍速く、さらに著しく小さい。任意の所与の演算の場合、複雑度レベルは最小複雑度と最大複雑度の間のレベルの大きい範囲の内の1つに設定できる。レベルが増すにつれ、マシン生成に使用可能な多様な難読化が漸次的に有効にされ、最大レベルはすべての使用可能な難読化を利用する。
各演算は個別の複雑度レベルを有することがあるが、実際には、複雑度レベルはより大きな精度で、おもに入力コードの機能単位レベルで指定され、特定の場合、関数の中のブロック単位レベルで指定され得る。複雑度レベルはコード注釈を介して入力コードで指定される。入力コードに適用される複雑度レベルはグローバルベースで拡大又は縮小することもでき、一連の異なる複雑度のある実行マシンの容易な生成を可能にする。一実施形態によると、単純な線形スケーリング演算が達成されるが、非線形モードも可能である。
シーケンスに影響を受ける融合の概念は実施形態に従って多くのステップ(S34、S43、S23)で使用され、効果を提供するために重要な役割を果たす。高レベルでは、シーケンスに影響を受ける融合は、プログラムの要素が本質的に無作為に見える実行時生成データに依存できるようにする方法であり、これによりプログラム要素は、このデータがプログラム要素の実行時に正しい値を正確に有する場合にだけ、正しく実行する。論理及びデータのいくつかの部分は、プログラム要素が実際に実行されるまで知ることができないので、この技法は、静的に解決することが極めて困難な方法でこれらのプログラム要素の論理及びデータを難読化するために使用される。これが機能するためには、データ生成シーケンスは、データを使用するプログラム要素が、生成されたデータを特有の既知の値に、使用の時点でのそれらの値を明らかにすることなく、変換する補償演算で修正できるように事前に知られている。
静的分析を防止するのに効果的であるために、データ生成プロセスは、データシーケンスが攻撃者によって事前に予測できないほど十分に複雑になることができる。これは、各変異演算がデータ生成バッファに対する演算の一意のシーケンスを実行するプログラム全体で多数のデータ変異演算を注入することによって達成される。これらの演算は、データバッファの中でのビットの混合を最大化するように設計できる。
演算間のデータフローの難読化は、実演算及びデコイ演算の出力を結合することを含む。データ要素自体は、有用な中間データの抽出を防ぐためにさらに難読化され得る。中間データ難読化は、事実上ホワイトボックスの内側で生成されたあらゆるデータ要素に適用され得、実際に、理想的にはあらゆる単一データ要素に適用される。一実施形態によると、実装の中間データ要素は、そのそれぞれをそのデータ要素に一意であり、データ要素がどのようにして難読化されるのかを指定する難読化コンテキストに関連付けることによって難読化される。例えば、データ要素がデータ要素を暗号化することによって難読化される場合、難読化コンテキストはその要素のための暗号化鍵を含む。データ要素が演算により書き込まれる場合、データ要素は難読化コンテキストを使用して難読化され、データ要素が別の演算により読み取られる場合、データ要素は同じ難読化コンテキストを使用し、難読化解除される。これが、データ要素がその難読化された形式でメモリに記憶されるが、作用されているとき非難読化形式に変えられることを保証する。各データ要素が一意の難読化コンテキスト(例えば、暗号化されている場合、各データ要素は一意の暗号化鍵を有する)を使用しているため、攻撃者は中間データを全体として解釈するため、個別のデータ要素ごとに難読化を解読しなければならず、このことは概して実現可能ではない。
2.動的秘密を用いるホワイトボックス実装
動的秘密を用いるホワイトボックス実装の方法は、秘密データが動的である、つまり実行時にだけ知られるホワイトボックス実装の生成を容易にする。静的鍵はホワイトボックス解決策の基本的な要素である。ホワイトボックスを作成するプロセスは、基本的には、鍵の値を導き出すことを困難にする形式で暗号アルゴリズムのバージョンに静的鍵を埋め込むことを含む。対照的に、動的鍵はすでにホワイトボックスの中に埋め込まれる代わりにホワイトボックスに渡され、このことはホワイトボックスの本質的に静的な性質に合わない。一実施形態によると、この問題は2つの暗号アルゴリズムを結合し、結合されたアルゴリズムから単一のホワイトボックス実装を生成することによって解決できる。これを可能にするには、ホワイトボックス生成(図2)方法が任意の暗号アルゴリズムに作用することの結果であり、このことは当然、2つ以上のアルゴリズムを結合する結果を含む。
選ばれたアルゴリズムAdと動的鍵Kdを使用するために、鍵Kdは最初に適切なアルゴリズム(例えば、AES)及び対応する鍵Kaesで暗号化され、暗号化鍵Kdeを生じさせる。
簡略にするために、暗号化鍵Kdeは事前に生成され、鍵Kdは、ホワイトボックス実装が実行中である装置上には絶対に存在しないと仮定する。動的鍵Kdの暗号化バージョンKdeは回送され、動的鍵の値を明らかにすることなくホワイトボックスの外部に記憶できる。動的鍵Kdを安全に使用するために、暗号化されたバージョンKdeを解読して動的鍵Kdを回復するホワイトボックス実装が生成される。次いで、動的鍵KdはアルゴリズムAdとともに使用して、選ばれた演算を実行できる。全体的な演算はこのようになる。
ホワイトボックス実装を生成するために、アルゴリズムDecryptAES及びAdのためのソースコードは単に結合され、上記演算を実装するためにアルゴリズムを使用する上位レベル関数が作成される。アルゴリズムAdがたまたまアルゴリズムDecryptAESである場合、次いで入力コードは上位レベル関数が2回呼び出すだろう単一のアルゴリズムだけを含むことになることに留意されたい。ホワイトボックス生成方法は、次いでホワイトボックスの保護境界の中で単一のユニットとして全体的な演算を実行する単一のホワイトボックス実装を生成する。ホワイトボックスを通るデータフローの観察による鍵の導出を防ぐ同じ機構が、解読された鍵Kdのホワイトボックスからの抽出をさらに防ぐ。
上述された方法は、ホワイトボックス実装とともに動的鍵を使用するためのいくつかの考えられる手法の1つである。ただし、それらはすべて2つ以上の暗号アルゴリズムを単一のホワイトボックスの中で結合する共通の要素を共有する。単一のホワイトボックスの中で複数のアルゴリズムを結合する一般的な概念の追加の拡張は、データの内容を明らかにすることなく暗号化されたデータに対して演算を実行できるようにすることだろう。これは、以下の例に示されるように、暗号解読演算DecryptAES、データに対する演算DataOp、及び暗号化演算EncryptAEを結合することによって達成できるだろう。
攻撃者が、アプリケーション作成者によって意図されていないコンテキストでホワイトボックス実装を使用しようと試みる2つの主要な方法がある。
攻撃1:実装を隔離し、別のプログラムにコピーする。これは、有能な攻撃者が達成するには相対的に簡単である。特定の要素により、実際には若干より複雑にする可能性があり、例えば、コードはコードを実行するために特有のメモリ位置に格納される必要があるが、有能な攻撃者は係る複雑性をかなり迅速に克服する。
攻撃2:実装を含んだ全体的なプログラムをコピーし、別のプログラムから直接的に実装を呼び出す。これを行うには、いくつかの異なる方法があるが、重要な要素は、実装を使用するプログラムから実装が分離されないという点である。実際には、この攻撃は以前の攻撃よりも若干より困難であることがあるが、有能な攻撃者の能力の十分に範囲内であり、特定の場合にはより容易でさえある。
一実施形態によると、攻撃1は、ホワイトボックス実装を含んだアプリケーションに対する一貫性をチェックする改ざん対策の解決策を適用することにより防ぐことができ、これによりホワイトボックスコードは、アプリケーションの残りが予想されたメモリ位置に実際に存在することを検証する改ざん対策チェックを含む。攻撃者が次いでホワイトボックスコードだけを別のプログラムにコピーしようと試みる場合、ホワイトボックスコードの中に含まれる改ざん対策チェックは故障し、コードは実行を拒否するだろう。これを最も効果的にするためには、改ざん対策解決策はホワイトボックス実装によって提供されるコードの大部分を利用し、そのコードの中に多数の一貫性チェックを自動的に注入して、攻撃者が一貫性チェックを打ち破り、コードをアウトオブコンテキストで使用するのを可能な限り困難にする必要がある。
攻撃2を防ぐのは著しくより困難であり、そのようにする方法は、ホワイトボックス実装にとって部分的に外部である追加の機構を使用する。追加の機構は、「コンテキスト実行」と呼ばれる一貫性をチェックする改ざん対策解決策に対する拡張である。注目されるのは、この機構により使用される根本的な手法が本開示によるその使用を超えた用途を有する点である。
コンテキスト実行の背後にある核となる概念は、プログラムによるホワイトボックスの使用目的だけが正しい結果を生じさせるように、ホワイトボックス実装の内部とホワイトボックスを使用するプログラムとの間に融合を導入することである。高レベルで、プロセスは、プログラムの中に融合生成手段を注入し、ホワイトボックス実装の中に融合ターゲットを注入することを含む。融合生成手段は、プログラムを実行するにつれて融合データを生成し、融合ターゲットはホワイトボックス実装の内側で実行される演算とこのデータを結合する。
(まったく実行しないことを含む)異常なプログラム実行が演算に正しくない結果を生じさせるのに対し、融合データ及びホワイトボックス演算の結合は、プログラムの通常の実行により生じる融合データがホワイトボックス演算の結果に変更を生じさせないように構築される。基本的なプロセスは以下のステップから成り立つ。
1.融合生成手段として使用するためにアプリケーションで位置のセットを選択する、
2.融合生成手段ごとに、融合データを生じさせるコードを注入する、
3.融合ターゲットとして使用するためにホワイトボックス実装の中で演算のセットを選択する、及び
4.融合データの部分をその既存の演算と結合するために各融合ターゲットを変換する。
選択された位置は、ホワイトボックス実装への1つ又は複数のスパース実行パスに沿ってあり、これらのスパース実行パスは実装へのすべての考えられるパスの上位セットを表す。例えば、実装への10の異なるパスを有する簡略なプログラムでは、10すべてのパスで出現する3つの位置があることがある。それらの3つの位置は実装へのスパース実行パスを表し、したがってコンテキスト実行のための位置として使用できる。別の例は、それらのパスの半分がすべて同じ3つの位置を通過するが、他の半分はすべて異なる3つの位置を通過する、実装への10のパスを有する簡略なプログラムだろう。このプログラムは、3つの位置の2つのセットのための2つのスパース実行パスを有するだろう。スパース実行パスは互いに交差し、互いを「包含する」こともあり、それらの相対的なトポロジーに対する制約はない。唯一の要件は、実装へのすべての考えられるパスが、少なくとも1つのスパース実行パスによって表されることである。
各生成手段は、通常、融合データの複数部分を生じさせ、その関連付けられた記憶位置に各データ部分を記憶する。記憶位置は現在の生成手段又はその前に実行する生成手段の内の任意のうちの1つに属してよい。位置が現在の生成手段に属する場合、次いで生成手段はその位置を初期化し、データを単にその位置に書き込む。位置が以前の生成手段に属する場合、次いで現在の融合データはすでにその位置あるデータとマージされる。融合データは多くの方法で生じる。最も簡略な方法は、(静的に生じる)無作為の入力値を変換する演算の一意の生成されたシーケンスを実行し、融合データとしてそれらの演算の結果を使用することを含む。また、融合データは他の融合データの部分(例えば、以前の生成手段により生じたデータ)を結合し、アプリケーション自体により生じた選択された値を使用することによって生じさせることもできる。プログラムが複数のスパース実行パスを含む(ほぼすべての重要なプログラムに当てはまるだろう)とき、融合生成手段は、すべてのスパースパスが融合データの同じセットを生じさせるように構築される。複数のスパース実行パスが無い場合、ホワイトボックス実装は(せいぜい)1つのスパースパスから正しく動作するだけだろう。
選択ステップは、概して、総合的な暗号演算に対して大きな影響を有する演算を好む。ただし、これは多くの暗号アルゴリズムに選択クラスタを生じさせることがあるので、選択ステップは、実装を通して選択された位置を可能な限り多く分散することも好む。別の重要な選択基準は、融合変換をサポートするための演算の適切性である。すべての演算が有効なターゲットであるわけではないが、ターゲットの多くは実用的であり、実装全体で十分に分散されるため、この基準は他の基準にほとんど影響を与えない。各変換は、融合データの予期される値だけが、演算に変換前に演算が生じさせたのと同じ結果を生じさせるように構築される。他のすべての値は不正確な結果を生じさせる。
攻撃者が、融合データが使用される直前に、融合データを単にダンプし、自身の目的のためにホワイトボックスを使用する前にこのデータを再作成するのを止めるために、融合データはダンプを著しく困難にする方法で記憶される。融合データの各部分は、(スパース実行パスごとに)1つの特定の融合生成手段によって所有され、融合データを更新する必要のある他の生成手段によってアクセス可能である異なる位置を有する。いくつかの異なるタイプの位置がある。
・ほぼグローバル変数のように、メモリ内のプログラムの書込み可能セクションの中に通常位置する静的な位置、
・ヒープ割当てを通して動的に作成されるヒープ位置、及び
・スタックシフトを介して動的に作成されるスタック位置
スタック位置は、(実行パスと対照的に)ホワイトボックス実装への呼出しパス上にある融合生成手段だけによって使用できる。位置は、常に、位置ごとに一意に符号化される記憶されているポインタ値を通してアクセスされる。各生成手段は、使用するポインタ値を解読する方法を知っている。このようにして、融合データを記憶することは、攻撃者が位置データのすべてを見つけ、ダンプするのに成功することをはるかに困難にするとともに、後続の点でデータを正しく再作成することを一層困難にする。
4.アルゴリズムの小さい部分を隔離することによる攻撃の防止
アルゴリズムのホワイトボックス実装を攻撃する最も効果的な方法の1つは、なんらかの方法で秘密データ(例えば、暗号化鍵)に作用することが知られているホワイトボックスの中で、アルゴリズムの小部分を隔離し、次いで、アルゴリズムのその小部分に対して総当たり攻撃を使用して秘密を抽出することである。暗号アルゴリズムは全体的に総当たり攻撃には非実用的に設計されているにすぎないため、これは効果的である。大部分の場合、これらのアルゴリズムの個々の部分は総当たり攻撃を介した攻撃に極めて実用的である。
アルゴリズム部分を隔離するための極めて効果的な方法は、アルゴリズム実装のメモリアクセスパターンを分析することである。大部分の暗号アルゴリズムは周知の実行パターンを有しており、このパターンは、多くの場合、対応するメモリアクセスパターンに極めて正確に反映され、したがって、しばしば、メモリアクセスパターンの簡略な視覚化でさえも使用することができ、総当たり攻撃を容易にするのに十分な精度でアルゴリズム部分を隔離する。
例えば、AESブロック暗号アルゴリズムは、演算の同じシーケンスの10ラウンド、12ラウンド、及び14ラウンドを実行する。これは、視覚化時に位置を見つけるが容易である関連するメモリアクセスの10/12/14ブロックの対応するシーケンスとして現れる。攻撃者はこれを使用して最後の2ラウンドを隔離し、次いで既知の方法を使用して、これらのラウンドの入力及び出力を観察することによってAES鍵を導き出すことができる。
一実施形態によると、このタイプの攻撃は、攻撃者が暗号演算の個々の部分を隔離するために依存する可能性があるアクセスパターンを排除することによって一層困難になる。メモリアクセスパターンの排除は、アルゴリズムのホワイトボックス実装を通して追加の無作為化されたメモリアクセス演算を注入することによって達成され得る。これらの演算は、実演算によってアクセスされるメモリ位置の同じセットにアクセスするが、無作為化された順序、及び実演算により示されるあらゆるパターンを隠すほど十分なノイズを追加する分散をもってアクセスする。
一実施形態によると、メモリアクセスパターンの難読化は上述されたデコイ生成への拡張として実装される。この拡張は、より多数のデコイを生成することから成り、追加のデコイはメモリアクセス演算のコピーとして作成される。また、これらの追加のデコイは不明瞭な式を通して演算と結合できるが、実際には、性能に対する影響を削減するために、追加のデコイの大きい部分は結合されない場合がある。
一実施形態によると、メモリレイアウトの難読化は、アルゴリズムの小部分を隔離することによって攻撃に対する追加の保護を提供するために、メモリアクセスパターンの難読化に沿って実行される。ノイズを導入することにより、アクセスパターンを難読化しようとするメモリアクセスパターンの難読化とは異なり、メモリレイアウト難読化は、メモリ内のデータフラグメントの位置を無作為化することによってその目標を達成する。
レイアウト難読化がないと、データにアクセスする演算が行うように、関連するデータ部分は通常互いに沿って存在し、これにより視覚化時に識別できるアクセスパターンを生じさせる。メモリアクセスパターンの難読化は、導入されたノイズを通してこれらのパターンを観察するのを困難にするが、該パターンは依然としてそこにある。実演算によりメモリでアクセスされたデータフラグメントの位置を無作為化することによって、関係するデータ部分は互いから分離され、実演算によって示されるあらゆるパターンを壊す。
本発明は、例示的な一実施形態に関して説明されてきた。特定の変更形態が本発明の範囲から逸脱することなく上記構成で行われてよいが、上記説明に含まれる又は添付図面に示されるすべての事項が制限的な意味ではなく、例示的として解釈されることが意図される。
本発明は特に暗号アルゴリズム又は秘密データを操作するアルゴリズムに適用しないが、本発明は任意のアルゴリズムに適用できる。
以下の特許請求の範囲は、本明細書に説明される本発明のすべての包括的及び特定の特徴、及び言語の問題としてそれらの間にあると言われてもよい、本発明の範囲のすべての記述を包含することも理解されるはずである。
本発明は、例示的な実施形態に関して説明される。当業者は、本発明が多くの異なる用途及び実施形態で実装され得、特に本明細書に図示される特定の実施形態にその応用が制限されていないことを理解する。
本発明の例示的な実施形態は、標準的な(非ホワイトボックス)実装のソースコードから直接的に任意の暗号アルゴリズムのホワイトボックス実装を自動的に生成するためにホワイトボックス実装を生成する方法に関する。
別の例示的な実施形態は、秘密データが動的である、つまり実行時にだけ知られるホワイトボックス実装を生成する方法に関する。
別の例示的な実施形態は、ホワイトボックス実装がアウトオブコンテキストで使用される、つまりその使用目的のためにアプリケーションによってよりむしろ、悪意のある目的のために攻撃者によって直接的に呼び出されるのを防ぐ方法に関する。これらのそれぞれは以下に同様に説明される。
図1は、本発明の例示的な一実施形態を実践するために適した環境を示す。電子装置CMPは、本発明の一実施形態に係るソフトウェアが記憶されるメモリMEM、メモリMEMに記憶されているソフトウェアを実行するためのプロセッサ(CPU)PRC、及びシステムハードウェアを制御するための他のプログラムを含む。通常、電子装置CMPと人間のユーザとの相互作用は、ユーザインタフェース等の入力/出力(I/O)装置を通して発生する。I/O装置は(モニタ等の)表示装置DSP、並びにマウスMS及びキーボードKEYB等の1台又は複数の入力装置、並びに/又はタッチスクリーン及びネットワークインタフェース等の他の適切な従来のI/O周辺機器を含んでよい。
メモリMEMは、アルゴリズムの実装の標準ソースコードPGSCから直接的にアルゴリズムのホワイトボックス実装を自動的に生成できるアプリケーションWBGNを保持する。
電子装置は、コンピュータ、又はスマートフォン、デジタルタブレット、もしくは接続されたオブジェクト等の任意の他の計算装置であってよい。
代替的な実施形態では、電子装置CMPは、さらにインターネット等のネットワークとインタフェースで接続される。当業者は、プログラムソースコードPGSCが電子装置CMP上でローカルに又はネットワーク上で電子装置とインタフェースで接続される遠隔位置のどちらかに記憶されてよいことを認識するだろう。同様に、ホワイトボックス生成アプリケーションWBGNは、ネットワーク化されたサーバ又は遠隔ピアに記憶されてよい。
1. ホワイトボックス実装の生成
一実施形態に従ってホワイトボックス実装を生成する方法は、それぞれが図2に示されるように複数の段階に分割される2つの主要なプロセスP1、P2を含む。プロセスP1、P2は実装コア生成P1及び実行マシン生成P2である。実装コア生成P1のプロセスは、暗号アルゴリズムであってよい入力アルゴリズムの初期のホワイトボックスバージョンを実装する低レベル演算のセットを生成する。この演算のセットは入力アルゴリズムよりもはるかにより複雑であり、鍵抽出攻撃に抵抗するための多くの技法を利用してよい。
実行マシン生成のプロセスP2は、まだ容易に実行可能な形式ではない上記に生成された演算のセットを鍵抽出攻撃に対する追加の保護を提供してよい実行可能な形式に変換する。このプロセスの出力は、既存のプロジェクトにコンパイルし、直接的に実行できるスタンドアロンソースコードである。スタンドアロンソースコードは通常、Cソースコードであるが、Java等の他の実装言語も使用できる。
方法のプロセスP1、P2は、アルゴリズムソースコードを解析することによって生じる中間表現(IR)として入力アルゴリズムを受け取る。暗号アルゴリズムはCで最も一般的に実装されるが、方法はコンパイルされたプログラミング言語及び解釈されたプログラミング言語の両方に適用可能である。方法によって生じるコードは、コンピュータ、スマートフォン、もしくはデジタルタブレット等の任意の計算装置、又は任意の接続されたオブジェクトによって実行されるように適応されてよい。保護されるアルゴリズムを実行することを目的とした装置がオープンプラットフォームの周りに設計される、及び/又は公衆網に接続されるときに、方法はいっそう有用である。
プロセスP1、P2はより詳細に以下に説明される。実装コア生成P1のプロセスは、入力アルゴリズムの初期のホワイトボックスバージョンを実装する低レベル演算のセットの生成を担う。一実施形態によると、プロセスP1は秘密の爆発及び融合、並びにデコイ生成の2つの段階S11、S12を含む。秘密の爆発及び融合の第1の段階S11は、低レベル演算の大きなセットにアルゴリズムを拡大し、各演算が使用する任意の秘密データと各演算を結合する。演算及び秘密データの組合せは、実際の秘密データフラグメントをその元の形式で使用しない方法で表される。
デコイ生成の第2の段階S12は、プロセスP1によって提供される実演算に沿って存在し、実演算とともに実行する、複製および変異されたデコイ演算の大きなセットを生じさせる。これらのデコイは、実装によるデータの信頼できる流れの確立を極めて困難にする方法で、実演算とおよび処理されるデータに相互に作用する。
一実施形態によると、段階S11は、図3に表されるように以下の4つのステップを含む。
‐アルゴリズム拡大(S31)、
‐部分的な評価(ステップS32)、
‐秘密の爆発(ステップS33)、及び
‐秘密の融合(ステップS34)
アルゴリズムの拡大のステップ31で、アルゴリズムは、使用可能な静的入力データ(例えば、秘密データ)が与えられると、アルゴリズムを実装するために使用される演算の完全なセットに拡大される。これらの演算はその最もインライン化され、展開された形式でアルゴリズムを表す。このステップは、演算間を流れるデータの値とともに、演算間のすべての知り得るデータ依存性をモデル化するデータ依存性グラフも生じさせる。
部分的な評価のステップ32では、演算は、統計的に既知の値を生じさせる演算を排除する部分的な評価を受ける。このステップの主要な目的は、秘密データがその最も導き出された形式で、及び秘密データが非静的データ(例えば、暗号化/解読データのブロック)と相互作用を開始する点でのみ存在するように、秘密データに対する中間演算を排除することである。
秘密の爆発のステップ33で、導き出された秘密データを含んだあらゆる残りの演算は、それぞれの新しい演算が元の演算よりも導き出された秘密データのより小さい部分を使用するように複数の演算に分割される。このプロセスは、導き出された秘密データの特定数のビットよりも多くを使用する演算がなくなるまで繰り返し適用される(単一ビットと同じ程度に低いことがある)。
秘密の融合のステップ34で、秘密データの導き出された部分のすべては、データを記憶するよりむしろデータを生じさせる演算の一意のセットに変換される。演算のこれらの一意のセットは(以下に説明されるように)シーケンスに影響を受ける。つまり、演算が生じさせるデータは、その点まで実装によって実行される以前の演算のほぼすべてに依存する。これらのデータを生じさせる演算は、次いでデータの生成及びデータの使用がほぼ区別ができないように、データを使用する演算と結合される。
アルゴリズムの拡大のステップS31で、アルゴリズムは、使用可能な静的入力データ(例えば、静的鍵データ)が与えられると、アルゴリズムを実装するために使用される演算の完全なセットに拡大される。これらの演算は、アルゴリズムをその最もインライン化され、展開された形式で表す。単純な例として、拡大プロセスは以下の疑似コードに適用される。
この疑似コードは、単純なループ及びこのループに対する入力「a」及び「I」を含む。この疑似コードの拡大は、まず、以下の演算を生じさせる。
この拡大された疑似コードでは、ループは展開され、条件(「if」)文は排除された。
関数呼出し及びより多くのプログラムの流れの制御を含んだより複雑な例は、インライン化される関数及び排除されている非到達コードも示すが、この単純な例はプロセスの残りに取り組むときに明瞭さを補助する。また、この拡大ステップは、演算間を流れるデータの値とともに演算間のすべての知り得るデータ依存性をモデル化するデータ依存性グラフも生じさせる。上記の簡略な例のこのグラフの表現は以下の通りである。
上記の表現では、別の演算に対する依存性を有する各値は、以下の形式で中括弧内の依存性情報で修飾される。
{値:#ソース:状態}
「値」が(その時点での)その値の実行時の内容である場合、「ソース」はその値を生じさせた演算であり、「状態」は、値が(「c」で示される)一定の入力だけから導き出されるのか、それとも(「v」で示される)少なくとも1つの可変入力だけから導き出されるのかを示す。例えば、行7で、修飾されたメモリ位置「a」は行5の演算によって生じた20の実行時値を有し、値は一定の入力データだけから導き出される。注目されるのは、ここに示される例がプロセスの表現にすぎず、プロセスを実装するために使用される物理的表現に直接的に対応しないことがある点である。例えば、本発明の現在の実施形態では、演算はここに示される疑似コードよりも低いレベルに存在し、「for」ループ等の構成体を有さない。また、現在の実施形態は実施形態自体を、わずか1つの出力を有する演算に制限し、このことが依存性モデルを簡略化する。ただし、プロセスは幅広い範囲の物理表現に適用できる。
アルゴリズムの拡大ステップS31は、以下を含む、アルゴリズムを実行し、実行中に起こることを記録するシミュレータを生成することによって達成される。
‐実行される各演算は、そのパラメータの実際値及び該値の一定状態/可変状態とともに記録される、
‐関数呼出し、関数終了、条件分岐、及び無条件分岐を含んだすべての制御フロー変更が記録されるが、すべての制御フロー変更の影響は記録されている通常の演算にすでに存在するため、通常の演算とは異なるとして記される。例えば、関数が呼び出される場合、次いで記録は以下のシーケンスを含む。1)呼出し演算、2)呼び出された関数の中の演算、3)関数終了、及び4)呼出し側の関数の残りの演算、並びに
‐演算により書き込まれるすべてのメモリ位置の状態は、その位置に書き込むための最後の演算、及びその演算の結果としてのその位置の一定状態/可変状態を(それぞれについて)記憶するマップに記録される。演算の入力値がすべて一定である場合、次いで書き込まれたメモリ位置は一定として記録されるだろう。それ以外の場合、メモリ位置は可変として記録される。
例のコードについてメモリ状態マップの更新方法は以下の表1に示される。
表1のそれぞれの表の行は実行中の各演算、及びその演算が実行された後のあらゆるメモリ位置の状態を表す。各メモリ位置「a」及び「i」はその位置の値、その位置に書き込むための最後の演算、及び位置の一定/可変(c/v)状態を示す3つの列によって表される。位置「a」及び「i」は演算1から12に交互に変更される。再び(行7の)演算7を見ると、演算が(行6からの読取りを)実行する前に、「a」の位置が20の値を有し、上記のデータ依存性グラフに記録される依存性情報に相当する演算5によって最後に書き込まれたことが分かる。演算7が(行7の後に)実行した後、分かるように、位置「a」は変化し、ここでその最後の演算が現在7に設定された状態で30の値を有する。
この単純な例コードを用いると、メモリ状態マッピングの使用が過剰に見える可能性がある。状態データは単に各変数(a及びi)に関連付けられ、同じ結果を達成できるだろう。ただし、実際のプログラムはアレイ、構造、割り当てメモリ、及びポインタエイリアシングを含んだはるかに複雑なメモリアクセスパターンを有する。メモリ状態マッピングは単一の機構ですべてのメモリアクセスパターンをサポートすることを可能にする。
シミュレータがアルゴリズムを実行するとき、いくつかのコードが実際には実行されないことがある。これが望ましい場合もある。アルゴリズムが決して実行されない非到達コード又は条件付きコードを含む場合があり、これは当然シミュレーションプロセスで廃棄される。ただし、アルゴリズムに応じて、シミュレーション中にコードが実行されないが、異なる条件下にあるだろう場合がある。これが発生するとき、コードが既知の静的データだけに基づいた決定のために実行されなかったのかどうかが確証される。これが当てはまる場合、コードは単に未使用のコードとして分類される。当てはまらない場合、次いでコードは入力依存コードとして分類される。入力依存コードは、代替的な決定を下させるだろう入力のセットを所与として、シミュレーション中に実際に実行された演算の代わりに決定論理を実行できるようにする決定論理とともに、演算の拡大されたセットに元の欠損コードを注入することによって処理できる。これにより、結果として生じる実装は、未知の入力に直面するときに機能できるが、再注入されたコードは完全な依存性情報を有しておらず、このことは以降のステップでのそれについて推測する能力を制限する。
多くの場合、入力依存コードは存在しないか、又はコードの小部分を表すにすぎないかのどちらかであり、したがって重要な問題とはならない。入力依存コードがより普及している場合、上記の解決策は以降の処理ステップを適切に実行する能力を制限し、このことは同様にホワイトボックスプロセスによって提供される保護を全体として制限するため、解決策は理想とは程遠い。これを軽減するために、シミュレーションは、異なる実行時入力で複数回実行され、これらのシミュレーションの結果をいくつかの実行時決定論理で演算の単一の拡大されたセットに結合することを可能とされる。シミュレータがすべての可能な実行パスを見ることができるように入力が選択される場合、次いで演算の完全な拡大されたセットが構築できる。各入力依存コードパスであるが、そのすべてのインスタンスではない、少なくとも1つの実行が検出される場合でも、実行時の値情報を伴わない依存性グラフが構築できる。
部分的な評価ステップS32で、演算は、統計的に既知の値を生じさせる演算を排除する部分的な評価を受ける。このステップの主な目的は、秘密データがその最も導き出された形式で、及び秘密データが非静的データ(例えば、暗号化する/解読するデータのブロック)と相互作用を開始する点でのみ存在するように、秘密データに対する中間演算を排除することである。このステップはアルゴリズムのインライン化され、展開されたモデルに作用するため、及び秘密データは静的入力データとして取り扱われるため、この結果、演算の大きな部分が排除される。これを示すために、単純な例のプログラムに適用されるときのこのステップの結果が以下の行に削減できる。
この結果は、メモリ位置「a」及び「i」に対する演算のすべてが統計的に既知の値を生じさせるために発生する。両方とも定数値で初期化され、次いでその現在の値を別の定数値と結合することによって連続的に修正される。つまり、その出力はつねに統計的に既知である。現実には、これらの2行のコードでさえ実際には存在しないだろう。プログラムが変数「a」及び「i」を使用した他のコードで拡大された場合、それらの演算は、定数及び変数「a」及び「i」が存在しないため、値50及び5を直接的に使用するだろう。変数「a」及び「i」が後のコードによって使用されなかった場合、次いで該変数は単に存在しないだろう。完全な部分的な評価プロセスは相対的に複雑であるが、基本的なプロセスは単純な例のプログラムを使用して示すことができる。データ依存性グラフからの依存性情報とともに拡大された形式で開始すると、演算1で開始し、演算1は演算2が行うように統計的に既知の値を明確に生じさせるため、演算1を排除できる。また、演算3は、演算3が、依存性情報が一定であると示す値「a」をリテラル値(10)に結合するため統計的に既知の値も生成し、したがって、演算3も排除できる。同じことは残りの演算にも当てはまる。つまり、残りの演算のすべてを排除できる。これにより、50の値を有する変数「a」及び5の値の変数「i」が残されるが、それらの値を生じさせるための演算は必要としない。論理的には、上記に示されている2つの代入が存在するが、2つの代入は実際の代入として絶対に存在しない。
変数(統計的に既知ではない)値及び演算の完全にインライン化され、展開された性質が検討されるとき、プロセスはより複雑化する。多くの場合、完全にインライン化され展開された演算でホワイトボックス実装を生成することは実際的ではない。結果として生じる実装は大きすぎて実用的ではないだろう。実用的な実装を生じさせるため、インライン化及び/又は展開のいくらかは排除される必要がある。これらのことを排除する問題は、演算の中の統計的に既知のデータの量に大きく寄与する点である。簡単な例のプログラムを見ることによって、なぜかが分かる。展開されたコードがループに戻されなければならない場合、次いで「a」及び「i」の両方とも(一定の入力だけから導き出されているにも関わらず)変数になり、同様にそれらの変数を使用した任意の後続コードを「汚染し」、その出力を可変にするだろう。同様の影響は、インライン化が排除されると発生する。これに関する問題は、主要な目標が、秘密データをその最も導き出された形式で可能な限り遠くまで実装の中に伝搬することであり、この伝搬は、秘密データが任意の可変データに出会うときに終了する。
したがって、部分的な評価ステップS32の目標の1つは、ステップが実装を通して導き出された秘密データの伝搬に対して与える影響を最小限に抑えつつ、該部分的な評価ステップができる限り多くのインライン化及び展開を排除することである。これを行うために、決定モデルが確立され、秘密データ伝搬の損失におけるコストに対する、インライン化/展開を排除することにより獲得される利益のレベルを表す、関数及び基本ブロックに対するスコアが割り当てられる。スコアの利益構成要素は、排除が提供するだろうコード削減の量に比例する。コスト構成要素は、排除によって影響を及ぼされる秘密データのすべての部分の伝搬損失を合計することによって計算される。個々の伝搬損失は、秘密データの部分その最も導き出された形式であっただろうものに到達する前に秘密データの部分が関与する追加の演算数を測定することによって計算される。コスト構成要素の当然の結果は、呼出しグラフの上部に近いコードが、呼出しグラフの終わりにあるコードよりもはるかに高いコストを有する傾向がある点である。このため、決定プロセスは下から上に作用し、十分なコード削減が達成されると終了する。この簡略化された例は図5に示される。
図5の上部の列番号はグラフの部分を指し、呼出しグラフは下に示され、各ボックスは関数の部分(ボックス内側に示される関数名)を表している。より幅広いボックスはそれらの中のより多くの演算を伴う関数の部分を表している。実行の開始は左上部にある。呼出しは下向き矢印で示され、関数終了は上向き矢印で示される。すべての呼出しは親関数のループの中で実行され、呼出しカウントが下向き矢印に示される。
呼出しグラフの下方に、2行の情報「H」及び「CTS」が示され、それぞれの列はそのすぐ上にある呼出しグラフ要素と関連付けられている。「H」行は、対応する列内の各要素が実行される合計数を示す。呼出しグラフの下部の関数「e」及び「f」は、ループ化された呼出しのいくつかのレベルのため、多くの回数にわたり実行される。「CTS」行は、対応する列のどのくらいの数の演算が一定の導き出された秘密データを生じさせるのかを示す。
これは簡略化された例であるため、インライン化/展開を排除するコストは、影響を及ぼされる領域の中で一定の導き出された秘密データを生じさせる演算の数に比例しているとしてモデル化される。上述されたように、実際のコストは秘密データの伝搬損失を測定することにより計算される。これに対して、この例は伝搬損失がつねに1である、つまり、例示的な目的にとって妥当な概算であるとみなされる。
図5の例から取得されるスコア計算は、以下の表2に提示される。
「利益」の列の結果は「サイズ*H」として計算され、「自己コスト」の列の結果は「CTS*H」として計算される。「子コスト」の列の結果は関数の子供(関数が呼び出す関数)の「自己コスト」数を加算することによって計算される。「コスト」の列の結果は「自己コスト+子コスト」として単純に計算される。子コストを含む理由は、コードの領域に対するインライン化/展開が排除される場合、この排除はインライン化/展開に依存するほぼすべてのものに影響を及ぼすだろうという点である。関数の場合、その関数が呼び出す関数を意味する。最後に、列「スコア」の結果は「利益/(コスト+1)」として計算される。表2から分かるように、関数「b」は最高スコアを有するとして第1の候補となるだろう。関数「b」かなり小さい利益を有するが、ゼロコストを有すため良好な選択肢になる。次の候補は、かなり高いコストを有するが、非常に大きい利益も有する関数「e」となる。この関数「f」が使用されると、関数「f」の利益とコストの両方とも非常に大きいが、依然として利益が勝る。関数「a」、「c」、及び「d」は、特に悪い候補となるだろう。つまり、呼出しグラフの上部にあることは、非常に大きいコストを有し、呼出しグラフの上部の関数のいずれも大きな利益を有さないことを意味する。
注目されるのは、実際には、スコア計算は各選択がなされるたびに実際に変化する点である。特に、選択と関連付けられたコストは一度しか発生せず、したがって、やはりそのコストを含んだ任意の他の選択はそれらのコストを相応して削減させる。
ステップS33で、導き出された秘密データを含んだあらゆる残りの演算は、それぞれの新しい演算が元の演算よりも、導き出された秘密データのより小さい部分を使用するように、複数の演算に分割される。各タイプの演算は多くの異なる方法で分割できる。例えば、「s」が秘密データであり、「t」が(おそらく可変)データの別の部分である32ビットの乗算演算「s*t」を考える。この演算は、各シフト演算が「s」からの単一のビットを表すシフト演算及び加算演算のシーケンスに分割できる。代わりに、乗算演算は、各乗算が「s」の少数のビットしか使用しない乗算及び加算のシーケンスに分割できるだろう。より簡略な例の場合、以下のXOR演算を検討する。
上記の例と同様に、「s」は秘密データであり、「t」は(おそらく可変)データの別の部分である。明確にするために、両方の変数「s」及び「t」はそれらの値を代入して示されている。実際には「s」の値はXOR演算の中で「リテラル値」として直接的に使用され、「t」はいくつかの可変値を伴い既に存在する。この演算は、以下に示すように、2つのXOR演算及び1つのOR演算から成るシーケンスに分割できる。
この場合、分割は「s」及び「t」の上部16ビットに対してXORを実行し、下部16ビットにXORを実行し、次いでOR演算と結果を結合することによって達成された。さらに小さい部分に構成要素を分割することは、本方式の自明の拡張である。例えば、構成要素は4つのXOR及び3つのORを使用し、4つの8ビット部分に分割できる。
ここに示す例は単一の演算に関して秘密データを分割することしか含んでいない。しかしながら、実際には、秘密データを含んだ演算を第1の演算の結果に(したがって秘密データに)依存する後続の演算と結合することによって演算のシーケンスで行われる。
この例は、以下に示される。
この例で、秘密データ「s」は「t」とXORされて、「u」を生じさせ、「u」は後続の行4で使用されて「w」を生じさせる。「s」に全く依存していない行3の存在は、「s」の従属物が連続しない可能性を示すのに役立つ。実際に、従属物は多くの関連していない演算によって分離されてよい。複数の演算に関して秘密データを分割するために、この例は以下に示されるように書き直すことができ、
この場合、行3はその値(「s XOR t」)を生じさせる演算で元のコードの「u」を置換する式である。
「s XOR t」のために分割演算を生じさせる代わりに、分割演算は「s」に対する2つの従属演算のシーケンスを表す式「(x XOR t)*v」のために作成される。これは、導き出された秘密データから従属物の任意の深さに拡張できる。この爆発プロセスは、導き出された秘密データの特定数より多いビットを使用する演算がなくなるまで繰り返し演算のセット全体で適用される。また、導き出されたデータの各部分が分割されるビット数は、導き出されたデータがどのようにして元の秘密データに関係するのかにも依存する。導き出されたデータと元の秘密データが相互に強く関連している場合、より少数のビットに分割される傾向がある。
秘密の融合のステップS34で、秘密データの導き出された部分のすべて(多くは単一ビットほど小さくてよい)が、データを記憶するよりむしろデータを生じさせる演算の一意のセットに変換される。演算の一意のセットは(以下に説明されるように)シーケンスに影響を受ける。つまり、演算が生じさせるデータはその点までに実装によって実行された以前の演算のほぼすべてに依存している。これらのデータを生じさせる演算は、次いでデータを使用する演算と結合され、これによりデータの生成及びデータの使用はほぼ区別ができない。
一実施形態によると、デコイ生成の段階S12は、図4に示されるように以下のステップを含む。
‐複製及び変異のステップS41、
‐演算インタリーブのステップS42、及び
‐データフロー融合のステップS43
複製及び変異のステップS41で、秘密の爆発及び融合の段階は多数回繰り返され、無作為なデータが秘密データを置き換えて、選ばれたアルゴリズムの代替のデコイ実装を表す演算のセットを生じさせる。
演算インタリーブのステップ42で、生成された演算(実及びデコイ)のすべてが、各セットからの演算が他のセットのすべてからの演算とインタリーブされる、演算の単一の大きなセットに結合され、これによって結合されたセットが実行されると、該結合されたセットは演算のすべてのセットを効果的に実行している。
データフロー融合のステップS43はインタリーブの後に実行される。このステップを実行する前に、演算の結合されたセットはまだ演算の関連のないセットから成り、互いの間に単に位置する。この最終ステップで、これらの関連のない演算は、演算の全体の組み合わされたセットを通るデータフローを決定するのが困難になるように互いと融合される。
複製及び変異のステップS41で、秘密の爆発及び融合の段階は無作為なデータで多数回繰り返されて、選ばれたアルゴリズムの代替のデコイ実装を表す演算セットを生じさせる。生成プロセスは秘密データの値に依存しているため、生成された演算の各セットは一意となる。結果は実質的に変異されているので、これを変異と呼ぶが、実際のプロセスは異なる開始シードで演算を生成することである。デフォルトにより、無作為に生成されるデータは単に実際の秘密データの代わりに使用される。これは、秘密データが無作為データと区別ができないときにはよいが、秘密データのいずれかがこの特性を有していない場合、デコイデータは秘密データの性質によりよく一致する使用法に必要とされる。これは、無作為に生成されたデータをデコイ秘密データとして適切にするために、アルゴリズムが無作為に生成されたデータを調整するアルゴリズム特有フィルタを提供できるようにすることによって解決される。
演算インタリーブのステップS42で、生成された演算(実及びデコイ)のすべてが、図6に示されるように演算の単一の大きなセットに結合される。図6は、インタリーブされて演算の単一の大きな結合されたセットC1を取得するデコイ演算セットDI1、DI2、DI3、DI4、及び実演算セットR1を示す。演算セットCIでは、各演算セットDI1からDI4及びR1の演算が、(セットの上下の矢印に従って)他のセットのすべてからの演算でインタリーブされ、これにより、結合されたセットC1が実行されるとき、実質的にすべての演算セットDI1からDI4及びR1を実行している。インタリーブは、たまたま互いに近い異なるセットからの演算間に直接的な対応がないように、部分的に重複するように特に設計される。特に、演算RIの実セットは結合されたセットC1のまさに開始及びまさに終了から常に離れて位置する。
インタリーブがステップS42で発生した後も、演算の結合されたセットは、単に互いの間に位置する演算の関連のないセットから成る。データフロー融合の最終ステップS43で、これらの関連していない演算は、全体的な、演算の結合されたセットを通って流れるデータが決定するのが困難になるように互いと融合される。これは、発信データフローのある演算のグループを漸次的に選択し、その出力データのすべてを、その出力データを正しい受入れ演算に送る新規に生成された演算を通してプッシュすることによって達成される。このルーティング演算は、(以下に説明されるように)シーケンスに影響を受ける融合をさらに使用する一意に生成された不明瞭な式を使用して構築される。これがどのように機能するのかを見るために、図7Aの例は、データフロー融合を使用して結合する演算の2つの個別のセットを示す。図7Aは左側に演算「a1」、「a2」、右側に演算「b1」、「b2」を示す。演算「a1」は2つの入力「I1a1」及び「I2a1」を有する。演算「b1」は2つの入力「I1b1」及び「I2b1」を有する。演算「a2」は変数「I1a2」及び演算「a1」の出力を受け取る。演算「b2」は変数「I1b2及び演算「b1」の出力を受け取る。データフロー融合を使用して演算「a1」、「a2」及び演算「b1」、「b2」を結合するために、追加の演算は演算「a1」と「a2」との間、及び演算「b1」と「b2」との間でも追加されるため、これらの演算は、演算「a1」及び「b1」がともに、演算「a2」又は「b2」のどちらかが実行される前に実行するように位置決めされる。これらの演算に対してデータフロー融合を実行することの結果は、図7Bに示される。図7Bでは、ルーティング演算ROPは、演算「a1」及び「b1」を実行した後であるが、演算「a2」又は「b2」を実行する前に実行するように挿入される。図示の通り、演算「a1」及び「b1」はそれぞれ演算「a2」及び「b2」にその出力を渡すよりむしろ、演算「a1」及び「b1」はルーティング演算ROPに出力を渡し、ROPが次いで出力を正しい受取人、つまり演算「a2」及び「b2」に渡す。ルーティング演算ROPによって使用される不明瞭な式は、どの出力がどの受取先に行くのかを決定するのを非常に困難にする。特に、静的分析を介して決定するのはほぼ不可能である。データフロー融合プロセスは、演算の結合されたセットのデータフローのすべてが十分に融合されるまで進む。
実装コア生成プロセスによって生じる演算のセットはその形式では実行できないため、該演算は、実際に使用できる実装を生じさせるために実行可能な形式に変換される。実行マシン生成プロセスP2はこの変換を実行し、ソフトウェアプロジェクトの中に含まれ、所望される暗号演算を実行するために直接的に呼び出すことができるソースコードを生じさせる。ただし、一実施形態によると、演算のコードへの単純で直接的な変換を実行するよりむしろ、プロセスP2は、鍵抽出攻撃に対する重要な追加の保護を提供する演算を実行するための専用マシンを生成する。
概念レベルでは、生成されたマシンは、バーチャルプログラムを処理し、バーチャルマシンモデルとの関連でそのプログラムによって指定される演算を実行する実行エンジンがあるという点で、バーチャルマシン(VM)にほぼ類似している。ただし、実装レベルでは、多くの重要な相違点がある。
それぞれの生成されたマシンは一意である。つまり、該マシンが実行できる演算、該マシンの演算の実行方法、演算が表される方法、及び演算を実行する機構はマシンごとに一意であり、
マシンは命令セットを有していない。つまり、所与のマシンが実行できる演算のセットは命令セットであると見なすことができるだろうが、該演算は、該演算が名称を与えられ、係るように使用できるようにするだろう識別できる概念上の意味を有しておらず、
マシンはプログラムを実行しない。つまり、所与のマシンは1つの特定のプログラムを実行できるにすぎず、そのプログラムはマシン自体の一体部分であり、多くの場合、マシンの実行側とプログラム側との間に境界はなく、
マシンには実行エンジンはない。つまり、各マシンは演算を実行することを担う多数の実行要素から成り、これらのそれぞれも実行する次の演算を決定することを担い、すべての実行ステップに関与する「中心的なエンジン」はなく、
マシンはバーチャルマシンモデルを有していない。つまり、任意の所与の演算の実装は特定のバーチャルCPU又はその実装方法に関して何らかの制限を課す任意の他の構造と関連付けられておらず、これに対する唯一の例外は、関数呼出しを実装するために使用されるプログラムスタックはあるが、マシン内部呼出しに使用される所定の呼出し規則はなく、
マシンは統計的に分析できない。つまり、命令セットなし、識別可能なプログラムなし、及びマシンモデルなしで一意のマシンを静的に分析する上での固有の困難さは別として、マシンを実行するプロセスは(以下に説明する)シーケンスに影響を受ける融合演算に完全に依存し、マシンのどの部分も、実行がその部分に達するまで(マシン自体によってでさえ)理解できない。
一実施形態によると、マシンを生成するプロセスは、図2に示されるように、以下のステップを含む。
小さい均一な命令セットに関して表される実装コア生成プロセスP1によって生じる演算のセットを、はるかに大きい不均一の命令セットに関して表される演算に変換する演算再表現のステップS21、
ステップS21から取得される再表現された演算の実装を生じさせる演算実装のステップS22、
シーケンスに影響を受ける融合を利用するための演算実装を変換して、静的分析に耐えるシーケンス融合のステップS23、及び
シーケンス融合ステップS23によって生じる実装の構成要素のすべてに適用され、実行可能な形式での出力される準備が完了しているコード生成のステップS24。
演算再表現のステップ21の出力は命令セットを有するものとして参照されるが、各命令の中に含まれる副演算は、副演算が従来の意味で命令のように使用するために集合的な名前を与えられることを可能にする有意義で概念的な関係性を互いに対して有さないため、厳密に命令セットとしての適性はない。例えば、「関数呼出し」命令は通常、個々の意味(例えば、スタック上に値をプッシュし、別のプログラム位置にジャンプする等)を有する副演算のシーケンスから成るが、個々の意味を「関数呼出し」という名称の単一命令としてともに表現できるようにする結合された意味も有する。ここで、レジスタr0に1234を追加して新しい命令を作る命令と結合されたこの関数呼出しシーケンスを検討する。この新しい命令は、何をするのかを表すために、「呼出し関数及び1234追加、r0」(又は何か類似するもの)と呼ばれなければならないだろう。例えば、10以上の命令がこのような方法で結合される場合、新しい命令の結果として生じる名称は複雑且つ特有すぎて、概念的に意味を持ち得ない。
所望される変換を達成するために、ステップS21は2つのステップ、つまり、演算書直しの第1のステップ、及び演算結合の第2のステップで実行される。演算書直しの第1のステップは、演算のシーケンスを、不明瞭な式、算術/論理書直し、及び総当たりの同等コード生成等の周知の難読化変換を使用し、意味的に同等な代替形式に変換する。演算のシーケンスは無作為に選択され、無作為に選ばれた難読化変換で変換される。このプロセスは、十分なレベルの変換が発生するまで繰り返す。それぞれの個々の演算はこのプロセスの間に複数回変換されてよい。このステップの主要なプロセスは第2のステップのためにコードの均一性を削減することである。難読化変換の使用は、結果として生じるコードを理解するのをより困難にさせるのにも役立つが、これは全体的なプロセスの重要な部分ではない。
演算結合の第2のステップは、演算のシーケンスを結合して、各命令が命令を生じさせるために結合された演算のシーケンスを表す、新しい命令セットを生じさせる。結合プロセスは、第1の演算で開始し、無作為な数の後続の演算を選んで、結合することによって(関数ごとに)機能する。演算のシーケンスは結合され、新しい命令インデックスと関連付けられる。このプロセスは、次いで、次に使用可能な(結合されていない)演算に移動し、すべての演算が処理されるまで、演算を無作為な数の後続の演算等と結合する。このステップの目的は、各命令を構成する演算間に概念上の関係性がない新しい命令セットを生じさせることである。これは、結合プロセスだけで達成できるが、書直しステップの不均一な結果に結合プロセスを適用することははるかにより効果的な結果を生じさせる。
上述された演算結合ステップは多様な点で改善できるだろうが、単純且つ効果的である。例えば、プロセスが関数の終わりに到達すると、結合されるために使用できる演算数は、最後の新しい命令が単一演算から形成される最悪のシナリオで削減される。この段階でのコードのかなり展開され、インライン化された性質は、コードの相対的に小さい部分に影響を及ぼすことを意味するため、これが実際に重要な問題を提起する可能性は低い。これが問題になると、問題は結合シーケンスを事前に計算し、すべてのシーケンスが十分に最小のサイズになるまでその境界を無作為に再分配することによって排除できるだろう。
演算実装のステップS22は、前のステップS21から再表現された演算の実装を生じさせる。演算実装は以下の部分を含む。
1.新しい命令を生成するために結合された演算の副演算実装部分、
2.パラメータ解読論理‐いくつかの演算は複数のコンテキストで実行されてよい(プログラムを実行することにほぼ同等)。これらの演算は、演算ごとに一意に符号化されるパラメータの形式でコンテキスト特有の入力及び出力を受け取り、
3.実行継続論理‐各演算実行後、次の演算及びそのコンテキスト(演算がコンテキストを有する場合)が解読され、実行は次いでその演算の実装によって継続される。
シーケンス融合のステップS23は、静的分析に抵抗するために(以下に説明される)シーケンスに影響を受ける融合を利用するための演算実装を変換する。この段階の前に、演算実装は互いの上に直接的にチェーンを作り、各演算実装は静的に独自の入力/出力及び連続パラメータを解読する。この段階の後、各演算実装は、同様に次の演算実装の上にチェーンを作るデコーダ実装の上にチェーンを作る。デコーダ実装は、次の演算実装の位置及びそのパラメータの解読を担い、これらはシーケンスに影響を受ける融合値を使用してデコーダ実装ごとに一意に符号化される。
演算実装によってチェーンが作成される特定のデコーダ実装はコンテキストに特有である。つまり、演算実装はパラメータとして特定のデコーダ実装を受け取り、特定のデコーダ実装がどのデコーダにチェーンを作成するのかの静的な知識を有していない。この変換の結果は、演算実装が、使用の時点でのみ解決され、演算シーケンスの静的分析を極めて困難にするデコーダのコンテキストに特有の動的なセットを通して互いから分離されることである。
シーケンス融合ステップS23が完了後、実装の構成要素のすべては実行可能な形式で出力される準備ができている。コード生成の最終ステップS24で、演算実装のすべては、既存のプロジェクトの中にコンパイルし、直接的に実行できるスタンドアロンソースコード部分としてともにレンダリングされ、通常Cソースコードであるが、他の実装言語も使用できる。
プロセスP2は、ホワイトボックス実装を実行できる実行マシンを生成することを含む。このマシン生成は、プロセスP1で実行される他のホワイトボックス生成ステップによって使用される技法に加えて、ステップS21、S22、S23の難読化技法を使用する。
実行マシンの生成は、これらの追加の難読化のすべてが実行マシン内のどこかで利用されることを仮定している。これは依然として特定の場合には当てはまることがあるが、経験は、これらの難読化が、プロセスP1の他のホワイトボックス生成ステップによって使用される難読化よりも(暗号アルゴリズムを保護することに関して)効果がより少なく、性能影響及びコードサイズに関して最も高価な難読化であることが実験により分かった。
一実施形態によると、最も効果的な難読化の使用を最大限にし、全体的な性能/サイズの影響に対するより多くの制御を提供するために、実行マシンは、複雑度を最大制御のための演算ごとのレベルで変えることができる可変難読化複雑度により生成される。最低レベルの複雑度では、演算のために生成されたコードは、本来、演算と演算が作用しているデータとの間の(たとえあったとしても)リダイレクション機構のほとんどない演算の単純なC実装である。このレベルの複雑度で生成されるコードは通常、最大複雑度で生成されるコードよりも10倍から100倍速く、さらに著しく小さい。任意の所与の演算の場合、複雑度レベルは最小複雑度と最大複雑度の間のレベルの大きい範囲の内の1つに設定できる。レベルが増すにつれ、マシン生成に使用可能な多様な難読化が漸次的に有効にされ、最大レベルはすべての使用可能な難読化を利用する。
各演算は個別の複雑度レベルを有することがあるが、実際には、複雑度レベルはより大きな精度で、おもに入力コードの機能単位レベルで指定され、特定の場合、関数の中のブロック単位レベルで指定され得る。複雑度レベルはコード注釈を介して入力コードで指定される。入力コードに適用される複雑度レベルはグローバルベースで拡大又は縮小することもでき、一連の異なる複雑度のある実行マシンの容易な生成を可能にする。一実施形態によると、単純な線形スケーリング演算が達成されるが、非線形モードも可能である。
シーケンスに影響を受ける融合の概念は実施形態に従って多くのステップ(S34、S43、S23)で使用され、効果を提供するために重要な役割を果たす。高レベルでは、シーケンスに影響を受ける融合は、プログラムの要素が本質的に無作為に見える実行時生成データに依存できるようにする方法であり、これによりプログラム要素は、このデータがプログラム要素の実行時に正しい値を正確に有する場合にだけ、正しく実行する。論理及びデータのいくつかの部分は、プログラム要素が実際に実行されるまで知ることができないので、この技法は、静的に解決することが極めて困難な方法でこれらのプログラム要素の論理及びデータを難読化するために使用される。これが機能するためには、データ生成シーケンスは、データを使用するプログラム要素が、生成されたデータを特有の既知の値に、使用の時点でのそれらの値を明らかにすることなく、変換する補償演算で修正できるように事前に知られている。
静的分析を防止するのに効果的であるために、データ生成プロセスは、データシーケンスが攻撃者によって事前に予測できないほど十分に複雑になることができる。これは、各変異演算がデータ生成バッファに対する演算の一意のシーケンスを実行するプログラム全体で多数のデータ変異演算を注入することによって達成される。これらの演算は、データバッファの中でのビットの混合を最大化するように設計できる。
演算間のデータフローの難読化は、実演算及びデコイ演算の出力を結合することを含む。データ要素自体は、有用な中間データの抽出を防ぐためにさらに難読化され得る。中間データ難読化は、事実上ホワイトボックスの内側で生成されたあらゆるデータ要素に適用され得、実際に、理想的にはあらゆる単一データ要素に適用される。一実施形態によると、実装の中間データ要素は、そのそれぞれをそのデータ要素に一意であり、データ要素がどのようにして難読化されるのかを指定する難読化コンテキストに関連付けることによって難読化される。例えば、データ要素がデータ要素を暗号化することによって難読化される場合、難読化コンテキストはその要素のための暗号化鍵を含む。データ要素が演算により書き込まれる場合、データ要素は難読化コンテキストを使用して難読化され、データ要素が別の演算により読み取られる場合、データ要素は同じ難読化コンテキストを使用し、難読化解除される。これが、データ要素がその難読化された形式でメモリに記憶されるが、作用されているとき非難読化形式に変えられることを保証する。各データ要素が一意の難読化コンテキスト(例えば、暗号化されている場合、各データ要素は一意の暗号化鍵を有する)を使用しているため、攻撃者は中間データを全体として解釈するため、個別のデータ要素ごとに難読化を解読しなければならず、このことは概して実現可能ではない。
2.動的秘密を用いるホワイトボックス実装
動的秘密を用いるホワイトボックス実装の方法は、秘密データが動的である、つまり実行時にだけ知られるホワイトボックス実装の生成を容易にする。静的鍵はホワイトボックス解決策の基本的な要素である。ホワイトボックスを作成するプロセスは、基本的には、鍵の値を導き出すことを困難にする形式で暗号アルゴリズムのバージョンに静的鍵を埋め込むことを含む。対照的に、動的鍵はすでにホワイトボックスの中に埋め込まれる代わりにホワイトボックスに渡され、このことはホワイトボックスの本質的に静的な性質に合わない。一実施形態によると、この問題は2つの暗号アルゴリズムを結合し、結合されたアルゴリズムから単一のホワイトボックス実装を生成することによって解決できる。これを可能にするには、ホワイトボックス生成(図2)方法が任意の暗号アルゴリズムに作用することの結果であり、このことは当然、2つ以上のアルゴリズムを結合する結果を含む。
選ばれたアルゴリズムAdと動的鍵Kdを使用するために、鍵Kdは最初に適切なアルゴリズム(例えば、AES)及び対応する鍵Kaesで暗号化され、暗号化鍵Kdeを生じさせる。
簡略にするために、暗号化鍵Kdeは事前に生成され、鍵Kdは、ホワイトボックス実装が実行中である装置上には絶対に存在しないと仮定する。動的鍵Kdの暗号化バージョンKdeは回送され、動的鍵の値を明らかにすることなくホワイトボックスの外部に記憶できる。動的鍵Kdを安全に使用するために、暗号化されたバージョンKdeを解読して動的鍵Kdを回復するホワイトボックス実装が生成される。次いで、動的鍵KdはアルゴリズムAdとともに使用して、選ばれた演算を実行できる。全体的な演算はこのようになる。
ホワイトボックス実装を生成するために、アルゴリズムDecryptAES及びAdのためのソースコードは単に結合され、上記演算を実装するためにアルゴリズムを使用する上位レベル関数が作成される。アルゴリズムAdがたまたまアルゴリズムDecryptAESである場合、次いで入力コードは上位レベル関数が2回呼び出すだろう単一のアルゴリズムだけを含むことになることに留意されたい。ホワイトボックス生成方法は、次いでホワイトボックスの保護境界の中で単一のユニットとして全体的な演算を実行する単一のホワイトボックス実装を生成する。ホワイトボックスを通るデータフローの観察による鍵の導出を防ぐ同じ機構が、解読された鍵Kdのホワイトボックスからの抽出をさらに防ぐ。
上述された方法は、ホワイトボックス実装とともに動的鍵を使用するためのいくつかの考えられる手法の1つである。ただし、それらはすべて2つ以上の暗号アルゴリズムを単一のホワイトボックスの中で結合する共通の要素を共有する。単一のホワイトボックスの中で複数のアルゴリズムを結合する一般的な概念の追加の拡張は、データの内容を明らかにすることなく暗号化されたデータに対して演算を実行できるようにすることだろう。これは、以下の例に示されるように、暗号解読演算DecryptAES、データに対する演算DataOp、及び暗号化演算EncryptAEを結合することによって達成できるだろう。
攻撃者が、アプリケーション作成者によって意図されていないコンテキストでホワイトボックス実装を使用しようと試みる2つの主要な方法がある。
攻撃1:実装を隔離し、別のプログラムにコピーする。これは、有能な攻撃者が達成するには相対的に簡単である。特定の要素により、実際には若干より複雑にする可能性があり、例えば、コードはコードを実行するために特有のメモリ位置に格納される必要があるが、有能な攻撃者は係る複雑性をかなり迅速に克服する。
攻撃2:実装を含んだ全体的なプログラムをコピーし、別のプログラムから直接的に実装を呼び出す。これを行うには、いくつかの異なる方法があるが、重要な要素は、実装を使用するプログラムから実装が分離されないという点である。実際には、この攻撃は以前の攻撃よりも若干より困難であることがあるが、有能な攻撃者の能力の十分に範囲内であり、特定の場合にはより容易でさえある。
一実施形態によると、攻撃1は、ホワイトボックス実装を含んだアプリケーションに対する一貫性をチェックする改ざん対策の解決策を適用することにより防ぐことができ、これによりホワイトボックスコードは、アプリケーションの残りが予想されたメモリ位置に実際に存在することを検証する改ざん対策チェックを含む。攻撃者が次いでホワイトボックスコードだけを別のプログラムにコピーしようと試みる場合、ホワイトボックスコードの中に含まれる改ざん対策チェックは故障し、コードは実行を拒否するだろう。これを最も効果的にするためには、改ざん対策解決策はホワイトボックス実装によって提供されるコードの大部分を利用し、そのコードの中に多数の一貫性チェックを自動的に注入して、攻撃者が一貫性チェックを打ち破り、コードをアウトオブコンテキストで使用するのを可能な限り困難にする必要がある。
攻撃2を防ぐのは著しくより困難であり、そのようにする方法は、ホワイトボックス実装にとって部分的に外部である追加の機構を使用する。追加の機構は、「コンテキスト実行」と呼ばれる一貫性をチェックする改ざん対策解決策に対する拡張である。注目されるのは、この機構により使用される根本的な手法が本開示によるその使用を超えた用途を有する点である。
コンテキスト実行の背後にある核となる概念は、プログラムによるホワイトボックスの使用目的だけが正しい結果を生じさせるように、ホワイトボックス実装の内部とホワイトボックスを使用するプログラムとの間に融合を導入することである。高レベルで、プロセスは、プログラムの中に融合生成手段を注入し、ホワイトボックス実装の中に融合ターゲットを注入することを含む。融合生成手段は、プログラムを実行するにつれて融合データを生成し、融合ターゲットはホワイトボックス実装の内側で実行される演算とこのデータを結合する。
(まったく実行しないことを含む)異常なプログラム実行が演算に正しくない結果を生じさせるのに対し、融合データ及びホワイトボックス演算の結合は、プログラムの通常の実行により生じる融合データがホワイトボックス演算の結果に変更を生じさせないように構築される。基本的なプロセスは以下のステップから成り立つ。
1.融合生成手段として使用するためにアプリケーションで位置のセットを選択する、
2.融合生成手段ごとに、融合データを生じさせるコードを注入する、
3.融合ターゲットとして使用するためにホワイトボックス実装の中で演算のセットを選択する、及び
4.融合データの部分をその既存の演算と結合するために各融合ターゲットを変換する。
選択された位置は、ホワイトボックス実装への1つ又は複数のスパース実行パスに沿ってあり、これらのスパース実行パスは実装へのすべての考えられるパスの上位セットを表す。例えば、実装への10の異なるパスを有する簡略なプログラムでは、10すべてのパスで出現する3つの位置があることがある。それらの3つの位置は実装へのスパース実行パスを表し、したがってコンテキスト実行のための位置として使用できる。別の例は、それらのパスの半分がすべて同じ3つの位置を通過するが、他の半分はすべて異なる3つの位置を通過する、実装への10のパスを有する簡略なプログラムだろう。このプログラムは、3つの位置の2つのセットのための2つのスパース実行パスを有するだろう。スパース実行パスは互いに交差し、互いを「包含する」こともあり、それらの相対的なトポロジーに対する制約はない。唯一の要件は、実装へのすべての考えられるパスが、少なくとも1つのスパース実行パスによって表されることである。
各生成手段は、通常、融合データの複数部分を生じさせ、その関連付けられた記憶位置に各データ部分を記憶する。記憶位置は現在の生成手段又はその前に実行する生成手段の内の任意のうちの1つに属してよい。位置が現在の生成手段に属する場合、次いで生成手段はその位置を初期化し、データを単にその位置に書き込む。位置が以前の生成手段に属する場合、次いで現在の融合データはすでにその位置あるデータとマージされる。融合データは多くの方法で生じる。最も簡略な方法は、(静的に生じる)無作為の入力値を変換する演算の一意の生成されたシーケンスを実行し、融合データとしてそれらの演算の結果を使用することを含む。また、融合データは他の融合データの部分(例えば、以前の生成手段により生じたデータ)を結合し、アプリケーション自体により生じた選択された値を使用することによって生じさせることもできる。プログラムが複数のスパース実行パスを含む(ほぼすべての重要なプログラムに当てはまるだろう)とき、融合生成手段は、すべてのスパースパスが融合データの同じセットを生じさせるように構築される。複数のスパース実行パスが無い場合、ホワイトボックス実装は(せいぜい)1つのスパースパスから正しく動作するだけだろう。
選択ステップは、概して、総合的な暗号演算に対して大きな影響を有する演算を好む。ただし、これは多くの暗号アルゴリズムに選択クラスタを生じさせることがあるので、選択ステップは、実装を通して選択された位置を可能な限り多く分散することも好む。別の重要な選択基準は、融合変換をサポートするための演算の適切性である。すべての演算が有効なターゲットであるわけではないが、ターゲットの多くは実用的であり、実装全体で十分に分散されるため、この基準は他の基準にほとんど影響を与えない。各変換は、融合データの予期される値だけが、演算に変換前に演算が生じさせたのと同じ結果を生じさせるように構築される。他のすべての値は不正確な結果を生じさせる。
攻撃者が、融合データが使用される直前に、融合データを単にダンプし、自身の目的のためにホワイトボックスを使用する前にこのデータを再作成するのを止めるために、融合データはダンプを著しく困難にする方法で記憶される。融合データの各部分は、(スパース実行パスごとに)1つの特定の融合生成手段によって所有され、融合データを更新する必要のある他の生成手段によってアクセス可能である異なる位置を有する。いくつかの異なるタイプの位置がある。
・ほぼグローバル変数のように、メモリ内のプログラムの書込み可能セクションの中に通常位置する静的な位置、
・ヒープ割当てを通して動的に作成されるヒープ位置、及び
・スタックシフトを介して動的に作成されるスタック位置
スタック位置は、(実行パスと対照的に)ホワイトボックス実装への呼出しパス上にある融合生成手段だけによって使用できる。位置は、常に、位置ごとに一意に符号化される記憶されているポインタ値を通してアクセスされる。各生成手段は、使用するポインタ値を解読する方法を知っている。このようにして、融合データを記憶することは、攻撃者が位置データのすべてを見つけ、ダンプするのに成功することをはるかに困難にするとともに、後続の点でデータを正しく再作成することを一層困難にする。
4.アルゴリズムの小さい部分を隔離することによる攻撃の防止
アルゴリズムのホワイトボックス実装を攻撃する最も効果的な方法の1つは、なんらかの方法で秘密データ(例えば、暗号化鍵)に作用することが知られているホワイトボックスの中で、アルゴリズムの小部分を隔離し、次いで、アルゴリズムのその小部分に対して総当たり攻撃を使用して秘密を抽出することである。暗号アルゴリズムは全体的に総当たり攻撃には非実用的に設計されているにすぎないため、これは効果的である。大部分の場合、これらのアルゴリズムの個々の部分は総当たり攻撃を介した攻撃に極めて実用的である。
アルゴリズム部分を隔離するための極めて効果的な方法は、アルゴリズム実装のメモリアクセスパターンを分析することである。大部分の暗号アルゴリズムは周知の実行パターンを有しており、このパターンは、多くの場合、対応するメモリアクセスパターンに極めて正確に反映され、したがって、しばしば、メモリアクセスパターンの簡略な視覚化でさえも使用することができ、総当たり攻撃を容易にするのに十分な精度でアルゴリズム部分を隔離する。
例えば、AESブロック暗号アルゴリズムは、演算の同じシーケンスの10ラウンド、12ラウンド、及び14ラウンドを実行する。これは、視覚化時に位置を見つけるが容易である関連するメモリアクセスの10/12/14ブロックの対応するシーケンスとして現れる。攻撃者はこれを使用して最後の2ラウンドを隔離し、次いで既知の方法を使用して、これらのラウンドの入力及び出力を観察することによってAES鍵を導き出すことができる。
一実施形態によると、このタイプの攻撃は、攻撃者が暗号演算の個々の部分を隔離するために依存する可能性があるアクセスパターンを排除することによって一層困難になる。メモリアクセスパターンの排除は、アルゴリズムのホワイトボックス実装を通して追加の無作為化されたメモリアクセス演算を注入することによって達成され得る。これらの演算は、実演算によってアクセスされるメモリ位置の同じセットにアクセスするが、無作為化された順序、及び実演算により示されるあらゆるパターンを隠すほど十分なノイズを追加する分散をもってアクセスする。
一実施形態によると、メモリアクセスパターンの難読化は上述されたデコイ生成への拡張として実装される。この拡張は、より多数のデコイを生成することから成り、追加のデコイはメモリアクセス演算のコピーとして作成される。また、これらの追加のデコイは不明瞭な式を通して演算と結合できるが、実際には、性能に対する影響を削減するために、追加のデコイの大きい部分は結合されない場合がある。
一実施形態によると、メモリレイアウトの難読化は、アルゴリズムの小部分を隔離することによって攻撃に対する追加の保護を提供するために、メモリアクセスパターンの難読化に沿って実行される。ノイズを導入することにより、アクセスパターンを難読化しようとするメモリアクセスパターンの難読化とは異なり、メモリレイアウト難読化は、メモリ内のデータフラグメントの位置を無作為化することによってその目標を達成する。
レイアウト難読化がないと、データにアクセスする演算が行うように、関連するデータ部分は通常互いに沿って存在し、これにより視覚化時に識別できるアクセスパターンを生じさせる。メモリアクセスパターンの難読化は、導入されたノイズを通してこれらのパターンを観察するのを困難にするが、該パターンは依然としてそこにある。実演算によりメモリでアクセスされたデータフラグメントの位置を無作為化することによって、関係するデータ部分は互いから分離され、実演算によって示されるあらゆるパターンを壊す。
本発明は、例示的な一実施形態に関して説明されてきた。特定の変更形態が本発明の範囲から逸脱することなく上記構成で行われてよいが、上記説明に含まれる又は添付図面に示されるすべての事項が制限的な意味ではなく、例示的として解釈されることが意図される。
本発明は特に暗号アルゴリズム又は秘密データを操作するアルゴリズムに適用しないが、本発明は任意のアルゴリズムに適用できる。
以下の特許請求の範囲は、本明細書に説明される本発明のすべての包括的及び特定の特徴、及び言語の問題としてそれらの間にあると言われてもよい、本発明の範囲のすべての記述を包含することも理解されるはずである。