Arm TrustZone®
Arm TrustZone®技術は、セキュリティのためのシステム・オン・チップ(SOC)およびCPUシステム全体のアプローチです。
Arm TrustZoneはArmv6KZで紹介され、Armv7-AおよびArmv8-Aでもサポートされています。特定のツールをサポートする必要はありません。同様の機能が、Arm TrustZone for Armv8-M (CMSE (Cortex-M Security Extension) とも呼ばれる) として Cortex-M に導入されました。CMSEではツールのサポートは必要ありません。またCMSEを対象とした開発ツールの標準インターフェースがあります。この拡張には、拡張の2 つのモード(セキュアおよび非セキュア)が含まれます。 またメモリの保護、およびメモリアクセスを有効にしたり、2つのモデル間の移行を制御するための命令も追加します。
32ビットモード
Armv8-MにTrustZoneを追加するには、セキュアモード用に1つ、非セキュアモード用に1つの、2 つの別々のイメージをビルドします。セキュアイメージは、非セキュアイメージで使用可能な関数エントリをエクスポートできます。
IARビルドツールは、組み込み関数、リンカオプション、コンパイラオプション、定義済プリプロセッサシンボル、拡張キーワード、およびセクションVeneer$$CMSEによりTrustZoneをサポートします。
ヘッダファイルarm_cmse.hでTrustZoneを使用する際に必要なデータタイプおよびユーティリティ関数を参照することができます。
関数タイプ属性__cmse_nonsecure_callおよび__cmse_nonsecure_entryは、セキュアなコードから非セキュアなコードにコールするとき、使用したレジスタを消去してコードを追加します。
IARビルドツールは、Cortex-Mセキュリティ拡張(CMSE)を目的にした開発ツールの標準インターフェースに従っていますが、次の例外があります。
可変セキュアエントリ関数は使用できません。
レジスタに合わないパラメータまたはリターン値があるセキュアエントリ関数は使用できません。
レジスタに合わないパラメータまたはリターン値での非セキュアなコールは使用できません。
浮動ポイントレジスタのパラメータまたはリターン値の非セキュアなコール。
コンパイラオプション
--cmseにはセキュリティ拡張のArmv8-Mアーキテクチャが必要です。またROPI(読み取り専用位置が独立)イメージまたはRWPI(読み取り書き込み位置が独立)イメージを構築しているときは、サポートされません。
ARM TrustZoneの詳細については、www.arm.comを参照してください。
Armv8-Mセキュリティ拡張(CMSE)を使用した例
arm\src\ARMv8M_Secureディレクトリで、Arm TrustZoneおよびCMSEを実際に使用するプロジェクトの例を見つけることができます。
例は、2つのプロジェクトで構成されます。
hello_s: アプリケーションのセキュアな部分hello_ns: アプリケーションのセキュアではない部分
注記
セキュアでないプロジェクトをビルドする前に、セキュアなプロジェクトをビルドする必要があります。
2つのエントリ関数がhello_sにあります。セキュアでないコール可能なregionのセキュアなゲートウェイを介したhello_nsに使用可能です。
secure_hello: クラシックHello world例のスタイルに挨拶を印刷します。register_secure_goodbye: コールバックは、既存のセキュア部分で印刷した文字列を返します。
リンカは自動的にセキュアゲートウェイに必要なコードを生成し、それをVeneers$$CMSEセクションに配置します。
arm\src\ARMv8M_Secure\Hello_Secure.にあるサンプルプロジェクトのワークスペースhello_s.ewwを開きます。[プロジェクト]>[オプション]>[一般オプション]>[32ビット]を選択して、[TrustZone]および[モードを選択し]、
hello_sプロジェクトをセットアップしセキュアモードで実行します。セキュアモードで実行します。[プロジェクト>[オプション]>[一般オプション]>[32ビット]を選択して、[TrustZone]および[モードを選択し]、
hello_nsプロジェクトをセットアップしセキュアモードで実行します。非セキュアモードで実行します。セキュアでない部分は、
0x200000で初期化ルーチンへのアドレス、セキュアでないスタックのトップ、セキュアでないmainといっしょに小さいベクタを読み込む必要があります。このベクタは、セキュアな部分をセットアップし、セキュアでない部分と通信するために使用されます。この例では、nonsecure_hello.cの次のコードで完了します:/* Interface towards the secure part */ #pragma location=NON_SECURE_ENTRY_TABLE __root const non_secure_init_t init_table = { __iar_data_init3, /* initialization function */ __section_end("CSTACK"), /* non-secure stack */ main_ns /* non-secure main */ };セキュアプロジェクトがビルドされると、リンカは、セキュアでない部分からコールされるセキュアな部分の関数のリファレンスだけが含まれている、セキュアでない部分のインポートライブラリファイルを自動的に生成します。[プロジェクト]>[オプション]>[リンカ]>[出力]>[TrustZone インポートライブラリ]を使用して、このファイルを指定します。
セキュアなプロジェクトをビルドします。
追加ライブラリを指定することで、TrustZoneインポートライブラリファイルを手動で、
hello_nsプロジェクトに含めます: [プロジェクト]>[オプション]>[リンカ]>[ライブラリ]>[追加ライブラリ]。セキュアでないプロジェクトをビルドします。
セキュアなプロジェクトは、セキュアでないプロジェクト出力ファイルをデバッガによりロードされる追加イメージとして指定する必要があります。これを行うには、[プロジェクト]>[オプション]>[デバッガ]>[イメージ]>[追加イメージのダウンロード]を使用します。
シミュレータでデバッグするには、プロジェクトを右クリックし
有効に設定を選択して、有効なプロジェクトとしてhello_sプロジェクトを設定します。[プロジェクト]>[オプション]>[デバッガ]>[ドライバ]を選択し、[シミュレータ]を選択します。
[シミュレータ]>[メモリ構成]を選択します。使用範囲の設定基準ファイルオプションが選択されていないことを確認します。
使用範囲を手動で設定を選択して、次の新しい範囲を追加します。
アクセスタイプ
開始アドレス
終了アドレス
RAM
0x0000'0000
0x003F'FFFF
RAM
0x2000'0000
0x203F'FFFF
SFR
0x4000'0000
0x5FFF'FFFF
SFR
0xE000'0000
0xE00F'FFFF
表90 TrustZone例のメモリ範囲OKをクリックして、[ブレークポイント]ダイアログボックスを閉じます。
[プロジェクト]>[ダウンロードしてデバッグ]を選択して、C-SPYを開始します。
[表示]>[ターミナル I/O]を選択して[ターミナル I/O]ウィンドウを開きます。
[デバッグ]>[移動]を選択して、実行を開始します。
ターミナル I/Oウィンドウは、この文字を印刷します。
Hello from secure World! Hello from non-secure World! Goodbye, for now.