(57)【要約】【課題】高級言語でのプログラミングにおいて、耐タンパ性の高いセキュアなコードを生成するための外部仕様をサポートし、ユーザの指示があった部分については、耐タンパ性を持つ実行可能プログラムを自動的に生成するプログラム作成方法を提供する。【解決手段】構文解析ステップと、中間語生成ステップと、レジスタ割り付けステップと、最適化処理ステップと、アセンブリ言語生成ステップと、機械語生成ステップと、機械語プログラム結合ステップとを実行し、ソースプログラム１０６を読み込んでから実行可能プログラム１０７を生成するまでの間で、ユーザの指示に基づいて、ソースプログラム１０６もしくは中間語１０９もしくはアセンブリ言語プログラム２０６もしくは機械語プログラム２０７に対して、実行可能プログラム１０７の動作内容の不正な解析に対抗する耐タンパ性を有するコードを自動的に生成する耐タンパコード挿入ステップを実行する。【選択図】図２
2009009537.tif 000002
【特許請求の範囲】
【請求項１】
コンピュータにより、プログラミング言語で記述されたソースプログラムを読み込んで実行可能プログラムを生成するプログラム作成方法であって、
前記コンピュータは、前記ソースプログラムを読み込んで構文解析を行う構文解析ステップと、該ソースプログラムから中間語の生成を行う中間語生成ステップと、該中間語に対してレジスタを割り付けるレジスタ割り付けステップと、該中間語に対して最適化処理を行う最適化処理ステップと、該中間語からアセンブリ言語プログラムを生成するアセンブリ言語生成ステップと、該アセンブリ言語プログラムから機械語プログラムを生成する機械語生成ステップと、該機械語プログラムと他の機械語プログラムとを結合させて実行可能プログラムを生成する機械語プログラム結合ステップとを実行し、
前記ソースプログラムを読み込んでから前記実行可能プログラムを生成するまでの間で、ユーザの指示に基づいて、前記ソースプログラムもしくは前記中間語もしくは前記アセンブリ言語プログラムもしくは前記機械語プログラムに対して、前記実行可能プログラムの動作内容の不正な解析に対抗する耐タンパ性を有するコードを自動的に生成する耐タンパコード挿入ステップを実行することを特徴とするプログラム作成方法。
【請求項２】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中の多重条件分岐処理に対して、各条件分岐の判定処理を正しく通過してきたかどうかをチェックするための情報をレジスタ又はメモリ上に保持し、各条件分岐先の処理内で前記情報が妥当な値であるかどうかをチェックすることにより、前記実行可能プログラムの実行時の誤動作を検出または防止することを可能とするコードであることを特徴とするプログラム作成方法。
【請求項３】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中の条件分岐処理に対して、該条件分岐での判定処理を二重もしくはそれ以上に多重化することにより、前記実行可能プログラムの実行時の誤動作を検出または防止することを可能とするコードであることを特徴とするプログラム作成方法。
【請求項４】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中の関数呼び出し処理に対して、関数呼び出し側では、呼び出し先の関数へ渡す引数から予め定められた手順により計算されるチェック用の値をレジスタ又はメモリ上に設定しておき、呼び出された関数側では、渡された引数から予め定められた手順により計算される値と、前記チェック用の値とを比較して引数の妥当性をチェックすることにより、前記実行可能プログラムの実行時の誤動作を検出または防止することを可能とするコードであることを特徴とするプログラム作成方法。
【請求項５】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中のループ処理に対して、同一の処理内容である複数パターンの命令列を生成することにより、前記実行可能プログラムの実行時の電流特性の特徴を希薄化するコードであることを特徴とするプログラム作成方法。
【請求項６】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中の条件分岐処理に対して、各条件分岐経路の実行時間を均一化する命令列を生成することにより、前記実行可能プログラムの実行時の電流特性の特徴を希薄化するコードであることを特徴とするプログラム作成方法。
【請求項７】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップで生成する耐タンパ性を有するコードは、前記ソースプログラム中のユーザにより指示された処理範囲に対して、該処理範囲の命令コードを積算したチェックサムの期待値を算出し、チェックサムによる検証を行うためのハードウェアの設定、命令コードの積算の開始・終了およびチェックサムによる検証の実行をハードウェアに指示する命令列を生成することにより、前記実行可能プログラムの実行時の誤動作を検出または防止することを可能とするコードであることを特徴とするプログラム作成方法。
【請求項８】
請求項１記載のプログラム作成方法において、
前記耐タンパコード挿入ステップでは、プログラム動作誤り検出のためのコードとして、前記ソースプログラム中の予め指定された第１命令の二重化にかかる第２命令のコードと、前記第１命令の実行結果と、前記第２命令の実行結果とを比較するための比較処理のコードと、前記比較処理の結果が不一致とされた場合に所定のエラー処理を行うためのコードとを生成することを特徴とするプログラム作成方法。
【請求項９】
請求項８記載のプログラム作成方法において、
前記耐タンパコード挿入ステップでは、さらに、前記第１命令の実行で用いられる変数と該変数の他処理との関連を依存解析するためのコードと、前記依存解析の結果に基づいて、前記第２命令の実行に必要とされる変数を含む情報の複製を得るためのコードと、前記変数を含む情報の複製を用いて前記第２命令を実行するコードとを生成することを特徴とするプログラム作成方法。
【請求項１０】
請求項９記載のプログラム作成方法において、
ユーザにより前記依存解析の深さの指定が可能であることを特徴とするプログラム作成方法。
【請求項１１】
プログラミング言語で記述されたソースプログラムを実行可能プログラムに変換する第１処理と、前記ソースプログラムを前記実行可能プログラムに変換する前に、プログラム動作誤り検出のための機能を追加する第２処理と、を実行可能なＣＰＵを含む情報処理装置であって、
前記第２処理では、前記ソースプログラム中の予め指定された第１命令の二重化にかかる第２命令のコードと、前記第１命令の実行結果と、前記第２命令の実行結果とを比較するための比較処理のコードと、前記比較処理の結果が不一致とされた場合に所定のエラー処理を行うためのコードとを生成することを特徴とする情報処理装置。
【請求項１２】
請求項１１記載の情報処理装置において、
前記第２処理では、さらに、前記第１命令の実行で用いられる変数と、該変数の他処理との関連を依存解析するためのコードと、前記依存解析の結果に基づいて、前記第２命令の実行に必要とされる変数を含む情報の複製を得るためのコードと、前記変数を含む情報の複製を用いて前記第２命令を実行するコードとを生成することを特徴とする情報処理装置。
【請求項１３】
請求項１２記載の情報処理装置において、
ユーザにより前記依存解析の深さの指定が可能であることを特徴とする情報処理装置。
【請求項１４】
プログラムを解釈して実行可能な命令解釈実行装置を有するマイコンであって、
前記プログラムに含まれる所定命令について前記命令解釈実行装置で複数回実行された結果が書き込まれる二重化データ用記憶装置と、前記二重化データ用記憶装置内のデータに基づいて、前記命令解釈実行装置で複数回実行された結果の比較を行い、その比較結果が不一致とされた場合に、前記命令解釈実行装置の動作を停止させるための信号を生成する演算器とを有することを特徴とするマイコン。
【請求項１５】
請求項１４記載のマイコンにおいて、
前記プログラムに含まれる所定命令について前記命令解釈実行装置で複数回実行されるときに用いられる変数は、前記所定命令が前記命令解釈実行装置で実行される前に複製されることを特徴とするマイコン。
【請求項１６】
実行可能プログラムおよび暗号鍵データや機密情報が格納されたメモリと、前記実行可能プログラムを解釈して実行可能なＣＰＵと、外部との入出力を制御する入出力部と、これらを接続するバスとを有し、
前記メモリに格納されている前記機密情報を不正に参照・書き換えされないように、前記暗号鍵データを用いた暗復号処理によって前記機密情報のやり取りを行うマイコンであって、
前記メモリに格納された前記実行可能プログラムは、請求項１記載のプログラム作成方法により生成された実行可能プログラムであることを特徴とするマイコン。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ＩＣカード等に実装されるセキュリティ用途向けマイコンに搭載されるプログラムの作成方法に関し、特に電磁波や放射線、過電圧その他の手段により誤動作又は不正なレジスタ値もしくはメモリ値の改変を起こし、不正な動作を生じさせることによりデータの破壊や機密情報の推定を行う攻撃（誤動作解析アタック）をはじめとする動作内容の不正な推定・解析に対抗する手段を持つ、すなわち耐タンパ性を持つプログラムの作成方法、および当該プログラムを作成する情報処理装置、ならびに当該プログラムを搭載するセキュリティ用途向けマイコンに適用して有効な技術に関するものである。
【背景技術】
【０００２】
ＩＣカードは、プラスチック製カードに半導体集積回路チップを埋め込み、プログラムや機密データを密閉したカード形態の情報処理装置である。ＩＣカードに対しては、リーダライタからのコマンドに応じてデータの転送や書き込みを行うが、取り扱うデータは、個人情報や電子マネーなど、機密性が高い情報であることが多い。そのため、第三者に対して機密情報の不正な参照を許さないために、内部の情報を勝手に書き換えることを禁止したり、暗号鍵を用いたデータの暗復号処理によって情報のやり取りを行ったり等の機能を備えている。
【０００３】
このような用途を持つため、ＩＣカード用途向けマイコンにとって、内部の機密情報を不正に読み取ったり、動作内容を解析したりすることに対する耐性（耐タンパ性）は、性能指標として重要なポイントである。この耐タンパ性は、デバイスの改善だけでなく、実装するソフトウェアに対する工夫によって向上させることも可能である。
【０００４】
機密情報を取り扱うＩＣカードでは、リーダライタとの間で受け渡しするデータは暗号化されている。よって、従来は、ＩＣカード内の機密情報を解析する難易度は、暗号化アルゴリズムを解析する難易度と同じであるというように考えられてきた。しかし、ＩＣカードの動作時の消費電流を観測することにより、ソフトウェアの動作内容が推定・解析されてしまう危険性が指摘されてきている。これは、言い換えれば「暗号化処理の実際の処理内容が解析される」危険性を示唆しているのと同じであり、「暗号化アルゴリズムが解析される」よりも容易に実現可能であるものと考えられる。
【０００５】
また、ＩＣカード用途向けマイコンの動作を不正に解析する際、異常電圧・異常クロックや熱、光の照射等のストレスをマイコンに与えることにより、ＲＡＭやレジスタの内容を不正な状態にし、プログラムの命令コードを不正に変化させ、強引に本来のプログラムフローとは異なる不正経路の動作を生じさせることにより、ソフトウェアの動作内容を推定・解析する手法（誤動作解析アタック）がある。
【０００６】
さらに、この誤動作解析アタックにより、チップに計算誤りを起こさせ、正しい計算結果と誤った計算結果の差分を用いて暗号鍵情報を推定するアタック手法も開発されている。このアタック手法の特徴は、アタックに必要な時間が非常に少ない点である。例えば、ＣＲＴ演算法を用いたＲＳＡ暗号に対する誤動作解析アタック手法では、鍵長にかかわらず、たった１回の演算誤りが得られれば、正しい値と誤った値の差分と公開鍵のモジュロＮとの最大公約数から、秘密素数が得られ、その結果から秘密鍵を推定できることが知られている。
【０００７】
秘密鍵暗号系として広く用いられているＤＥＳ暗号では、正しい演算結果と誤った演算結果が数個から数十個得られると、秘密鍵を得ることができることがE.Bihamらによって報告されている。ＤＥＳ暗号の後継暗号として提案されたＡＥＳ暗号でも途中の演算のうちの１バイトに誤計算を起こさせることができれば、２回の誤計算結果から鍵を得ることができる手法がJ.J.Quisquaterらによって提案されている。これらのアタックは、アタックに必要な計算量が暗号鍵の長さにかかわらず一定か、もしくは暗号鍵のビット長のみに比例し、かつ計算量は非常に小さいという特徴がある。
【０００８】
暗号鍵を推定する誤動作解析アタック対策としては、暗号に応じて（１）処理を二重化することにより２回計算を行い、２回の演算結果が等しくなることを確認する方法、（２）逆計算による検算を行う方法、（３）剰余体上での縮退表現や、パリティを用いた演算の整合性のチェックなどが提案されている。
【０００９】
このような不正な動作解析手法に対抗するため、ソフトウェアに対する工夫によって耐タンパ性を向上させようとした場合、従来のソフトウェア開発ツールでは、特開２００２−３３４３１７号公報（特許文献１）に提示されているように、ユーザ自身が手作業により耐タンパ性を向上させるセキュアなプログラムを記述する必要があった。しかし、ユーザがプログラムで記述できる部分は限定的であり、また、開発ツールが生成する機械語を完全にコントロールすることも難しいため、実際にセキュアなプログラムを手作業により作成することは難しい。
【００１０】
一方、コンパイラやソフトウェア実装方式の工夫、特にプログラム中で用いるデータ領域の工夫をすることで攻撃者からの攻撃を回避する方法としては、特開２００１−２０２２３７号公報（特許文献２）に提示されているように、実行可能なバイナリデータ中にダミーデータの埋め込み場所を設定する方法や、特開２００３−３３０５６３号公報（特許文献３）に提示されているように、スタック構造をプログラム毎に変更することでプログラム破壊攻撃に対する耐性を向上する方法といった技術が提案されている。
【００１１】
なお、以下では、ユーザが記述したソースプログラムを入力として、機械語で記述された最終的な実行可能プログラムを生成する開発ツール全般（コンパイラやリンケージエディタなどを含む）を言語ツールと呼称する。
【特許文献１】特開２００２−３３４３１７号公報
【特許文献２】特開２００１−２０２２３７号公報
【特許文献３】特開２００３−３３０５６３号公報
【発明の開示】
【発明が解決しようとする課題】
【００１２】
前述した通り、ユーザが耐タンパ性を持つプログラムを作成することは難しい。その理由は、昨今ではプログラムがＣ言語などの高級言語で開発されることが多く、アセンブリ言語のソースプログラムをユーザが直接作成するというのが現実的ではないことなどが挙げられる。また、耐タンパ性を持つプログラムを手作業で開発すること自体、通常のソフトウェア開発と比較して多くの工数を必要とすることも挙げられる。
【００１３】
仮にＣ言語のような高級言語で耐タンパ性を持つソースプログラムを記述したとしても、動作内容を変えずに実行性能を上げたり、実行可能プログラムのサイズを削減したりする言語ツールの最適化処理において、前記記述が冗長な命令として削除される可能性がある。あるいは、耐タンパ性を高めるのに直接関係無い冗長な命令まで生成される可能性がある。高級言語による記述では、実際の命令列まで細かく制御するのは一般に困難である。また、仮にユーザが耐タンパ性を持つプログラムを作成したとしても、その効果を検証するには実際に不正な動作解析による攻撃を行ってみる必要があり、実現は難しい。
【００１４】
また、ユーザがどのように耐タンパ性を持つプログラムを作成すればよいのかについて必ずしも精通していない点も挙げられる。耐タンパ性を持つプログラムを作成するには、耐タンパ性を向上させるための種々のプログラミング技法に加えて、対象マシンの機械語命令の仕様や特性を知らなければならないが、高級言語でプログラミングしている場合、これは一般的には望めないことである。
【００１５】
そこで本発明の目的は、Ｃ言語などの高級言語でのプログラミングにおいて、耐タンパ性の高いセキュアなコードを生成するための外部仕様（オプションもしくは拡張言語仕様など）を言語ツールでサポートし、ソースプログラムの中で前記インタフェースによりユーザの指示があった部分については、耐タンパ性を持つセキュアな実行可能プログラムを自動的に生成するプログラム作成方法を提供することにある。
【００１６】
本発明の前記ならびにその他の目的と新規な特徴は、本明細書の記述および添付図面から明らかになるであろう。
【課題を解決するための手段】
【００１７】
本願において開示される発明のうち、代表的なものの概要を簡単に説明すれば、次のとおりである。
【００１８】
本発明は、コンピュータにより、プログラミング言語で記述されたソースプログラムを読み込んで実行可能プログラムを生成するプログラム作成方法であって、前記コンピュータは、前記ソースプログラムを読み込んで構文解析を行う構文解析ステップと、該ソースプログラムから中間語の生成を行う中間語生成ステップと、該中間語に対してレジスタを割り付けるレジスタ割り付けステップと、該中間語に対して最適化処理を行う最適化処理ステップと、該中間語からアセンブリ言語プログラムを生成するアセンブリ言語生成ステップと、該アセンブリ言語プログラムから機械語プログラムを生成する機械語生成ステップと、該機械語プログラムと他の機械語プログラムとを結合させて実行可能プログラムを生成する機械語プログラム結合ステップとを実行し、前記ソースプログラムを読み込んでから前記実行可能プログラムを生成するまでの間で、ユーザの指示に基づいて、前記ソースプログラムもしくは前記中間語もしくは前記アセンブリ言語プログラムもしくは前記機械語プログラムに対して、前記実行可能プログラムの動作内容の不正な解析に対抗する耐タンパ性を有するコードを自動的に生成する耐タンパコード挿入ステップを実行することを特徴とするものである。
【００１９】
また、本発明は、前記プログラム作成方法を実行する情報処理装置および前記プログラム作成方法により生成された実行可能プログラムを格納するマイコンにも適用することができる。
【発明の効果】
【００２０】
本願において開示される発明のうち、代表的なものによって得られる効果を簡単に説明すれば以下のとおりである。
【００２１】
本発明によれば、ユーザが手作業で作るのが難しい耐タンパ性を持つセキュアな実行可能プログラムを、言語ツールで自動的に生成することができる。これによりセキュアなプログラムの開発生産性が向上する。
【発明を実施するための最良の形態】
【００２２】
以下、本発明の実施の形態を図面に基づいて詳細に説明する。なお、実施の形態を説明するための全図において、同一部には原則として同一の符号を付し、その繰り返しの説明は省略する。
【００２３】
＜概要＞
以下、本発明の実施の形態である言語ツールについて説明する。本実施の形態での言語ツールは、耐タンパ性を有する機械語を生成するための外部仕様（拡張言語仕様もしくはオプションなど）を有し、容易に耐タンパ性を有するプログラムを生成することが出来るインタフェースを提供する。
【００２４】
本実施の形態での言語ツールは、ソースプログラムにおいて前記インタフェースによってユーザにより指示された部分に対して、その動作内容を変えずに耐タンパ性を向上させる機械語を生成するための耐タンパコード挿入ステップを実行する。この耐タンパコード挿入ステップにて生成される、耐タンパ性を向上させるコードは以下の６種類である。
【００２５】
（１）多重条件分岐の分岐経路検証
誤動作解析アタックにより、条件分岐用の情報レジスタの内容などが不正になる場合、不正な経路の実行となる危険がある。条件分岐がネストしているような多重条件分岐の場合、各条件分岐での判定処理を正しく通過したかどうかをチェックするための情報をレジスタやメモリ上に保持し、各条件分岐先の処理のブロック内で前記情報が妥当な値かどうかをチェックすることで不正な分岐経路の実行を防ぐ。
【００２６】
（２）条件分岐判定の多重化
誤動作解析アタックにより、条件分岐用の情報レジスタの内容などが不正になる場合、不正な経路の実行となる危険がある。よって、条件分岐での判定処理を単一ではなく、二重三重に実施することにより、正常な経路への分岐をより確実に行い、不正な分岐経路実行の危険を抑える。
【００２７】
（３）関数呼び出し時のパラメータ内容チェック
誤動作解析アタックにより、ＲＡＭ（実行時スタック）が不正な状態となった場合、関数呼び出しのパラメータ（引数）が不正になり、不正な動作を生じさせる危険がある。よって、関数呼び出し時に、呼び出し側でパラメータの合計値（チェックサム）等をメモリ又はレジスタ上に設定し、呼び出された側では受け取ったパラメータの合計値を計算し、呼び出し側で設定した合計値と比較して関数呼び出し間のパラメータの妥当性チェックを行うことにより、不正な関数の実行を防ぐ。
【００２８】
（４）実行時の電流特性希薄化
プログラムの動作内容を変えずに、実行時の電流特性の特徴を薄めるような機械語を生成する。これにより、本実施の形態での言語ツールによって生成されたプログラムの動作内容を消費電流から解析することは困難となり、ＩＣカード等に保持する機密情報を知られる危険性を抑えることができる。実行時の電流特性の特徴を薄める手法としては、（ａ）ループ処理についての複数パターンのコード生成による電流特性複雑化、（ｂ）条件分岐の各分岐経路の実行時間を均一化することによる電流特性近似化、の２通りがある。
【００２９】
（５）チェックサム算出および検証
命令コードを積算したチェックサムの期待値を算出し、実行時の命令コードの積算値と比較することでプログラムフローの正常実行を監視することを可能とする機械語を生成する。これにより、本実施の形態での言語ツールによって生成されたプログラムを、不正な動作を起こさせる誤動作解析アタックにより解析することは困難となり、ＩＣカード等に保持する機密情報を知られる危険性を抑えることができる。
【００３０】
（６）プログラムコードの二重化処理
誤動作解析アタック対策として、二重化処理を用いることでプログラムの動作誤りを検出する方法で、特にプログラムの動作系を二重化するハードウェアの構成を用いず、既存の単一処理系を前提としたハードウェア上で実現する方法として、プログラムコードを二重化することにより２回演算を行い、２回の演算結果が等しくなることを確認することにより、プログラムの動作誤りを検出する。
【００３１】
以下、これら６種類の手法を適用した言語ツールの例について説明する。
【００３２】
＜実施の形態１＞
以下、本発明の実施の形態１として、多重条件分岐の分岐経路検証を行う実行可能プログラムを生成する言語ツールの例について説明する。
【００３３】
図１は、本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図である。図１に示すように、情報処理装置はＣＰＵ１０１、ディスプレイ１０２、入出力デバイス１０３、主記憶装置１０４、及び外部記憶装置１０５より構成されている。主記憶装置１０４には、本実施の形態での言語ツール１０８と、言語ツール１０８によるコンパイル処理過程で生成される中間語１０９とが保持される。外部記憶装置１０５には、言語ツール１０８への入力となるソースプログラム１０６と、言語ツール１０８により生成される実行可能プログラム１０７とが保持される。コンパイル処理はＣＰＵ１０１が言語ツール１０８を実行することにより行われる。ディスプレイ１０２はコンパイル処理状況等を表示することによりユーザに通知する。入出力デバイス１０３はユーザからのコマンドを言語ツール１０８に与えるために用いる。
【００３４】
以下に、本実施の形態での言語ツールの具体的な内容について説明する。図２は、本実施の形態での言語ツールの構成と処理概要の例を表した図である。図２において、言語ツール１０８はコンパイラ２０１、アセンブラ２０４、リンケージエディタ２０５から構成され、コンパイラ２０１はフロントエンド２０２とバックエンド２０３とに分けられる。
【００３５】
言語ツール１０８は図１に示す情報処理装置上で稼動し、まずコンパイラ２０１がＣ言語などの高級言語で記述されたソースプログラム１０６を読み込む。コンパイラ２０１は、読み込んだソースプログラム１０６に対して、フロントエンド２０２によって構文解析、字句解析、意味解析の処理を行い、中間語１０９を生成する。中間語１０９は、コンパイル処理過程で必要となるコンパイラ内部データである。
【００３６】
次に、コンパイラ２０１は、バックエンド２０３によって、耐タンパコード挿入処理を行い、中間語１０９に対して耐タンパ性を向上させるセキュアな命令列を追加・生成する。その後、中間語１０９を基にレジスタ割り付け処理、最適化処理を行って、アセンブリ言語プログラム２０６を生成する。これにより、耐タンパ性を向上させるセキュアな命令列を含んだ形でアセンブリ言語プログラム２０６が生成される。
【００３７】
その後、コンパイラ２０１によって生成されたアセンブリ言語プログラム２０６をアセンブラ２０４が読み込み、機械語プログラム２０７を生成する。その後、リンケージエディタ２０５が機械語プログラム２０７に対して他の機械語プログラムを結合（リンク）することによって、実行可能プログラム１０７が生成される。言語ツール１０８によってこのように作成された実行可能プログラム１０７は、ＩＣカードなどのターゲットマイコン２０８に格納され実行される。
【００３８】
なお、耐タンパコード挿入処理は、本実施の形態での言語ツール１０８では中間語生成処理の後に中間語１０９に対して行っているが、中間語１０９に対して行う場合は、アセンブリ言語生成処理の前で行われればよく、最適化処理の後に行うことも可能である。また、中間語１０９に対してではなくアセンブリ言語プログラム２０６や、機械語プログラム２０７に対してアセンブラ２０４やリンケージエディタ２０５が耐タンパコード挿入処理を行うことも可能である。さらに、可能な場合には、図示しないプリプロセッサ等によりソースプログラム１０６に対して耐タンパコード挿入処理を行い、その後コンパイラ２０１による処理を行うようにすることもできる。
【００３９】
図３は、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図である。ターゲットマイコン２０８は、特に制限されないが、公知の半導体集積回路製造技術により、単結晶シリコン基板などの一つの半導体基板に形成される主にＩＣカード用途向けマイコンであり、不揮発性メモリ３０１、揮発性メモリ３０４、入出力部３０５、コプロセッサ３０６、ＣＰＵ３０７、暗号専用回路３０８、およびこれらを接続するバス３０９により構成される。
【００４０】
不揮発性メモリ３０１は、特に制限されないが、フラッシュメモリなどで構成され、不揮発性メモリ３０１内のプログラム格納領域３０２には、言語ツール１０８が生成した実行可能プログラム１０７が格納される。この実行可能プログラム１０７は、ＣＰＵ３０７によって実行される。また、データ格納領域３０３には、暗号鍵データや機密情報などのデータが格納される。
【００４１】
揮発性メモリ３０４は、ＣＰＵ３０７での演算処理における変数記憶領域や、中間データの格納領域として利用される。暗号専用回路３０８では、ターゲットマイコン２０８が搭載されたＩＣカード３１０の不正使用を回避するための暗号処理が行われる。
【００４２】
ここで、例えばプログラム格納領域３０２には、耐タンパコード挿入処理によって追加・生成されたセキュアな命令列を含んだ実行可能プログラム１０７以外にも、必要であれば耐タンパコード挿入処理を無効にすることにより生成された、セキュアな命令列が含まれない第２の実行可能プログラム１０７が格納されていてもよい。
【００４３】
この耐タンパコード挿入処理の有効・無効については、ソースプログラム１０６を言語ツール１０８に読み込む際に、任意のレジスタに設定することによってその制御を行うことが可能である。これによって、耐タンパ性が必要とされるプログラムに対しては耐タンパコード挿入処理を行うことで耐タンパ性を高め、それ以外のプログラムに対しては、プログラム容量を抑えた実行可能プログラム１０７を生成することができ、不要なプログラム容量の増大を抑制することが可能となる。
【００４４】
また、実行可能プログラム１０７を、外部端子３１１を介してＩＣカード３１０の外部から揮発性メモリ３０４にロードし、ＣＰＵ３０７により実行する構成とすることも可能である。揮発性メモリ３０４は、ダイナミック・ランダム・アクセス・メモリ（ＤＲＡＭ）や、スタティク・ランダム・アクセス・メモリ（ＳＲＡＭ）とすることができる。かかる構成においても、前述した実行可能プログラム１０７を不揮発性メモリ３０１に格納する構成の場合と同様の作用効果を得ることができる。
【００４５】
図４は、本実施の形態でのコンパイラ２０１での処理の流れの例を示したフローチャートである。まずステップ４０１で、フロントエンド２０２にてソースプログラム１０６を読み込んで構文解析を行う。構文解析処理については、例えば「エイホ、セシィ、ウルマン著：コンパイラＩ（サイエンス社、１９９０年）３０頁〜７４頁」などに記載されているので、ここでは詳しく説明しない。次に、ステップ４０２でフロントエンド２０２にて中間語生成を行う。中間語については同じく「エイホ、セシィ、ウルマン著：コンパイラＩＩ（サイエンス社、１９９０年）５６４頁〜６１７頁」などに記載されているので、ここでは詳しく説明しない。
【００４６】
次に、ステップ４０３で未処理の関数があるかどうかを調べる。Ｃ言語では入力ソースプログラムは関数という処理単位に分かれているので、本実施の形態での言語ツール１０８では関数ごとに翻訳処理を行うものとする。未処理の関数がなければここで終了する。未処理の関数があれば、ステップ４０４で未処理の関数を取り出し、該関数が耐タンパコード挿入対象の関数かどうかを調べる。耐タンパコード挿入対象の関数かどうかは、例えば中間語１０９内の各入力関数に対して作られるテーブルに情報（ON/OFF）を記録しておき、該情報を参照することによって行う。該情報はステップ４０１の構文解析時に、ソースプログラム１０６中で後述する言語仕様拡張により耐タンパコード挿入の指示がされた関数に対して設定されるものとする。
【００４７】
前記関数が耐タンパコード挿入対象である場合はステップ４０５へ進み、バックエンド２０３にて中間語１０９に対して耐タンパコード挿入の処理を行った後ステップ４０６へ進む。ステップ４０５の耐タンパコード挿入処理の詳細については後述する。耐タンパコード挿入対象の関数ではない場合はステップ４０６へ進む。なお、前述のように、ステップ４０５の耐タンパコード挿入処理は、ステップ４０７の最適化処理の後で行うことも可能である。
【００４８】
ステップ４０６では、バックエンド２０３にて中間語１０９に対してレジスタ割り付けを行う。レジスタ割り付け処理については同じく「エイホ、セシィ、ウルマン著：コンパイラＩＩ（サイエンス社、１９９０年）６５９頁〜６６５頁」などに記載されているので、ここでは詳しく説明しない。次にステップ４０７へ進み、バックエンド２０３にて中間語１０９に対して最適化処理を行う。最適化処理については同じく「エイホ、セシィ、ウルマン著：コンパイラＩＩ（サイエンス社、１９９０年）７１５頁〜８８１頁」などに記載されているので、ここでは詳しく説明しない。
【００４９】
次にステップ４０８へ進み、バックエンド２０３にて中間語１０９からアセンブリ言語の生成を行い、アセンブリ言語プログラム２０６を出力する。アセンブリ言語生成処理については同じく「エイホ、セシィ、ウルマン著：コンパイラＩＩ（サイエンス社、１９９０年）６７９頁〜６９２頁」などに記載されているので、ここでは詳しく説明しない。
【００５０】
図５は、本実施の形態でのコンパイラ２０１への入力となる、ソースプログラム１０６の例である。本実施の形態ではソースプログラム１０６はＣ言語で記述されたものを対象としており、耐タンパコード挿入対象を指定するための言語仕様拡張がされている。行５０１に示す「#pragma secure_func(f,g)」がそれであり、行５０２の関数fと行５１２の関数gに対して耐タンパコードを挿入することを指示している。指示がされていない行５１６の関数hに対しては通常のコード生成を行う。行５０２の関数fは、行５０４の条件式cond1の値が真の場合は行５０５の実行文１を実行し、偽の場合は、行５０６の条件式cond2の値が真の場合は行５０７の実行文２を、偽の場合は行５０９の実行文３を実行することを示している。
【００５１】
図６は、本実施の形態でのコンパイラ２０１により生成される、ステップ４０５での耐タンパコード挿入処理を行う前の、中間語１０９の例を示したものである。コンパイラが生成する中間語には、一般にソースプログラムに近いレベルのものから、機械語に近いレベルのものまで存在するが、本実施の形態では機械語に近いレベルのものを想定している。中間語１０９は命令と呼ばれるメモリセルを２重リンクでリスト状に繋げる形で構成しており、図中の実線の矢印は命令間のリンクを表している。
【００５２】
図６に示す中間語１０９は、図５のソースプログラム１０６の行５０４〜行５１０の部分に相当するものである。命令６０１（cmp）は、定数0（偽）と変数cond1とを比較（compare）することを示す。命令６０２（beq）は、前記比較の結果、0とcond1が等しい（Equal）場合に、オペランドのポインタで指される（リンクされる）命令６０５へ分岐することを示す。そうではない（等しくない）場合は、直後の命令６０３に制御を移す（fall-through）。命令６０３は、図５のソースプログラム１０６における行５０５の実行文１に対応する文である。ここでは１つの命令で表されているが、複数の命令から構成されている場合もある。命令６０４（bra）は、オペランドのポインタで指される命令６１０へ無条件分岐することを示す。
【００５３】
命令６０５（cmp）は、定数0（偽）と変数cond2とを比較（compare）することを示す。命令６０６（beq）は、前記比較の結果、0とcond2が等しい（Equal）場合に、オペランドのポインタで指される（リンクされる）命令６０９へ分岐することを示す。そうではない（等しくない）場合は、直後の命令６０７に制御を移す（fall-through）。命令６０７は図５のソースプログラム１０６における行５０７の実行文２に対応する文である。ここでは１つの命令で表されているが、複数の命令から構成されている場合もある。命令６０８（bra）は、オペランドのポインタで指される命令６１０へ無条件分岐することを示す。
【００５４】
命令６０９は、図５のソースプログラム１０６における行５０９の実行文３に対応する文である。ここでは１つの命令で表されているが、複数の命令から構成されている場合もある。命令６１０は、図５のソースプログラム１０６におけるif...else if...else 節終了後に後続で実行される命令である。
【００５５】
図７は、本実施の形態での、図４のステップ４０５での耐タンパコード挿入処理の詳細な例を表すフローチャートである。まずステップ７０１で、中間語１０９内の全命令の処理済フラグをOFFにする。次にステップ７０２において、中間語１０９内の最初の命令を取り出し、それをtとする。次にステップ７０３で、tがNULLかどうかを調べる。NULLであれば命令がすべて処理済みなので終了する。NULLでなければステップ７０４へ進み、tが条件分岐命令かどうかを調べる。条件分岐命令でなければステップ７０８へ進み、tの次の命令を新たにtとし、ステップ７０３から繰り返す。ステップ７０４でtが条件分岐命令であれば、ステップ７０５でtの処理済フラグがONかどうかを調べる。ONであればステップ７０８へ進み、ONでなければステップ７０６へ進む。
【００５６】
ステップ７０６では、tが多重条件分岐の開始命令かどうかを調べる。tが多重条件分岐の開始命令であるか否かは、（１）tの直前の命令が比較命令であること、（２）tの分岐先命令から始まる、合流や分岐のない命令列（基本ブロック）の末尾が、比較命令とその直後の条件分岐命令であること、の２つを判断することによっておこなう。分岐先にさらに比較命令、条件分岐命令のパターンが連続している場合は、連続している限り同じ多重条件分岐に属するとみなす。前記判断により、tが多重条件分岐の開始命令でなければ、ステップ７０８へ進む。tが多重条件分岐の開始命令であれば、ステップ７０７へ進む。
【００５７】
ステップ７０７では、以下の（１）〜（５）の処理を行う。
（１）多重条件分岐の各比較命令をそれぞれc_0、c_1、...、c_nとする。
（２）c_0の直前に経路情報の初期化命令を挿入する。
（３）c_iの直後に経路情報の設定命令を挿入する。
（４）多重条件分岐の各分岐先に経路情報のチェック命令を挿入する。
（５）多重条件分岐の経路中の各条件分岐命令、及び前記（４）で挿入したチェック命令中の条件分岐命令の処理済フラグをONにする。
前記（１）〜（５）の処理終了後、ステップ７０８へ進む。
【００５８】
図８は、図６の中間語１０９に対して、図７に示す耐タンパコード挿入処理を行った後の中間語１０９の例を示すものである。以下に、図７の処理フローに従って該中間語１０９が生成される過程を示す。
【００５９】
ステップ７０２で、図６の中間語１０９から最初の命令（命令６０１）を取り出し、それをtとする。ステップ７０３でtがNULLかどうかを調べる。tはNULLではないのでステップ７０４へ進み、tが条件分岐命令かどうかを調べる。tは条件分岐命令ではないのでステップ７０８へ進み、tの次の命令（命令６０２）を新たにtとする。再びステップ７０３でtがNULLかどうかを調べ、NULLではないのでステップ７０４へ進み、tが条件分岐命令かどうかを調べる。tは条件分岐命令なのでステップ７０５へ進み、処理済フラグがONかどうかを調べる。処理済フラグはOFFなのでステップ７０６へ進み、多重条件分岐の開始命令かどうかを調べる。（１）tの直前の命令（命令６０１）は比較命令であり、（２）tの分岐先命令（命令６０５）が比較命令であり、その直後の命令（命令６０６）が条件分岐命令なので、tは多重条件分岐の開始命令であると判定され、ステップ７０７へ進む。
【００６０】
ステップ７０７では、以下の（１）〜（５）の処理を行う。
（１）多重条件分岐の各比較命令（命令６０１、命令６０５）をそれぞれc_0、c_1とする。
（２）c_0の直前に経路情報の初期化命令（命令８０１）を挿入する。命令８０１（mov）は定数0を変数flagに移動（Move）することを意味する。
（３）c_0、c_1の直後にそれぞれ、c_0、c_1を通ったことを変数flagに記録する経路情報の設定命令（命令８０２、命令８０３）を挿入する。命令８０２、命令８０３（bset/eq）は、c_0、c_1の比較結果が等しい（Equal）場合に、それぞれ変数flagの0番目、1番目のビットに1を設定する（Set）することを意味する。
（４）多重条件分岐の各分岐先の処理にそれぞれ、変数flagの0番目のビットに1が設定されている（変数flagの値が1である）かどうか、及び0番目と1番目のビットに1が設定されている（変数flagの値が3である）かどうかを定数と比較して調べる命令（命令８０４、命令８０７）と、比較結果が等しければ正常処理へと分岐する条件分岐命令（命令８０５、命令８０８）と、エラー処理へ無条件に分岐する分岐命令（命令８０６、命令８０９）とを挿入する。命令８０５、命令８０８（beq）はそれぞれ、命令８０４、命令８０７の比較結果が等しい（Equal）場合に、オペランドのポインタで指される（リンクされる）命令６０７、命令６０９へ分岐することを示す。
（５）多重条件分岐の経路中の各条件分岐命令（命令６０２、命令６０６）、及び前記（４）で挿入した各条件分岐命令（命令８０５、命令８０８）の処理済フラグをONにする。
【００６１】
次にステップ７０８へ進み、tの次の命令（命令６０３）を新たにtとし、ステップ７０３へ戻る。ステップ７０３で再びtがNULLかどうかを調べ、NULLではないのでステップ７０４へ進み、tが条件分岐命令かどうかを調べる。tは条件分岐命令ではないので、ステップ７０８へ進み、tの次の命令（命令６０４）を新たにtとする。この時点で、当該処理中の中間語１０９に条件分岐命令であって処理済フラグがOFFの命令は存在しないため、以降の処理ではステップ７０７に入ることはなく、耐タンパコードの挿入処理は行われない。
【００６２】
図９は、図５のソースプログラム１０６を入力としたときの、従来技術のコンパイラの出力するアセンブリ言語プログラムの例である。まず「cmp #0,cond1」命令（命令９０１）により、定数0（偽）の値とcond1の値を比較し、その結果を条件コードレジスタに格納する。次の「beq L1」命令（命令９０２）では、該条件コードレジスタの値を調べ、比較結果が等しい（Equal）場合はラベルL1（命令９０５）へ分岐する。そうではない（等しくない）場合は直後の命令へ制御が移り、実行文１（命令９０３）を実行して、「bra L2」命令（命令９０４）でラベルL2（命令９１２）へ分岐する。
【００６３】
命令９０２でL1へ分岐した場合、「cmp #0,cond2」命令（命令９０６）により、定数0（偽）の値と条件式cond2の値を比較し、その結果を条件コードレジスタに格納する。次の条件分岐命令（命令９０７）では、該条件コードレジスタの値を調べ、比較結果が等しい場合はラベルL3（命令９１０）へ分岐する。そうではない（等しくない）場合は直後の命令へ制御が移り、実行文２（命令９０８）を実行して、命令９０９でL2へ分岐する。命令９０７でL3へ分岐した場合、実行文３（命令９１１）を実行して直後の命令（分岐先L2と同じになる）へ制御を移す。
【００６４】
図１０は、図５のソースプログラム１０６を入力としたときの、本実施の形態でのコンパイラ２０１が出力するアセンブリ言語プログラム２０６の例である。まず、「mov #0,R1」命令（命令１００１）でレジスタR1を0に初期化する。次に、図５のソースプログラム１０６の行５０４のif文に対応する条件比較命令（命令１００２）の直後で、「bset/eq #0,R1」命令（命令１００３）により、前記条件比較命令の比較結果が等しい場合にレジスタR1の0番ビットに1を立てることにより、前記if文を通ってきたことを記録し、次の条件分岐命令１００４でラベルL1（命令１００７）へ分岐する。そうではない（等しくない）場合は、実行文１（命令１００５）を実行した後、分岐命令（命令１００６）でラベルL2（命令１０２３）へ分岐し、多重条件分岐を抜ける。
【００６５】
命令１００４でL1へ分岐した場合、図５のソースプログラム１０６の行５０６のif文に対応する条件比較命令（命令１００８）の直後で、該条件比較命令の比較結果が等しい場合にレジスタR1の１番ビットに１を立てることにより（命令１００９）、前記if文を通ってきたことを記録する。
【００６６】
命令１００８の条件比較命令の比較結果が等しくない場合は、命令１０１０の条件分岐命令で分岐せずに命令１０１１の条件比較命令へ進み、レジスタR1の0番ビットに1が設定されている（R1の値が１である）かどうかを調べることにより、図５のソースプログラム１０６の行５０４のif文を通ってきたかどうかをチェックする。前記条件比較命令の比較結果が等しい（Equal）場合、次の「beq L4」命令（命令１０１２）の条件分岐によりラベルL4（命令１０１４）に分岐し、実行文２（命令１０１５）を実行した後、分岐命令（命令１０１６）により多重条件分岐を抜ける。命令１０１１の条件比較命令の比較結果が等しくない場合、条件分岐命令（命令１０１２）で分岐せず、次の分岐命令（命令１０１３）でエラー処理（error()）へ分岐する。
【００６７】
命令１００８の条件比較命令の比較結果が等しい場合は、命令１０１０の条件分岐命令でラベルL3（命令１０１７）へ分岐して、命令１０１８の条件比較命令へ進み、レジスタR1の0番ビットと1番ビットに1が設定されている（R1の値が3である）かどうかを調べることにより、図５のソースプログラム１０６の行５０４及び行５０６のif文を通ってきたかどうかをチェックする。前記条件比較命令の比較結果が等しい場合、次の条件分岐命令（命令１０１９）によりラベルL5（命令１０２１）に分岐し、実行文３（命令１０２２）を実行した後、多重条件分岐を抜ける。命令１０１８の条件比較命令の比較結果が等しくない場合、条件分岐命令（命令１０１９）で分岐せず、次の分岐命令（命令１０２０）でエラー処理（error()）へ分岐する。このように、実行可能プログラム１０７の実行の途中で正しい経路を通っていないと判定された場合、エラー処理へと制御が移るため、誤動作の可能性が低くなる。
【００６８】
本実施の形態では、図５において、耐タンパコードを挿入する関数をソースプログラム１０６中で#pragma指示文により指定していたが、これに限定されるものではなく、コンパイラ起動コマンドに付加するコンパイルオプションによって指定することもできる。図１１はその例である。ここで「cc」はコンパイルコマンド、「prog.c」はコンパイル対象ファイル（ソースプログラム）、「-secure_func=f,g」は耐タンパコード挿入を行う対象の関数として関数fと関数gを指定していることを表している。すなわち、図１１のコンパイルコマンドにより、ソースプログラムprog.c中の関数fと関数gについては耐タンパコード挿入を行い、それ以外の関数については通常通り耐タンパコード挿入を行わずにアセンブリ言語プログラム２０６を生成することを指示している。
【００６９】
また、本実施の形態では、図５において、耐タンパコードを挿入するかどうかを関数ごとに指定していたが、さらに細かい粒度（たとえばソースプログラム１０６の文単位）で指定することも可能である。図１２はそのような指定の例を示したものである。図１２において、関数内の「#pragma secure_stm」（命令１２０４）と「#pragma secure_stm_end」（命令１２１２）で囲まれた範囲の文に対して耐タンパコード挿入を行うことを指示する。このようにした場合、コンパイラ２０１による中間語１０９の生成において、耐タンパコード挿入対象かどうかを示すフラグを中間語１０９内の関数ごとではなく命令ごとに設定することで、命令ごとに耐タンパコード挿入の制御が可能になる。
【００７０】
なお、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理の処理済フラグがONになっている中間語１０９の命令については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【００７１】
以上のように、本実施の形態での言語ツール１０８により、多重条件分岐の分岐経路検証といった、ユーザが手作業で作成するのが難しい耐タンパ性を持つ実行可能プログラム１０７を自動的に生成することができ、耐タンパ性を持つアプリケーションの開発生産性が向上する。
【００７２】
＜実施の形態２＞
以下、本発明の実施の形態２として、条件分岐判定を多重化した実行可能プログラムを生成する言語ツールの例について説明する。
【００７３】
本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。また、本実施の形態での言語ツール１０８の構成と処理概要の例は図２と同じである。また、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。図４のステップ４０５の耐タンパコード挿入処理の詳細は、実施の形態１でのものとは異なるため、図１３〜図１６を用いてさらに詳しく説明する。
【００７４】
図１３は、本実施の形態での言語ツール１０８への入力となる、ソースプログラム１０６の例である。行１３０１において変数aと変数bの値を比較し、一致している場合は行１３０２の実行文１を、そうではない場合は行１３０４の実行文２を行うことを示している。
【００７５】
図１４は、本実施の形態での言語ツール１０８により生成される、図４のステップ４０５での耐タンパコード挿入処理を行う前の、中間語１０９の例を示したものである。前記実施の形態１での図６と同様に、本実施の形態でも機械語に近いレベルの中間語を想定している。命令と呼ばれるメモリセルを、２重リンクでリスト状に繋げる形で構成している点も図６と同様である。
【００７６】
図１４の中間語１０９は、図１３のソースプログラム１０６の行１３０１〜行１３０５の部分に相当するものである。命令１４０１（cmp）は、変数aと変数bを比較（compare）することを示す。命令１４０２（bne）は、前記比較の結果、aとbが等しくない（Not Equal）場合に、オペランドのポインタで指される（リンクされる）命令１４０５へ分岐することを示す。そうではない（等しい）場合は、直後の命令１４０３に制御を移す（fall-through）。命令１４０３は、図１３のソースプログラム１０６の行１３０２の実行文１に対応する文である。ここでは１つの命令で表されているが、複数の命令から構成されている場合もある。命令１４０４（bra）は、オペランドのポインタで指される命令１４０６へ無条件分岐することを示す。
【００７７】
図１５は、本実施の形態での、図４のステップ４０５での耐タンパコード挿入処理の詳細な例を表すフローチャートである。まずステップ１５０１で、中間語１０９内の全命令の処理済フラグをOFFにする。次にステップ１５０２において、中間語１０９内の最初の命令を取り出し、それをtとする。次にステップ１５０３で、tがNULLかどうかを調べる。NULLであれば命令がすべて処理済みなので終了する。NULLでなければステップ１５０４へ進み、tが条件分岐命令かどうかを調べる。条件分岐命令でなければステップ１５０７へ進み、tの次の命令を新たにtとし、ステップ１５０３から繰り返す。ステップ１５０４でtが条件分岐命令であれば、ステップ１５０５でtの処理済フラグがONかどうかを調べる。ONであればステップ１５０７へ進み、ONでなければステップ１５０６へ進む。
【００７８】
ステップ１５０６では、以下の（１）〜（８）の処理を行う。
（１）tの直後の命令をsとする。
（２）tの直後に、tの分岐条件を反転した条件分岐命令を挿入し、これをuとする。
（３）uの直後に、ラベル_errorへの無条件分岐命令を挿入し、これをvとする。
（４）tの分岐先の命令（wとする）の直前に、tの分岐条件を反転した条件分岐命令を挿入し、これをxとする。
（５）tの分岐先をxに変更する。
（６）uの分岐先をsに変更する。
（７）xの分岐先をvに変更する。
（８）s、t、u、v、w、xの処理済フラグをONにする。
前記（１）〜（８）の処理終了後、ステップ１５０７へ進む。
【００７９】
図１６は、図１４の中間語１０９に対して図１５の耐タンパコード挿入処理を行った後の中間語１０９の例を示すものである。以下に、図１５の処理フローに従って該中間語１０９が生成される過程を示す。
【００８０】
ステップ１５０２で最初の命令（命令１４０１）を取り出し、それをtとする。ステップ１５０３でtがNULLかどうかを調べる。tはNULLではないのでステップ１５０４へ進み、tが条件分岐命令かどうかを調べる。tは条件分岐命令ではないのでステップ１５０７へ進み、tの次の命令（命令１４０２）を新たにtとする。再びステップ１５０３でtがNULLかどうかを調べる。tはNULLではないので、ステップ１５０４でtが条件分岐命令かどうかを調べる。tは条件分岐命令なのでステップ１５０５へ進み、処理済フラグがONかどうかを調べる。処理済フラグはOFFなのでステップ１５０６へ進む。
【００８１】
ステップ１５０６では、以下の（１）〜（８）の処理を行う。
（１）tの直後の命令（命令１４０３）をsとする。
（２）tの直後にtの分岐条件を反転した条件分岐命令を挿入し、これをuとする。tの分岐条件は「ne(Not Equal)」なので、これを反転した条件は「eq(Equal)」である。図１６の命令１６０１がuに相当する。
（３）uの直後に、ラベル_errorへの無条件分岐命令を挿入し、これをvとする。図１６の命令１６０２がvに相当する。
（４）tの分岐先の命令は図１４の命令１４０５なので、これをwとし、wの直前にtの分岐条件を反転した条件分岐命令を挿入し、これをxとする。図１６の命令１６０３がxに相当する。
（５）t（命令１４０２）の分岐先をx（命令１６０３）に変更する。
（６）u（命令１６０１）の分岐先をs（命令１４０３）に変更する。
（７）x（命令１６０３）の分岐先をv（命令１６０２）に変更する。
（８）s、t、u、v、w、xの処理済フラグをONにする。
【００８２】
次にステップ１５０７へ進み、tの次の命令（命令１６０１）を新たにtとし、ステップ１５０３へ戻る。ステップ１５０３で再びtがNULLかどうかを調べ、tはNULLではないのでステップ１５０４へ進み、tが条件分岐命令かどうかを調べる。t（命令１６０１）は条件分岐命令なのでステップ１５０５へ進み、tの処理済フラグがONかどうかを調べる。命令１６０１の処理済フラグは、前記ステップ１５０６の（８）の処理でONにされているので、ステップ１５０７へ進み、tの次の命令（命令１６０２）が新たにtに設定され、再びステップ１５０３からの処理を行う。この時点で、当該処理中の中間語１０９に条件分岐命令であって処理済フラグがOFFの命令は存在しないため、以降の処理ではステップ１５０６に入ることはなく、耐タンパコードの挿入処理は行われない。
【００８３】
図１７は、図１３のソースプログラム１０６を入力としたときの、従来技術のコンパイラの出力するアセンブリ言語プログラムの例である。まず、「cmp Ra,Rb」命令（命令１７０１）により、変数aの値を保持するレジスタRaと、変数bの値を保持するレジスタRbの値を比較し、その結果を条件コードレジスタに格納する。次の命令１７０２では、該条件コードレジスタの値を調べ、比較結果が等しくない場合はラベルL1（命令１７０５）へ分岐する。そうではない（等しい）場合は直後の命令へ制御を移し、実行文１（命令１７０３）を実行して、命令１７０４でラベルL2（命令１７０７）へ分岐する。命令１７０２でL1へ分岐した場合、実行文２（命令１７０６）を実行した後、直後の命令へ制御を移す。
【００８４】
図１８は、図１３のソースプログラム１０６を入力としたときの、本実施の形態での言語ツール１０８が出力するアセンブリ言語プログラム２０６の例である。ここでは図１３のソースプログラム１０６の行１３０１のif文に対応する条件分岐命令が命令１８０２〜命令１８０３のように、２つ連続して並べられている。これにより、もし最初の条件分岐命令が、誤動作解析アタックなどの攻撃により不正にfall-through分岐した場合でも、２番目の条件分岐命令で再度条件判定が行われるため、誤動作の可能性が低くなる。
【００８５】
なお、図１８のアセンブリ言語プログラム２０６では、命令１８０２〜命令１８０３に示すように、分岐条件を反転させて条件分岐を連続して行うようにしているが、分岐条件を反転させずに連続して行うようなコードを生成してもよい。このときのアセンブリ言語プログラム２０６の例を図１９に示す。
【００８６】
命令１９０２〜命令１９０３は同じ分岐条件の条件分岐命令を連続して並べている。この場合も、最初の条件分岐命令１９０２が誤動作解析アタックにより不正にfall-through分岐したとしても、次の条件分岐命令１９０３で再度同じ条件判定が行われるため、誤動作の可能性が低くなる。命令１９０２又は命令１９０３で分岐しなかった場合、命令１９０５でさらに同様の分岐条件で判定し、ここで分岐する判定となった場合はエラー処理（error()）へ分岐する。また、逆に最初の条件分岐命令１９０２が誤動作解析アタックにより不正にラベルL1（命令１９０８）へ分岐したとしても、命令１９０９で再び分岐条件を調べ、正しい分岐方向であるラベルL3（命令１９０４）に戻れるようにする。命令１９０９にてL3に分岐しなかった場合は、命令１９１０でさらに同じ分岐条件でチェックを行い、正しい分岐方向に戻れていない場合はエラー処理（error()）へ分岐する。
【００８７】
図１８及び図１９のアセンブリ言語プログラム２０６の例では、条件分岐命令を２つ並べて多重化しているが、条件分岐命令を３つ以上並べて多重化することも可能である。
【００８８】
図２０は、本実施の形態での言語ツール１０８に、さらに前記実施の形態１で示した多重条件分岐の分岐経路検証を行うコードを挿入する処理を組み合わせた場合に、図５のソースプログラム１０６を入力としたときの言語ツール１０８が出力するアセンブリ言語プログラム２０６の例を示したものである。実施の形態１での言語ツール１０８にて耐タンパコード挿入処理を行った出力結果である図１０のアセンブリ言語プログラム２０６に比べて、ラベル２００６と命令２００７、ラベル２０１７と命令２０１８、及び命令２００５、命令２０１２、命令２０１６、命令２０２７の各条件分岐命令が、本実施の形態での言語ツール１０８での処理により追加で挿入されている。
【００８９】
なお、図２０において、本実施の形態での言語ツール１０８により多重化される条件分岐命令は、図５のソースプログラム１０６において存在した条件分岐命令に対応するもののみであり、前記実施の形態１での言語ツール１０８での処理により挿入された条件分岐命令（命令２０２１、命令２０２９）については多重化されていないが、該条件分岐命令を多重化することも可能である。
【００９０】
実施の形態１と同様に、本実施の形態においても、耐タンパコードを挿入する関数をソースプログラム１０６中で#pragma指示文により指定する。コンパイラ起動コマンドに付加するコンパイルオプションによって指定することもできる。また、耐タンパコードを挿入するかどうかを関数毎ではなくさらに細かい粒度で指定することも可能である。
【００９１】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理の処理済フラグがONになっている中間語１０９の命令については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【００９２】
以上のように、本実施の形態での言語ツール１０８により、条件分岐判定の多重化といった、ユーザが手作業で作成するのが難しい耐タンパ性を持つ実行可能プログラム１０７を自動的に生成することができ、耐タンパ性を持つアプリケーションの開発生産性が向上する。
【００９３】
＜実施の形態３＞
以下、本発明の実施の形態３として、関数呼び出し時のパラメータ内容チェックを行う実行可能プログラムを生成する言語ツールの例について説明する。
【００９４】
本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。また、本実施の形態での言語ツール１０８の構成と処理概要の例は図２と同じである。また、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。図４のステップ４０５の耐タンパコード挿入処理の詳細は、実施の形態１及び実施の形態２でのものとは異なるため、図２１〜図２４を用いてさらに詳しく説明する。
【００９５】
図２１は、本実施の形態での言語ツール１０８への入力となる、ソースプログラム１０６の例である。関数main（行２１０１〜行２１０６）から、行２１０４においてarg1、arg2を実引数として関数sub（行２１０８〜行２１１１）を呼び出していることを示している。
【００９６】
図２２は、本実施の形態での言語ツール１０８により生成される、図４のステップ４０５での耐タンパコード挿入処理を行う前の、中間語１０９の例を示したものである。コンパイラが生成する中間語には、一般にソースプログラムに近いレベルのものから、機械語に近いレベルのものまで存在するが、本実施の形態ではソースプログラムに近いレベルのものを想定している。中間語１０９はノードと呼ばれるメモリセルを２重リンクでツリー状に接続する形で構成しており、ソースプログラム１０６の１つの関数が１つのツリーに対応し、ツリーのルートに当たるノード同士は２重リンクでリスト状につなげる形で構成している。図中の矢印はノード間のリンクを表す。
【００９７】
図２２の中間語１０９は、図２１のソースプログラム１０６に対応するものである。ノード２２０１は関数mainの先頭文（行２１０１）を表すノードである。ノード２２０１には、関数内の最初の実行文（行２１０３）を示すstmtノード２２０２が接続されている、stmtノード２２０２には、前記実行文（行２１０３）の処理内容を表すノード２２０３と、次の実行文（行２１０４）を示すstmtノード２２０４が接続されている。同様に、stmtノード２２０６はstmtノード２２０４の次に実行される文（行２１０５）を示す。
【００９８】
stmtノード２２０４には、行２１０４の処理内容である関数呼び出しを示すcallノード２２０５が接続されている。callノード２２０５には、呼び出し先の関数subを表すidノード２２０７と、実引数のリストを示すarg_listノード２２０８とが接続されている。arg_listノード２２０８には、関数呼び出しの実引数arg1、arg2を表すidノード２２１０とidノード２２１１とが接続されている。
【００９９】
ノード２２１２は、次の関数subの先頭文（行２１０８）を表すノードである。ノード２２１２には、関数の仮引数リストを示すparamノード２２１３と、関数内の最初の実行文（行２１１０）を示すstmtノード２２１４とが接続されている。paramノード２２１３には、仮引数a、bを表すidノード２２１５とidノード２２１６とが接続されている。関数の先頭文を示すノード２２０１とノード２２１２は２重リンクでリスト状につなげる形で構成している。
【０１００】
図２３は、本実施の形態での、図４のステップ４０５での耐タンパコード挿入処理の詳細な例を表すフローチャートである。
【０１０１】
まずステップ２３０１で、中間語１０９の最初の文のノードを取り出し、それをtとする。次にステップ２３０２で、tがNULLかどうかを調べる。NULLであればノードがすべて処理済みなので終了する。NULLでなければステップ２３０３へ進み、tが関数先頭文のノードかどうかを調べる。関数先頭文のノードでなければステップ２３０６へ進む。関数先頭文のノードであればステップ２３０４へ進み、該関数に仮引数があるかどうかを調べる。仮引数が無ければステップ２３０６へ進み、仮引数があればステップ２３０５へ進む。
【０１０２】
ステップ２３０５では、以下の（１）〜（２）の処理を行う。
（１）前記仮引数をpar1、par2、...、parNとしたとき、
if (par1+par2+...+parN != sum) goto error
という実行文に相当するノードを、該関数の先頭の実行文のノードとして挿入する。元々の先頭の実行文のノードは、新たに挿入した前記ノードの次の実行文として接続する。
（２）該関数の仮引数の末尾に仮引数sumを追加する。
【０１０３】
次にステップ２３０６で、tが関数呼び出し文のノードかどうかを調べる。関数呼び出し文のノードではない場合はステップ２３０９へ進み、tの次の文のノードを新たにtとし、ステップ２３０２から繰り返す。tが関数呼び出し文のノードの場合、ステップ２３０７へ進み、該関数呼び出しに実引数があるかどうかを調べる。実引数が無ければステップ２３０９へ進む。実引数がある場合はステップ２３０８へ進み、実引数をarg1、arg2、...、argNとしたとき、arg1+arg2+...+argNを実引数の末尾に追加してステップ２３０９へ進む。
【０１０４】
図２４は、図２２の中間語１０９に対して図２３の耐タンパコード挿入処理を行った後の中間語１０９の例を示すものである。以下に、図２３の処理フローに従って該中間語１０９が生成される過程を示す。
【０１０５】
まずステップ２３０１で、図２２の中間語１０９から最初のノード（ノード２２０１）を取り出し、これをtとする。次にステップ２３０２で、tがNULLかどうかを調べる。tはNULLではないのでステップ２３０３へ進み、tが関数先頭文のノードかどうかを調べる。tは関数mainの先頭文のノードなのでステップ２３０４へ進み、該関数に仮引数があるかどうかを調べる。該関数には仮引数が無いのでステップ２３０６へ進み、tが関数呼び出し文のノードかどうかを調べる。tは関数呼び出し文のノードではないのでステップ２３０９へ進み、tの次の文のノード（ノード２２０２）を新たにtとする。ノード２２０２は関数先頭文でも関数呼び出し文でもないので何も処理されず、ステップ２３０９でノード２２０４を新たにtとする。
【０１０６】
tは関数先頭文のノードではないので、ステップ２３０３からステップ２３０６に移るところまではノード２２０２の場合と同様だが、ノード２２０４にはcallノード２２０５が接続されており、関数呼び出し文のノードなのでステップ２３０７へ進み、該関数呼び出し文に実引数があるかどうかを調べる。callノード２２０５には実引数リストのarg_listノード２２０８が接続されており、実引数があるので、ステップ２３０８へ進む。
【０１０７】
ステップ２３０８では、前記実引数がarg1、arg2なので、arg1+arg2を実引数リストの末尾に追加して（ノード２４０１〜ノード２４０３）、ステップ２３０９へ進む。次にtの次の文（ノード２２０６）を新たなtとする。以降、関数main内の文のノードは、ノード２２０２と同様に関数先頭文でも関数呼び出し文でもないので、耐タンパコード挿入処理は行われない。
【０１０８】
関数main内の実行文の処理が終了すると、次の関数の処理に移り、ノード２２１２をtとして、ステップ２３０２でtがNULLかどうかを調べる。tはNULLではないのでステップ２３０３へ進み、tが関数先頭文のノードかどうかを調べる。tは関数subの先頭文のノードなのでステップ２３０４へ進み、該関数に仮引数があるかどうかを調べる。ノード２２１２にはparamノード２２１３が接続されており、仮引数があるので、ステップ２３０５へ進む。
【０１０９】
ステップ２３０５では、以下の（１）〜（２）の処理を行う。
（１）paramノード２２１３に接続されているidノード２２１５、idノード２２１６より、仮引数がa、bなので、if (a+b != sum) goto errorという実行文に相当するノード（ノード２４０５〜ノード２４１３）を、関数subの先頭の実行文のノードとして挿入する。元々の先頭の実行文のstmtノード２２１４は、新たに挿入したstmtノード２４０５の次の実行文として接続する。
（２）関数subの仮引数の末尾に仮引数sum（ノード２４０４）を追加する。
【０１１０】
次にステップ２３０６へ進み、tが関数呼び出し文のノードかどうかを調べる。tは関数呼び出し文のノードではないのでステップ２３０９へ進み、tの次の文のノード（ノード２２１４）を新たにtとする。以降、関数sub内の文には関数先頭文も関数呼び出し文もないので、ステップ２３０５及びステップ２３０８に入ることはなく、耐タンパコードの挿入処理は行われない。
【０１１１】
図２５は、図２１のソースプログラム１０６を入力としたときの、従来技術のコンパイラの出力するアセンブリ言語プログラムの例である。まず、関数main内で、「mov arg1,r0」命令（命令２５０３）でレジスタr0にarg1の値を、「mov arg2,r1」命令（命令２５０４）でレジスタr1にarg2の値をそれぞれ設定する。次に、「push」命令（命令２５０５、命令２５０６）でレジスタr0、r1の値をパラメータとしてスタックに積んで呼び出し先の関数に渡せるようにして、「jsr _sub」命令（命令２５０７）で関数subを呼び出している。関数subでは、「pop」命令（命令２５１０、命令２５１１）により、渡されたパラメータの値をレジスタに戻している。
【０１１２】
図２６は、図２１のソースプログラム１０６を入力としたときの、本実施の形態での言語ツール１０８が出力するアセンブリ言語プログラム２０６の例である。図２６のアセンブリ言語プログラム２０６では、図２１のソースプログラム１０６の行２１０４の関数subの呼び出しに対応する命令（命令２６１０）に対して、命令２６０５、命令２６０６により実引数arg1、arg2の値を加算したものをレジスタr2に設定し、それを命令２６０９の「push」命令により末尾の実引数としてスタックに積んで関数subに渡している。
【０１１３】
呼び出された関数subの処理では、まず命令２６１３〜命令２６１５の「pop」命令によりレジスタr0、r1、r2にパラメータの値を戻す。次に、命令２６１６、命令２６１７により、仮引数a、bに相当するパラメータの値（r0、r1）をレジスタr3に足し合わせる。次に、命令２６１８により、追加された仮引数sumに相当するパラメータの値（r2）と前記r3の値を比較している。前記比較結果が等しくない（ne）場合は命令２６１９によりエラー処理（error()）へ分岐する。これにより、関数呼び出し時に、誤動作解析アタックなどの攻撃により不正にパラメータの値が変更された場合はエラー処理へ制御が移るため、誤動作の可能性が低くなる。
【０１１４】
実施の形態１と同様に、本実施の形態においても、耐タンパコードを挿入する関数をソースプログラム１０６中で#pragma指示文により指定する。コンパイラ起動コマンドに付加するコンパイルオプションによって指定することもできる。また、耐タンパコードを挿入するかどうかを関数毎ではなくさらに細かい粒度で指定することも可能である。
【０１１５】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理の処理済フラグがONになっている中間語１０９の命令については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【０１１６】
以上のように、本実施の形態での言語ツール１０８により、関数呼び出し時のパラメータ内容チェックといった、ユーザが手作業で作成するのが難しい耐タンパ性を持つ実行可能プログラム１０７を自動的に生成することができ、耐タンパ性を持つアプリケーションの開発生産性が向上する。
【０１１７】
＜実施の形態４＞
本発明の実施の形態４として、ループ処理についての複数パターンのコード生成による電流特性複雑化を行うことにより、実行時の電流特性の特徴を薄めるような機械語を生成する言語ツールの例について説明する。
【０１１８】
ソースプログラムにおけるループ処理（Ｃ言語におけるfor文、while文、do while文等）をそのまま機械語に翻訳して実行可能プログラムを生成すると、当該実行可能プログラムは同じような処理を繰り返し実行するために、実行時の電流特性に一定のパターン化した特徴が現れる。このような特徴的な電流特性は、攻撃者に対して不正な動作解析の機会を与える危険性が高い。
【０１１９】
図２７は、ループ処理を記述したＣ言語のソースプログラムの例であり、単純なデータ転送処理を繰り返し行うものである。図２８は、図２７のソースプログラムを従来の言語ツールにてコンパイルした結果の機械語命令列をアセンブラ記述により表した例である。図２８において、（１）〜（３）で表された処理ブロックのうち、（２）の処理ブロックはループ処理の内容である図２７の行２７０２のデータ転送処理を実行する部分となる。図２９は、図２８のプログラムを実行した場合の処理順序の例を表した図であり、図２８における（２）のデータ転送処理が繰り返し実行されることを表している。この場合、同じような電流特性が短い周期で繰り返され、その特性からループ処理であることが推定される危険性がある。
【０１２０】
そこで、本実施の形態での言語ツールでは、ループ内の処理について、同じ内容の処理を複数パターンの命令列で展開することにより、処理を複雑化させる。図３０は、図２７のソースプログラムについて、ループ処理を複雑化させてコンパイルした結果の機械語命令列をアセンブラ記述により表した例である。図３０において、（１）〜（１０）で表された処理ブロックのうち、（２）〜（９）の処理ブロックは、ループ処理の内容である図２７の行２７０２のデータ転送処理をそれぞれ異なる複数パターンの命令列で表現したものである。図３１は、図３０のプログラムを実行した場合の処理順序の例を表した図であり、図３０における（２）〜（９）の処理ブロックが順に実行されることを表している。
【０１２１】
これにより、ループ毎に同じ命令列の繰り返しではなく、すべて異なる複数パターンの命令列により処理を行うことになり、単純なループ処理を実行した場合の電流特性の規則性を希薄化することができる。よって実行時には一見不規則な電流特性となり、ループ処理以外の他の処理の実行時と見分けが付きにくくなり、攻撃者からの不正な動作解析を困難にすることができる。
【０１２２】
このような機械語の命令列の作成は、ユーザによる手作業でも可能ではあるが、アセンブリ言語等の低級言語の知識を要求するためそのハードルは高く、工数も要する。よって、言語ツールにループ内の処理を自動的に複雑化する機能を追加することによって、自動的にこのような機械語の命令列が生成されるようにする。この場合、ある処理に対して複数パターンの命令列を作成できるように、言語ツールは多くの処理パターンを内部に記憶しておき、対象となるループ処理に対して必要な数だけパターンを埋め込むようにする。
【０１２３】
以下に、本実施の形態での言語ツールの具体的な内容について説明する。本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。また、本実施の形態での言語ツール１０８の構成と処理概要の例は図２と同じである。また、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。
【０１２４】
図４のステップ４０５の耐タンパコード挿入処理によって、ソースプログラム１０６中のループ処理がどのように複雑化されるかを、簡単な例を挙げて説明する。一般的に、ソースプログラム１０６中に記述されるループ処理は、ループ回数が多いために、全てのループ処理を図３０に示す例のように一度に展開すると、プログラムサイズが発散してしまう場合がある。また、ループ回数があらかじめ固定ではなく、実行時までループ回数が確定しない場合も多く、ループ内の処理を全て展開することは現実的ではない。
【０１２５】
そこで、図３０に示す例のようにループ内の処理を一律に全パターンで展開するのとは別に、下記のような手順により効果的に複数パターンに展開する。
（１）ユーザが指定する数に達するまで、ループ内処理を複数パターンの命令列で作成する。
（２）作成された複数パターンの命令列の実行をswitch文のような形式で振り分ける。
（３）前記switch文での振り分けに使用する変数とその計算式を設定する。
（４）前記switch文をソースプログラム１０６に記述されているループ回数だけループさせる。
【０１２６】
このようにしてループ処理を複数パターンの命令列に展開する場合のコード生成例を図３２に示す。図３２は、Ｃ言語によりループ処理を記述したソースプログラム１０６と、当該ソースプログラム１０６を本実施の形態でのコンパイラ２０１によってコンパイルした結果の例を表している。なお、コンパイルした結果については、説明を簡便にするためにアセンブリ言語ではなくＣ言語による擬似プログラムの形式で表している。
【０１２７】
ソースプログラム１０６の行３２０２〜行３２０４は、単純なデータ転送を行うループ処理の例を表している。当該ループ処理が、処理内容を知られたくないループである場合、ユーザは、行３２０１および行３２０５の拡張言語仕様#pragmaにて、耐タンパコード挿入処理の対象範囲として当該ループ処理を指定することができる。図３３は、Ｃ言語でソースプログラム１０６を記述する場合の拡張言語仕様#pragmaによる書式の例である。ここで、ループの先頭では、書式３３０１の#pragmaにて当該ループ処理を複数パターンの命令列で展開する際の最大サイズを指定することができる。これにより、プログラムサイズが発散してしまうのを避けることができる。
【０１２８】
前記（１）の手順により、行３２０３の処理は、行３２１６〜行３２２３のように、行３２０１の#pragmaにて指定されている最大サイズである８つの処理パターンに展開されている。ここで、行３２１６〜行３２２３の「転送パターンx」という処理は、行３２０３のデータ転送処理と同じ動作内容を、それぞれ異なる命令列によって実現するものを表している。
【０１２９】
また、前記（２）の手順により、行３２１４のswitch文で行３２１６〜行３２２３の処理が振り分けられるようになっている。また、前記（３）の手順により、行３２１１、行３２２５で、行３２１４のswitch文で使用する変数xの設定と値の更新を行うようになっている。また、前記（４）の手順により、行３２１２のfor文で、行３２１４〜行３２２５の処理を、ソースプログラム１０６における行３２０２で指定されているループ回数と同じ回数だけループさせている。
【０１３０】
このような処理により、行３２１２〜行３２２６のループ処理を実行した場合のループ毎の処理時間や電流特性は異なることになり、それぞれが同じ内容の処理であることが悟られにくくなる。この場合、各データ転送パターンを順に実行するだけでも、ループ内の処理の電流特性周期は単純に８倍になるが、行３２２５での変数xの値の更新方法を工夫することにより、電流特性周期をさらに大きくすることができ、単純なデータ転送処理であることを隠蔽することができる。
【０１３１】
ここで、変数xは、行３２１４のswitch文による処理の振り分けのために用いる判定値なので、見かけ上ランダムな値になるのが望ましく、見かけ上の規則性がない、もしくは薄くなるように行３２２５で更新することができるのであれば、「その時点で値が確定している何らかのデータ」を用いればよい。判定値の更新方法として、例えば以下のような方法が考えられる。
（ａ）判定値のテーブルを別途用意する。またはテーブルに相当するものを利用する。
（ｂ）その時点で設定されているレジスタ等の値を利用する。
【０１３２】
以下に、前記（ａ）、（ｂ）の更新方法によって判定値を更新してループ処理を複雑化した場合の例を説明する。図３４は、前記（ａ）の、判定値のテーブルまたはそれに相当するものを利用して判定値を更新してループ処理を複雑化した場合の例を、Ｃ言語のソースプログラムのイメージで表した図である。
【０１３３】
ここで、処理の振り分けに際しては、判定値のテーブルを実際に使用するのが最も簡単ではあるが、当該テーブルをメモリ上に保持するのではメモリの使用効率が悪くなる。振り分けに際しては実際に判定値のテーブルを用意する必要はなく、テーブルに相当するものとして例えば、ターゲットマイコン２０８のプログラム格納領域３０２に格納されている実行可能プログラム１０７の命令コード自体を判定のための要素としても、電流特性の周期性がない処理の振り分けが可能である。図３４のコンパイル結果では、行３４２５にて実行可能プログラム１０７の命令コードの値を順次参照し、行３４１４ではその値を利用して0〜7の数値を算出し、switch文による処理の振り分けを行っている。
【０１３４】
図３５は、前記（ｂ）の、レジスタの設定値を利用して判定値を更新してループ処理を複雑化した場合の例を、Ｃ言語のソースプログラムのイメージで表した図である。図３５のコンパイル結果では、行３５２５にて実行時点におけるレジスタの値を取得して、行３５１４ではその値を利用して0〜7の値を算出してswitch文による処理の振り分けを行うことにより、ループ処理の電流特性の規則性を排除している。なお、行３５２５において参照するレジスタは、汎用レジスタやシステムレジスタなど全てのレジスタを対象にすることができる。
【０１３５】
判定値の更新方法は上述した方法だけに限られず、これ以外にも種々の方法が考えられる。例えば、判定値の規則性の周期が大きくなるような計算式によって判定値を更新する方法などが考えられる。
【０１３６】
なお、本実施の形態での言語ツール１０８では、ソースプログラム１０６において耐タンパコード挿入処理の対象となるループ処理を指定する方法として、図３３に示す拡張言語仕様#pragmaによりループ処理毎に指定する方法をとっているが、実施の形態１と同様に、コンパイラ起動コマンドに付加するコンパイルオプションによって一括指定する方法をとることも可能である。
【０１３７】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理によって挿入された中間語１０９については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【０１３８】
以上のように、本実施の形態での言語ツール１０８により、単純なループ処理を複数の処理パターンによって展開して複雑化することで実行時の電流特性の規則性を希薄にし、消費電流の解析による処理内容の推定・解析を困難にするといった、耐タンパ性を持つプログラムを生成することができる。また、このようなユーザが手作業で作成することが難しいプログラムを自動的に生成することができ、耐タンパ性を持つプログラムの開発生産性が向上する。また、本実施の形態での言語ツール１０８によってコンパイルを実行することにより、高級言語で記述された既存のソースプログラムをそのまま耐タンパ性を有するセキュアなプログラムへ移植することも容易となる。
【０１３９】
＜実施の形態５＞
本発明の実施の形態５として、条件分岐の各分岐経路の実行時間を均一化することによる電流特性近似化を行うことにより、実行時の電流特性の特徴を薄めるような機械語を生成する言語ツールの例について説明する。
【０１４０】
ソースプログラム１０６に条件分岐（Ｃ言語におけるif文、switch文等）があり、分岐先の処理が例えば処理Ａと処理Ｂである２通りの分岐経路がある場合、処理Ａと処理Ｂの実行時間が異なると、実行時の電流特性から「どちらの処理を行った」ということを推測される危険性がある。特に、機密情報の種類に応じて処理を分ける場合などにおいて危険性が高い。
【０１４１】
図３６は、条件分岐処理を記述したＣ言語のソースプログラムの例であり、３つのデータ転送処理を行う分岐経路１と１つのデータ転送処理を行う分岐経路２とを有する。ここでは１命令あたりの実行サイクル数を例えば１と仮定して説明する。図３７は、図３６のソースプログラムを従来の言語ツールにてコンパイルした結果の機械語命令列をアセンブラ記述により表した例である。図３７において、分岐経路１は実行サイクル数が４であり、分岐経路２は実行サイクル数が１となっており、分岐経路によって処理の実行時間が異なることから、処理内容を推測される危険性がある。
【０１４２】
そこで、本実施の形態での言語ツールでは、実行しても実行可能プログラムの動作内容に影響を与えないような処理を埋め込むなどによって、各分岐経路の処理の実行時間が均一化されるように機械語の命令列を生成する。これにより、実行可能プログラムの実行時には、各分岐経路の処理の実行時間が近い値となり、また電流特性も近似したものになるため、攻撃者からの不正な動作解析を困難にすることができる。
【０１４３】
このような機械語の命令列の作成は、ユーザによる手作業でも可能ではあるが、低級言語の知識を要求するためそのハードルは高く、工数も要する。よって、言語ツールに各分岐経路の処理の実行時間を均一化する機能を追加することによって、自動的にこのような機械語の命令列が生成されるようにする。その際、分岐経路の実行時間は、分岐経路中の各命令の実行サイクル数によって計算する。言語ツールは、各命令の実行サイクル数を記憶しておき、各分岐経路内の命令の実行サイクル数の合計が一致する（あるいは可能な限り近い値になる）ように自動的に命令列を生成する。
【０１４４】
以下に、本実施の形態での言語ツールの具体的な内容について説明する。本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。また、本実施の形態での言語ツール１０８の構成と処理概要の例は図２と同じである。また、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。
【０１４５】
図４のステップ４０５の耐タンパコード挿入処理によって、ソースプログラム１０６中の条件分岐処理の実行時間がどのように均一化されるかを、簡単な例を挙げて説明する。なお、ここでは説明を簡単にするために各命令の実行サイクル数は同じであるとする。
【０１４６】
図３８は、Ｃ言語により条件分岐処理を記述したソースプログラム１０６の例と、当該ソースプログラム１０６を従来のコンパイラによりコンパイルした結果の例と、本実施の形態でのコンパイラ２０１によってコンパイルした結果の例を表している。図中、斜字体で記載されている部分は、本実施の形態でのコンパイラ２０１の耐タンパコード挿入処理によって生成された命令列を表している。なお、ここでは１命令あたりの実行サイクル数を例えば１と仮定して説明する。
【０１４７】
ソースプログラム１０６の行３８０２〜行３８０９は、条件分岐処理の例を表している。当該条件分岐処理が、処理内容を知られたくない条件分岐である場合、ユーザは実施の形態４と同様に、行３８０１および行３８１０の拡張言語仕様#pragmaにて、耐タンパコード挿入処理の対象範囲として当該条件分岐処理を指定することができる。図３９は、Ｃ言語でソースプログラム１０６を記述する場合の拡張言語仕様#pragmaによる書式の例である。
【０１４８】
図３８において、本実施の形態でのコンパイラ２０１によるコンパイル結果では、行３８２８〜行３８３１のように、ソースプログラム１０６のelse節における行３８０８の加算処理を、対応する分岐経路の処理である行３８０３〜行３８０５の加算処理のコンパイル結果である行３８２３〜行３８２６と同様に３つの加算処理として実現し、両方の分岐経路の実行サイクル数の合計が４サイクルで一致するように命令列が生成されている。ここで、行３８０８における「3を加算する」という処理と、行３８２８〜行３８３０における「1を加算する」という処理を３回行うことは、最終的な動作内容としては同じである。
【０１４９】
また、対象の条件分岐処理がelse節を有しないif文である場合は、使用しないダミーデータに対して条件分岐先の処理と同様の処理を行うelse節を追加するようにすれば、簡単に前記と同様の内容を実現することができる。図４０は、Ｃ言語によりelse節を有しないif文を記述したソースプログラム１０６の例と、当該ソースプログラム１０６を従来のコンパイラによりコンパイルした結果の例と、本実施の形態でのコンパイラ２０１によってコンパイルした結果の例を表している。図中、斜字体で記載されている部分は、本実施の形態でのコンパイラ２０１の耐タンパコード挿入処理によって生成された命令列を表している。
【０１５０】
図４０において、本実施の形態でのコンパイラ２０１によるコンパイル結果では、行４０２５以下のelse節が追加されており、当該else節では行４０２６にて、対応する分岐経路中の処理である行４０２３のデータ設定処理と同様のデータ設定処理を、使用しないダミーデータに対して行い、両方の分岐経路の実行サイクル数の合計が２サイクルで一致するように命令列が生成されている。なお、ここでは１命令あたりの実行サイクル数を例えば１と仮定して説明する。
【０１５１】
本実施の形態では、if〜else文によって２つの分岐経路を有する条件分岐処理を例として挙げているが、例えばif〜else if文や、switch文によってソースプログラム１０６において分岐経路が２つ以上となるような場合も前記と同様な処理を行うことが可能である。
【０１５２】
なお、本実施の形態での言語ツール１０８では、ソースプログラム１０６において耐タンパコード挿入処理の対象となる条件分岐処理を指定する方法として、図３９に示す拡張言語仕様#pragmaにより条件分岐処理毎に指定する方法をとっているが、実施の形態４と同様に、コンパイラ起動コマンドに付加するコンパイルオプションによって一括指定する方法をとることも可能である。
【０１５３】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理によって挿入された中間語１０９については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【０１５４】
以上のように、本実施の形態での言語ツール１０８により、条件分岐処理に対して冗長な命令を追加することで各条件分岐処理の実行時間を均一化し、実行時の電流特性を近似させることによって、消費電流の解析による処理内容の推定・解析を困難にするといった、耐タンパ性を持つプログラムを生成することができる。また、このようなユーザが手作業で作成することが難しいプログラムを自動的に生成することができ、耐タンパ性を持つプログラムの開発生産性が向上する。また、本実施の形態での言語ツール１０８によってコンパイルを実行することにより、高級言語で記述された既存のソースプログラムをそのまま耐タンパ性を有するセキュアなプログラムへ移植することも容易となる。
【０１５５】
＜実施の形態６＞
本発明の実施の形態６として、命令コードを積算したチェックサムの期待値を算出し、実行時の命令コードの積算値とハードウェアにより比較することでプログラムの誤動作を検出または防止することを可能とする機械語を生成する言語ツールの例について説明する。
【０１５６】
プログラムの実行時に、ハードウェアを用いてソースプログラムにおける所定の領域の命令コードの積算値（チェックサム）を算出しその期待値と比較することによって、期待値と異なる場合は命令コードの変化や命令コードのスキップが発生したと推定され、プログラムの誤動作を検出または防止することが可能である。
【０１５７】
このようなチェックサムによる検証の際には、所定の領域の命令コードを0から積算し、あらかじめ設定されている期待値と比較する方法と、積算結果が所定の値（例えば0）になるように積算の初期値を設定し、積算結果が所定の値になることを確認する方法とが考えられる。以下では、前記期待値および初期値を積算設定値と総称する。
【０１５８】
チェックサムによる検証を行うためには、プログラムに、チェックサム検証のためのハードウェアのレジスタ情報の設定や、所定の領域での積算開始・終了の指示などをハードウェアに対して行う命令列を埋め込む必要がある。このような機械語の命令列の作成は、ユーザによる手作業でも可能ではあるが、低級言語の知識を要求するためそのハードルは高く、工数も要する。
【０１５９】
また、前述の積算設定値は、事前にレジスタ等に設定しておく必要がある。ここで、積算設定値の算出については、ユーザが人手により算出する方法や、プログラムの１回目の実行時に算出してそれを記憶しておき、２回目以降の実行時には記憶した値を用いる方法などが考えられる。しかし、ユーザが人手により算出する場合は、開発工数が大きく増加してしまう。また、プログラムの１回目の実行時に算出する方法では、１回目の実行時にはチェックサムによる検証ができないことになる。
【０１６０】
よって、言語ツール１０８にチェックサム検証のためのハードウェアのレジスタ情報の設定、所定の領域のチェックサムの積算開始と積算終了・検証実行の指示をハードウェアに対して行う命令列を作成する機能、および当該所定の領域の積算設定値を算出する機能を追加することによって、チェックサム検証を行うことを可能とする機械語の命令列が自動的に生成されるようにする。
【０１６１】
以下に、本実施の形態での言語ツールの具体的な内容について説明する。本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。また、本実施の形態での言語ツール１０８の構成と処理概要の例は図２と同じである。また、本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。
【０１６２】
図４のステップ４０５の耐タンパコード挿入処理によって、チェックサム検証を行うことを可能とする命令列がどのように作成されるかを、簡単な例を挙げて説明する。図４１は、Ｃ言語によりチェックサム検証を行うための指示を記述したソースプログラム１０６の例と、当該ソースプログラム１０６を本実施の形態でのコンパイラ２０１によってコンパイルした結果の例を表している。図中、斜字体で記載されている部分は、本実施の形態でのコンパイラ２０１の耐タンパコード挿入処理によって生成された命令列を表している。
【０１６３】
ソースプログラム１０６の行４１０６〜行４１０７は、関数内における処理ブロックの例を表している。当該処理ブロックに対してチェックサム検証を行いたい場合、ユーザは実施の形態４と同様に、行４１０５および行４１０８の拡張言語仕様#pragmaにて、耐タンパコード挿入処理の対象範囲、すなわちチェックサム検証の対象範囲として当該処理ブロックを指定することができる。図４２は、Ｃ言語でソースプログラム１０６を記述する場合の拡張言語仕様#pragmaによる書式の例である。書式４２０１の#pragmaを使用して、行４１０１において積算設定値を格納するレジスタのアドレスや、チェックサムの積算開始・終了を指示するためのレジスタおよびその設定値等を定義している。
【０１６４】
本実施の形態でのコンパイラ２０１によるコンパイル結果では、行４１１７〜行４１２１までの処理範囲に対して積算設定値を算出して#CSというシンボルに定義し、行４１１２、行４１１３にてその値をレジスタに設定する命令列が生成されている。また、行４１１４、行４１１５および行４１２０、行４１２１にてハードウェアに対してチェックサムの積算開始の指示および積算終了と検証実行の指示を行うためのレジスタを設定する命令列が生成されている。
【０１６５】
ここで処理中に条件分岐がある場合、条件分岐の後に続く命令列は、分岐条件により、実行されるか否かが実行時まで不明である。従って、ハードウェアによるチェックサム検証では、条件分岐命令の実行時に自動的にチェックサム検証が行われる場合がある。このとき、条件分岐をまたぐ範囲を耐タンパコード挿入処理の対象範囲、すなわちチェックサム検証の対象範囲として指定すると、チェックサムの検証時にエラーとなってしまう。
【０１６６】
図４３は、耐タンパコード挿入処理の対象範囲として条件分岐命令をまたぐ範囲を指定したソースプログラム１０６の例と、当該ソースプログラム１０６のコンパイル結果の例を表している。図中、斜字体で記載されている部分は、本実施の形態でのコンパイラ２０１の耐タンパコード挿入処理によって生成された命令列を表している。
【０１６７】
ソースプログラム１０６の行４３０６〜行４３０７は、Ｃ言語による条件分岐処理の例を表しており、ここではif文を使用しているがfor文等でも同様である。この条件分岐処理全体を、行４３０５および行４３０８の#pragmaにて耐タンパコード挿入処理の対象範囲として指定している。この場合、プログラムの実行時に、コンパイル結果における行４３１９の条件分岐処理（BNE）においてハードウェアによって自動的にチェックサム検証が行われ、積算設定値算出の途中での検証となるために結果がエラーとなってしまう。
【０１６８】
そこで、本実施の形態でのコンパイラ２０１では、処理中に条件分岐がある場合でもチェックサム検証が正しく行えるよう、耐タンパコード挿入処理の対象範囲として指定された範囲中に条件分岐が出現する毎に、対象範囲を区切ってチェックサム検証を行うように命令列を自動生成する。図４４は、耐タンパコード挿入処理の対象範囲として条件分岐をまたぐ範囲を指定したソースプログラム１０６の例と、当該ソースプログラム１０６を本実施の形態でのコンパイラ２０１によってコンパイルした結果の例を表している。図中、斜字体で記載されている部分は、本実施の形態でのコンパイラ２０１の耐タンパコード挿入処理によって生成された命令列を表している。
【０１６９】
図４４のコンパイル結果において、行４４１９、行４４２８の分岐命令（BNE、BRA）の出現によって、積算の停止とその時点におけるチェックサム検証がハードウェアにより行われる。従って、そこまででチェックサム検証の対象範囲を区切り、そこから新たに積算を開始するための命令列が生成されている（行４４２１〜行４４２４、行４４３０〜行４４３３）。これにより、ユーザは条件分岐処理を意識することなく耐タンパコード挿入処理の対象範囲を指定することができ、容易にチェックサム検証を行うことが可能となる。
【０１７０】
なお、本実施の形態での言語ツール１０８では、ソースプログラム１０６において耐タンパコード挿入処理の対象範囲、すなわちチェックサム検証の対象範囲を指定する方法として、図４２に示す拡張言語仕様#pragmaにより処理ブロック毎に指定する方法をとっているが、実施の形態１と同様に、コンパイラ起動コマンドに付加するコンパイルオプションによって一括指定する方法をとることも可能である。
【０１７１】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理によって挿入された中間語１０９については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【０１７２】
以上のように、本実施の形態での言語ツール１０８により、ハードウェアによって命令コードのチェックサム検証を行う際のハードウェアの設定や、チェックサム検証のための命令コードの積算開始・終了の指示、対象範囲の積算設定値の自動算出等を行うことによって、チェックサム検証によってプログラムの実行時の誤動作を検出または防止することを可能とする耐タンパ性を持つプログラムを生成することができる。また、このようなユーザが手作業で作成することが難しいプログラムを自動的に生成することができ、耐タンパ性を持つプログラムの開発生産性が向上する。また、本実施の形態での言語ツール１０８によってコンパイルを実行することにより、高級言語で記述された既存のソースプログラムをそのまま耐タンパ性を有するセキュアなプログラムへ移植することも容易となる。
【０１７３】
＜実施の形態７＞
本発明の実施の形態７として、プログラムコードを二重化することによりプログラムの動作誤りを検出する例について説明する。
【０１７４】
前述したように、暗号鍵を推定する誤動作解析アタック対策としては、暗号に応じて処理を二重化することにより２回計算を行い、２回の演算結果が等しくなることを確認する方法などが提案されている。この方法における２回計算は、プログラマーがその都度プログラミングをするか、２つ以上のＣＰＵないし演算装置でそれぞれ計算し、計算結果の出力時にそれぞれが合致するかを確かめる方法で実現されてきており、プログラマーが新たにプログラムをするか、２回計算に適したハードウェアを用意する方法が主流であった。
【０１７５】
二重化処理を用いることでプログラムの動作誤りを検出する方法で、特にプログラムの動作系を二重化するハードウェアの構成を用いず、既存の単一処理系を前提としたハードウェア上で実現する方法としては、実行されるプログラムを二重化することが合理的と考えられる。プログラムの二重化の対象としてはプログラムコードが考えられる。ここで、プログラムコードとは、プログラム言語で記述されたソースプログラムや、コンパイラを介して生成される中間語やアセンブリ言語プログラムや機械語である。
【０１７６】
しかしながら、プログラムコードの二重化処理を用いることでプログラムの動作誤りを検出することは行われていない。それは、ソフトウェアの多重化自体が、プログラムの処理速度やメモリ使用効率の面で不利となることから、重要視されていなかったことに起因する。また、二重化処理を用いることでプログラムの動作誤りを検出する場合、二重化されたプログラムの実行後に一重目と二重目の計算結果の比較を行う必要があるが、一重目の演算中に演算処理で必要な変数が更新されることがあり、かかる場合には二重目の演算を正しく行うことができないから、結果として一重目と二重目の計算結果の比較が困難となることが考えられる。
【０１７７】
そこで、本実施の形態では、プログラムコードを二重化した機械語の命令列を自動的に生成することにより、プログラムの動作誤りを検出する。プログラム動作誤り検出のための機能を追加する耐タンパコード挿入処理には、ソースプログラム中の予め指定された第１命令の二重化にかかる第２命令のコードを生成する第１機能と、前記第１命令の実行結果と、前記第２命令の実行結果とを比較するための比較処理のコードを生成する第２機能と、前記比較処理の結果が不一致とされた場合にプログラム実行を停止させるためのエラー処理コードを生成する第３機能とが含まれる。
【０１７８】
さらに本実施の形態での耐タンパコード挿入処理には、前記第１命令の実行で用いられる変数と、その変数の他処理との関連を依存解析するためのコードを生成する第４機能と、前記第４機能の解析結果に基づいて、前記第２命令の実行に必要とされる変数を含む情報の複製を得るためのコードを生成する第５機能とが含まれる。そして前記依存処理では、後述する依存解析の深さを示す解析シンボルが用いられる。
【０１７９】
以下に、本実施の形態での言語ツールの具体的な内容について説明する。本実施の形態での言語ツールが稼動する情報処理装置の例を示した構成図は図１と同じである。図４５は、本実施の形態での言語ツール１０８の構成と処理概要の例を表した図である。図２で示した言語ツール１０８の構成に追加して、言語ツール１０８への入力として、ソースプログラム１０６とともに解析シンボル４５０１が入力されるようになっている。その他の構成は図２で示した構成と同じである。本実施の形態での言語ツール１０８が生成した実行可能プログラム１０７を動作させるターゲットマイコン２０８の例を示した構成図は図３と同じである。また、本実施の形態でのコンパイラ２０１での処理の流れの例は図４と同じである。
【０１８０】
図４のステップ４０５の耐タンパコード挿入処理によって、プログラムコードの二重化がどのように行われるかを、簡単な例を挙げて説明する。図４６は、一般的なソースプログラム１０６での処理の流れの例を表した図である。プログラムコードは、少なくとも制御フローにおける命令処理単位を境界として分割した単位であるので、スタート（Ｓｔａｒｔ）４６０１と命令処理（１）４６０２が分割の１つであるプログラムコード（１）４６１１とされ、命令処理（２）４６０３と命令処理（３）４６０４とが分割の１つであるプログラムコード（２）４６２１とされ、命令処理（４）４６０５とエンド（Ｅｎｄ）４６０６とが分割の１つであるプログラムコード（３）４６３１とされる。
【０１８１】
図４７は、図４６のソースプログラム１０６を入力として本実施の形態での言語ツール１０８によって得られた実行可能プログラム１０７での処理の流れの例を表した図である。図４７の例では、ユーザにより二重化を行う対象として指定されたプログラムコード（２）４６２１が二重化処理されている。すなわち、命令処理（２）４６０３及び命令処理（３）４６０４が二重化され、二重命令処理（１）４７０２及び二重命令処理（２）４７０３が挿入されている。
【０１８２】
また、プログラムコード（２）４６２１において、命令処理（２）４６０３の前に変数コピー処理４７０１が挿入される。変数コピー処理４７０１では、命令処理（２）４６０３で用いられる変数と、命令処理（３）４６０４で用いられる変数とが、互いに異なる記憶領域にコピーされる。例えば命令処理（２）４６０３で用いられる変数が第１記憶領域にコピーされ、命令処理（３）４６０４で用いられる変数が第２記憶領域にコピーされる。このような変数コピー処理４７０１により変数の複製が得られる。さらに、この変数コピー処理４７０１において、命令処理（２）４６０３と、命令処理（３）４６０４とで書き換わる変数があるか否かを命令処理の記述から判定し、書き換わる変数にはフラグが立てられる。
【０１８３】
そして、前記変数コピー処理４７０１の後に、命令処理（２）４６０３と、命令処理（３）４６０４とが挿入される。その後、命令処理（２）４６０３と論理的にもしくは数学的に同値となる二重命令処理（１）４７０２が挿入され、さらに、命令処理（３）４６０４と論理的にもしくは数学的に同値となる二重命令処理（２）４７０３が挿入される。二重命令処理（１）４７０２では、前記第１記憶領域にコピーされた変数が参照され、二重命令処理（２）４７０３では、前記第２記憶領域にコピーされた変数が用いられる。
【０１８４】
前記二重命令処理（２）４７０３の後に比較処理４６０４が挿入される。この比較処理４７０４では、前記フラグが立てられた変数が、命令処理（２）４６０３と、二重命令処理（１）４７０２の実行や、命令処理（３）４６０４と、二重命令処理（２）４７０３の実行により、書き換わったか否かの判別が行われる。そして、前記比較処理４７０４において、前記フラグが立てられた変数が一つでも書き換えられていると判断された場合には、プログラム実行停止のためのエラー処理４７０５に遷移する。前記比較処理４７０４において、変数の書き換えが行われていないと判断された場合には、プログラムコード（３）４６３１の命令処理（４）４６０５に遷移するようになっている。
【０１８５】
前記の例によれば、命令処理（２）４６０３もしくは命令処理（３）４６０４の処理中にハードウェア誤動作が発生し、記憶領域のデータが予想しない値に変化されるか、あるいは処理そのものを誤ったとしても、二重命令処理（１）４７０２もしくは二重命令処理（２）４７０３の実行により、それぞれ同値となる処理が行われることから、二重命令処理（１）４７０２もしくは二重命令処理（２）４７０３の実行で同一のハードウェア誤動作が起きない限り、比較処理４７０４において、プログラムの動作誤りを検知することができる。
【０１８６】
次に、前記二重化処理についてさらに詳細に説明する。図４８は、前記二重化処理についての具体例を示した図である。プログラムコード４８２１、４８３１、４８４１を含むソースプログラム１０６が言語ツール１０８に入力され、プログラムコード４８３１についての二重化処理が指定された場合には、プログラムコード４８１１において、命令処理４８０２の前に変数コピー処理４８０１が挿入される。
【０１８７】
ここでは、変数f、e、gの複製f'、e'、g'が得られる。命令処理４８０２で用いられる変数e、f、gの複製e'、f'、g'が第１記憶領域にコピーされ、命令処理４８０３で用いられる変数g、e、fの複製g'、e'、f'が第２記憶領域にコピーされる。命令処理４８０２の二重化にかかる二重化命令処理４８０４により、「e'=f'*g'」の演算処理が行われ、命令処理４８０３の二重化にかかる二重化命令処理４８０５により、「g'=e'+f'」の演算処理が行われる。
【０１８８】
比較処理４８０６では、変数e、f、gと、その複製e'、f'、g'との比較が行われる。この比較結果に基づいて、全ての変数が一致しない限り、プログラム実行停止のためのエラー処理４８０７に遷移する。
【０１８９】
なお、プログラムコード４８３１に対して二重化処理を行うためのユーザの指示は、例えば、実施の形態１での言語ツール１０８のように、拡張言語仕様#pragmaを用いて指定する方法や、コンパイラ２０１に対するコンパイラオプションによって指定する方法などを用いることができる。
【０１９０】
また、実施の形態１と同様に、図４のステップ４０７の最適化処理では、耐タンパコード挿入処理によって挿入された命令についての中間語１０９については、冗長な命令であるとして削除したり変形したりしないようにし、挿入された耐タンパコードが最適化処理においても保存されるようにする。
【０１９１】
ソースプログラム１０６において処理の実行に用いられる変数と、その変数の他処理との関連を解析する前記依存解析の深さは、ソースプログラム１０６とともに言語ツール１０８に入力される解析シンボル４５０１によって指定することができる。
【０１９２】
例えば図４９に示されるように、対象となるソースプログラム１０６が命令処理４９０２〜４９０８を含む場合を考える。かかる場合において、変数Gについて浅い依存解析４９０９が指定された場合には、依存範囲４９１０が変数E、Fのみに限定される。それに対して、変数Gについて深い依存解析４９１１が指定された場合には、依存範囲４９１２が変数A、B、C、D、E、Fにまで拡げられる。依存解析の深さが深いほど解析精度は向上するが、情報量が多くなるため解析に時間がかかる。依存解析の深さは、対象となるソースプログラム１０６に応じて適宜指定するのが望ましい。
【０１９３】
以上のように、本実施の形態によれば、以下の作用効果を得ることができる。
【０１９４】
（１）言語ツール１０８を実行する情報処理装置により生成された実行可能プログラム１０７を実行するターゲットマイコン２０８によれば、二重化処理を行うプログラムコードの実行直前において、プログラムコードがアクセスする記憶領域中の変数が記憶領域中の別領域に二重化される。特に、プログラムコード中の変数の依存解析を行うことで、効率的な変数の二重化が実現可能である。この二重化された変数を用いて、二重化対象となるプログラムコードで一重目のプログラムコードによる計算が行われ、二重目のプログラムコードでは二重化を行った変数を用いて二重目の計算が行われる。一重目の計算で変数の値や情報が更新されていたとしても、二重目の処理で用いる変数は一重目の計算を行う前に別領域に二重化されたものであることから、一重目の計算による更新に影響されない。この結果、一重目と二重目の処理ではそれぞれ同一の計算処理が行うことができる。これらを踏まえて一重目と二重目の計算を順次実行した後に、一重目と二重目の計算によって更新された変数を比較することで、計算処理中に起きた誤動作の検知を容易に行うことができる。
【０１９５】
（２）前記（１）の作用効果を発揮する実行可能プログラム１０７は、言語ツール１０８を実行する情報処理装置でのコンパイル処理において自動的に生成されるため、ソースプログラム１０６に対する二重化処理をプログラマーが行わずに済む。
【０１９６】
（３）図４７における変数コピー処理４７０１において、命令処理（２）４６０３と、命令処理（３）４６０４とで書き換わる変数があるか否かが命令処理の記述から判定され、書き換わる変数にはフラグが立てられる。そして、比較処理４７０４では、前記フラグが立てられた変数が、命令処理（２）４６０３と、二重命令処理（１）４７０２の実行や、命令処理（３）４６０４と、二重命令処理（２）４７０３の実行により、書き換わったか否かの判別が行われる。このように比較処理４７０４において前記フラグが立てられた変数のみが比較対象とされるので、全ての変数について比較処理を行う場合に比べて、必要な処理を短時間で完了することができる。
【０１９７】
＜実施の形態８＞
本発明の実施の形態８として、プログラムコードを二重化することによりプログラムの動作誤りを検出する別の構成例について説明する。
【０１９８】
図５０に示されるターゲットマイコン５０００は、特に制限されないが、ＩＣカード３１０に搭載されるＩＣカード用マイコンとされ、特に制限されないが、記憶装置５００５、命令解釈実行装置５００７、二重化データ用記憶装置５００８、および演算器５００９を含み、それらがバス５００６により、相互に信号のやり取りが可能に結合される。そして、ターゲットマイコン５０００は、特に制限されないが、公知の半導体集積回路製造技術により、単結晶シリコン基板などの一つの半導体基板に形成される。
【０１９９】
前記記憶装置５００５には、データ領域（１）５００１、データ領域（２）５００２、命令列領域５００３、二重化処理命令列領域５００４が形成される。プログラム動作誤りを検出したい命令列は、記憶装置５００５内の命令列領域５００３に格納されている。命令列領域５００３の命令列の一部には、プログラム動作誤り検出を行いたい命令であることを示すマークが付されている。このマークがトリガとなって命令の二重化処理が行われる。
【０２００】
命令解釈実行装置５００７は、いわゆるＣＰＵとされ、バス５００６を介して、命令列領域５００３の命令を順次フェッチし、それを解釈して実行する。この命令実行結果は、データ領域（１）５００１に格納される。このとき、データ領域（１）５００１は結果を格納するだけでなく、命令解釈実行装置５００７がデータを参照する為に使われることもある。
【０２０１】
プログラム動作誤り検出を行いたい命令であることを示すマークが付された命令がフェッチされた場合、当該命令を実行する前に、二重化処理命令列領域５００４の二重化処理命令列の実行に遷移される。命令解釈実行装置５００７は、前記二重化処理命令列に従い、二重化対象となる命令を命令列領域５００３から読み出し、当該命令実行において用いられる、データ領域（１）５００１内のデータをデータ領域（２）５００２にコピーし、その後に、プログラム動作誤り検出を行いたい命令であることを示すマークが付された命令（先にフェッチした命令）を実行する。このとき、命令解釈実行装置５００７は、データ領域（１）５００１のデータを参照することもある。
【０２０２】
プログラム動作誤り検出を行いたい命令であることを示すマークが付された命令の実行結果は、二重化データ用記憶装置５００８に書き込まれる。その後に、命令解釈実行装置５００７は、前記マークが付された命令と同一命令若しくはそれと等価な命令を実行する。結果的に前記マークが付された命令が複数回実行される。このとき、命令解釈実行装置５００７は、参照すべきデータがある場合には、データ領域（１）５００１ではなく、必ずデータ領域（２）５００２を参照する。そして前記マークが付された命令と同様の命令の実行結果は、二重化データ用記憶装置５００８における未使用領域に書き込まれる。
【０２０３】
その後、命令解釈実行装置５００７は、演算器５００９の動作を制御して、二重化データ用記憶装置５００８内の２つの命令実行結果を比較する。この結果が一致しない場合、演算器５００９は、制御信号Ｓｉｇｎａｌ５０１０をアサートする。これにより、命令解釈実行装置５００７は、プログラム実行を停止させるためのエラー処理に遷移され、そのエラー処理が行われることで、それ以降のプログラム実行が停止される。また、二重化データ用記憶装置５００８内の２つの命令実行結果が一致する場合には、命令列領域５００３から次の命令がフェッチされる。そして、前記マークが付されていない命令がフェッチされた場合には、命令解釈実行装置５００７による前記二重化処理は行われない。
【０２０４】
前記の構成によれば、命令列領域５００３の命令列において、プログラム動作誤り検出を行いたい命令であることを示すマークが付されていれば良いので、命令列領域５００３の命令列は、図４５〜図４９に示した場合のように、言語ツール１０８において、プログラム動作誤り検出のための機能をソースプログラム１０６や中間語１０９などに追加する処理が不要とされる。換言すれば、既存の実行可能プログラム１０７の命令列に対してマークを付することによって、再コンパイルなどをしなくても、プログラムコードの二重化処理を用いることでプログラムの動作誤りを検出することができる。
【０２０５】
さらに、例えば、図５０に示される構成では、命令列領域５００３の命令列の一部には、プログラム動作誤り検出を行いたい命令であることを示すマークが付され、このマークがトリガとなって命令の二重化処理が行われるようにしたが、記憶装置５００５内に二重化処理タイミングを決定するためのデータを格納しておき、このデータに基づいて、対応するタイミングで二重化処理を行うようにしても良い。かかる場合には、命令列領域５００３の命令列の一部にプログラム動作誤り検出を行いたい命令であることを示すマークを付する必要が無い。
【０２０６】
以上に説明した各実施の形態において、前記ターゲットマイコン２０８、５０００は、ＩＣカード以外にも適用することができる。また、言語ツール１０８における耐タンパコード挿入処理は、図２０で示した例のように、それぞれを任意に組み合わせて用いることも可能である。
【０２０７】
また、以上の説明では、主として本発明者によってなされた発明をその背景となった利用分野であるコンパイラ２０１を有する言語ツール１０８に適用した場合について説明したが、本発明はそれに限定されるものではない。少なくともソースプログラム１０６を実行可能プログラム１０７に変換することを条件に適用することができ、ソースプログラム１０６を実行可能プログラム１０７に変換するための処理をコンピュータによって実現するための形式変換プログラムに広く適用することができる。
【０２０８】
以上、本発明者によってなされた発明を実施の形態に基づき具体的に説明したが、本発明は前記実施の形態に限定されるものではなく、その要旨を逸脱しない範囲で種々変更可能であることはいうまでもない。
【産業上の利用可能性】
【０２０９】
本発明のプログラム作成方法は、ＩＣカード等の情報処理装置や組込みシステムに搭載する耐タンパ性を持つセキュアなプログラムの作成方法に利用可能である。また当該プログラムを搭載するＩＣカード等のセキュリティ用途向けのマイコンなどにも利用可能である。
【図面の簡単な説明】
【０２１０】
【図１】本発明の実施の形態１での言語ツールが稼動する情報処理装置の例を示した構成図である。
【図２】本発明の実施の形態１での言語ツールの構成と処理概要の例を表した図である。
【図３】本発明の実施の形態１での言語ツールが生成した実行可能プログラムを動作させるターゲットマイコンの例を示した構成図である。
【図４】本発明の実施の形態１でのコンパイラでの処理の流れの例を示したフローチャートである。
【図５】本発明の実施の形態１でのコンパイラへの入力となるソースプログラムの例である。
【図６】本発明の実施の形態１でのコンパイラにより生成される耐タンパコード挿入処理を行う前の中間語の例を示した図である。
【図７】本発明の実施の形態１でのコンパイラにおける耐タンパコード挿入処理の詳細な例を表すフローチャートである。
【図８】本発明の実施の形態１でのコンパイラによって耐タンパコード挿入処理を行った後の中間語の例を示した図である。
【図９】従来技術のコンパイラの出力するアセンブリ言語プログラムの例を示した図である。
【図１０】本発明の実施の形態１でのコンパイラが出力するアセンブリ言語プログラムの例を示した図である。
【図１１】本発明の実施の形態１でのコンパイラにおける耐タンパコードを挿入する関数をコンパイルオプションによって指定する例を示した図である。
【図１２】本発明の実施の形態１でのコンパイラにおいて耐タンパコードの挿入をさらに細かい粒度で指定する例を示した図である。
【図１３】本発明の実施の形態２でのコンパイラへの入力となるソースプログラムの例を示した図である。
【図１４】本発明の実施の形態２でのコンパイラにより生成される、耐タンパコード挿入処理を行う前の中間語の例を示した図である。
【図１５】本発明の実施の形態２でのコンパイラにおける、耐タンパコード挿入処理の詳細な例を表すフローチャートである。
【図１６】本発明の実施の形態２でのコンパイラによって耐タンパコード挿入処理を行った後の中間語の例を示した図である。
【図１７】従来技術のコンパイラの出力するアセンブリ言語プログラムの例を示した図である。
【図１８】本発明の実施の形態２でのコンパイラが出力するアセンブリ言語プログラムの例を示した図である。
【図１９】本発明の実施の形態２でのコンパイラにおいて、分岐条件を反転させずに連続して行うようなコードを生成したときの例を示した図である。
【図２０】本発明の実施の形態２でのコンパイラにおいて、さらに実施の形態１での多重条件分岐の分岐経路検証を行うコードを挿入する処理を組み合わせた場合に出力されるアセンブリ言語プログラムの例を示した図である。
【図２１】本発明の実施の形態３でのコンパイラへの入力となるソースプログラムの例を示した図である。
【図２２】本発明の実施の形態３でのコンパイラにより生成される、耐タンパコード挿入処理を行う前の中間語の例を示した図である。
【図２３】本発明の実施の形態３でのコンパイラにおける、耐タンパコード挿入処理の詳細な例を表すフローチャートである。
【図２４】本発明の実施の形態３でのコンパイラによって耐タンパコード挿入処理を行った後の中間語の例を示した図である。
【図２５】従来技術のコンパイラの出力するアセンブリ言語プログラムの例を示した図である。
【図２６】本発明の実施の形態３でのコンパイラが出力するアセンブリ言語プログラムの例を示した図である。
【図２７】ループ処理を記述したＣ言語のソースプログラムの例である。
【図２８】図２７のソースプログラムを従来の言語ツールにてコンパイルした結果をアセンブラ記述により表した例である。
【図２９】図２８のプログラムを実行した場合の処理順序の例を表した図である。
【図３０】図２７のソースプログラムについて、ループ処理を複雑化させてコンパイルした結果をアセンブラ記述により表した例である。
【図３１】図３０のプログラムを実行した場合の処理順序の例を表した図である。
【図３２】本発明の実施の形態４での言語ツールによってループ処理を複数パターンの命令列に展開する場合のコード生成例を表した図である。
【図３３】本発明の実施の形態４での言語ツールにおけるソースプログラムを記述する場合の拡張言語仕様による書式の例である。
【図３４】本発明の実施の形態４での言語ツールにおいて、判定値のテーブルまたはそれに相当するものを利用して判定値を更新してループ処理を複雑化した場合の例を表した図である。
【図３５】本発明の実施の形態４での言語ツールにおいて、レジスタの設定値を利用して判定値を更新してループ処理を複雑化した場合の例を表した図である。
【図３６】条件分岐処理を記述したＣ言語のソースプログラムの例である。
【図３７】図３６のソースプログラムを従来の言語ツールにてコンパイルした結果をアセンブラ記述により表した例である。
【図３８】Ｃ言語により条件分岐処理を記述したソースプログラムの例と、当該ソースプログラムを従来のコンパイラによりコンパイルした結果の例と、本発明の実施の形態５でのコンパイラによってコンパイルした結果の例を表している。
【図３９】本発明の実施の形態５での言語ツールにおけるソースプログラムを記述する場合の拡張言語仕様による書式の例である。
【図４０】else節を有しないif文を記述したソースプログラムの例と、当該ソースプログラムを従来のコンパイラによりコンパイルした結果の例と、本発明の実施の形態５でのコンパイラによってコンパイルした結果の例を表している。
【図４１】チェックサム検証を行うための指示を記述したソースプログラムの例と、当該ソースプログラムを本発明の実施の形態６でのコンパイラによってコンパイルした結果の例を表している。
【図４２】本発明の実施の形態６での言語ツールにおけるソースプログラムを記述する場合の拡張言語仕様による書式の例である。
【図４３】条件分岐をまたぐ範囲を指定したソースプログラムの例と、当該ソースプログラムのコンパイル結果の例である。
【図４４】条件分岐をまたぐ範囲を指定したソースプログラムの例と、当該ソースプログラムを本発明の実施の形態６でのコンパイラによってコンパイルした結果の例である。
【図４５】本発明の実施の形態７での言語ツールの構成と処理概要の例を表した図である。
【図４６】一般的なソースプログラムでの処理の流れの例を表した図である。
【図４７】本発明の実施の形態７での言語ツールによって得られた実行可能プログラムでの処理の流れの例を表した図である。
【図４８】本発明の実施の形態７での二重化処理についての具体例を示した図である。
【図４９】本発明の実施の形態７での依存解析の深さについて説明する図である。
【図５０】本発明の実施の形態８での実行可能プログラムを動作させるターゲットマイコンの例を示した構成図である。
【符号の説明】
【０２１１】
１０１…ＣＰＵ、１０２…ディスプレイ、１０３…入出力デバイス、１０４…主記憶装置、１０５…外部記憶装置、１０６…ソースプログラム、１０７…実行可能プログラム、１０８…言語ツール、１０９…中間語、
２０１…コンパイラ、２０２…フロントエンド、２０３…バックエンド、２０４…アセンブラ、２０５…リンケージエディタ、２０６…アセンブリ言語プログラム、２０７…機械語プログラム、２０８…ターゲットマイコン、
３０１…不揮発性メモリ、３０２…プログラム格納領域、３０３…データ格納領域、３０４…揮発性メモリ、３０５…入出力部、３０６…コプロセッサ、３０７…ＣＰＵ、３０８…暗号専用回路、３０９…バス、３１０…ＩＣカード、３１１…外部端子、
４５０１…解析シンボル、
５０００…ターゲットマイコン、５００１…データ領域（１）、５００２…データ領域（２）、５００３…命令列領域、５００４…二重化処理命令列領域、５００５…記憶装置、５００６…バス、５００７…命令解釈実行装置、５００８…二重化データ用記憶装置、５００９…演算器、５０１０…制御信号Ｓｉｇｎａｌ。
【図１】
2009009537.tif 000003
【図２】
2009009537.tif 000004
【図３】
2009009537.tif 000005
【図４】
2009009537.tif 000006
【図５】
2009009537.tif 000007
【図６】
2009009537.tif 000008
【図７】
2009009537.tif 000009
【図８】
2009009537.tif 000010
【図９】
2009009537.tif 000011
【図１０】
2009009537.tif 000012
【図１１】
2009009537.tif 000013
【図１２】
2009009537.tif 000014
【図１３】
2009009537.tif 000015
【図１４】
2009009537.tif 000016
【図１５】
2009009537.tif 000017
【図１６】
2009009537.tif 000018
【図１７】
2009009537.tif 000019
【図１８】
2009009537.tif 000020
【図１９】
2009009537.tif 000021
【図２０】
2009009537.tif 000022
【図２１】
2009009537.tif 000023
【図２２】
2009009537.tif 000024
【図２３】
2009009537.tif 000025
【図２４】
2009009537.tif 000026
【図２５】
2009009537.tif 000027
【図２６】
2009009537.tif 000028
【図２７】
2009009537.tif 000029
【図２８】
2009009537.tif 000030
【図２９】
2009009537.tif 000031
【図３０】
2009009537.tif 000032
【図３１】
2009009537.tif 000033
【図３２】
2009009537.tif 000034
【図３３】
2009009537.tif 000035
【図３４】
2009009537.tif 000036
【図３５】
2009009537.tif 000037
【図３６】
2009009537.tif 000038
【図３７】
2009009537.tif 000039
【図３８】
2009009537.tif 000040
【図３９】
2009009537.tif 000041
【図４０】
2009009537.tif 000042
【図４１】
2009009537.tif 000043
【図４２】
2009009537.tif 000044
【図４３】
2009009537.tif 000045
【図４４】
2009009537.tif 000046
【図４５】
2009009537.tif 000047
【図４６】
2009009537.tif 000048
【図４７】
2009009537.tif 000049
【図４８】
2009009537.tif 000050
【図４９】
2009009537.tif 000051
【図５０】
2009009537.tif 000052