例外1 SMC

まずSMCコールです。SMCコールによってSecure Monitorにハンドリングを移すことができます。

例外に関しては非同期例外と同期例外に分かれていて、非同期例外は命令実行により発生しない例外になります。例えばNormal Priority InterruptとかFast Interruptが非同期例外に当たります。

一方、同期例外は命令実行によって発生する例外です。SVC命令・HVC命令とかがそれぞれ「EL0からEL1に例外を渡すとき」「EL1からEL2に例外を渡すとき」になっていて、今回のSMC命令もEL3に例外を渡すものになっています。

そういった例外のハンドラの決定というものが例外ベクタテーブルで決定されていまして。例えばAArch64のSMC命令を実行するとなったときは、このVBAR_EL3の、ここのオフセットで指定されている部分の同期の例外命令というものの実行を行なうことによって、実際のハンドラの命令が決定されます。

例外に関わる代表的なレジスタをいくつかここでまとめています。重要なものが黒字に書いてあるんですけれども、Secure Configuration Register(SCR)ということで、どの例外をEL3にルーティングするべきか指定するかたちになります。ここでかなり重要になるNS bitというものもここで指定されます。

Saved Program Status Register(SPSR)というものが、例外の処理後に戻る実行状態とか例外のレベルの保持とかっていうものも、厳密にはPSTATEの保持になるんですけれども、ここのレジスタで行なわれます。

あとは、ELRの部分で例外の処理後に戻るアドレスの保持。ESRで例外理由に関わるもの。Vector Base Address Register(VBAR)の部分では、それぞれの先ほど出てきた例外レベルのベクタアドレスのベース仮想アドレスの部分の指定を、このレジスタで行なっています。

例外2 NS Bit

(スライドを示し)ここのNS bitですね。Secure Configuration Registerの部分になるんですけれども、一番この末端の部分って、NS bitが1の場合だとNormalステートで現在の処理が実行されていることになります。逆にNSが0の場合だとSecureステートの状態で実行されていることになります。

ここのNS bitの変更がEL3の権限でしかできないから、さっきのここ(スライド14ページ)の(2)のNS bitの更新がここのSecure Monitorの部分のみで行なわれていることが保証されています。なので、ここのHypervisorのところからいきなりTrusted OSに矢印が生えたりはできないようになっています。

ここまでが全体像の流れになっていて、SMCでSecure Monitorに渡して、NS bit更新して、Normalレジスタの状態の記録とか、あるいはそれの復元とかを行なってERETで最後に渡すという流れになっています。

MMU

次に、TrustZoneにおけるMMU・SoC・Secure Bootの全体像をザーッと紹介していきたいと思います。

MMU、先ほどの発表でいろいろお話があったと思います。変換テーブルのそれぞれのやりとりに対してメモリの属性を指定していて、いろいろ指定するBitやFlagがありますが、とくにここにも、Security Bit、NS bitがあります。これがまた1だったらNormalだし、0だったらSecureというかたちになって、この5-bitの部分に指定されることになっています。

ここのエントリのアドレス変換のときにエントリのNS bitの部分が、仮想メモリのページをNormalかあるいはSecureか、どちらの物理メモリの空間にマッピングするかコントロールしています。

なので、ここの変換テーブルのSecureのEL1とかEL0のメモリを物理アドレスにマッピングするときに、NS=0だったらSecureなアドレス空間にマッピングしますし、逆にNSが1に指定されている場合だとNon-secureなほうのアドレス空間に記録されます。

逆にNon-secureのほうはすべてNon-secureな物理空間にマッピングされて、Non-secureが逆にSecureに矢印が生えたりということはできないようになっています。

SoC

ここまでがMMUとかプロセッサの中身の話でしたが、当然SoCとして全体的にはそれだけではありません。それぞれ全体にSecureとか、あるいはそれを設定可能であったり、あるいはNon-secureとかがNS bitによって指定されていることになっています。

例えばTrusted RAMとかがありますし、逆にNon-trusted RAMとかが存在したりとか、あるいはTrusted Clockが存在したりとか。あと、先ほどのTrusted Configuration Register、一番重要なレジスタとお伝えしたんですけれども、そこのレジスタがここにあったりとかします。

今回すべてをお伝えすることはできないですけれども、それぞれのハードウェアのコンポーネントによってSecureかNon-secureかを設定することが可能になっています。

ここまでの前提として、Secure MonitorとかTrusted OSといったものが安全であると仮定して話していました。というのも、Secure Monitorがブート時に改ざんされていて何か悪意のある動作をしていたら、今までのすべての前提が崩れてしまいます。それを防ぐためにArmではSecure Bootみたいな、OSの起動時とかにマシンにとって信頼のある署名がされている場合のみローダを実行することによって、そこのイメージの改ざん体制というものを防ぐ仕組みが入っています。

その署名のときに使う秘密鍵は、冒頭でお伝えしたTPMなどの秘密鍵を使ってRoot of Trustというかたちで署名をして、起動する部分でその署名の検証を毎回行なうことによって、改ざんされたセキュアモニタとかOSイメージの起動を防ぐことになっています。

(スライドを示し)ここがイメージなんですけれども、もうちょっとArmに特化した部分になるとこういうかたちになっていて、「ARM Trusted Firmware」というOSを含むソフトウェアを安全に起動するための機能群が提供されています。

ここでは、先ほどの図と同じように、右側がTrusted World、左がNormal Worldになっています。実際にブートが起動するときのものが、BL1・BL2で、BL2が起動したもの、そのブートのファームウェアによって、まずBL3 1のSecure Monitorですね、ここのSecure Monitorというものの起動が行なわれて、Trusted OSの部分の起動が行なわ次にNormal OSというものの起動が行なわれて、署名の検証によって、ここで改ざんされていないことをすべて検証されているというプロセスになっています。

OP-TEEとTEEの標準化API

ここまでがハードウェアの話です。次は、実際にTrustZone上でのTEEの実装とか、あるいはまだ脆弱性とかがいろいろ発見されていますので、そこの概要をお伝えしたいと思います。

Open Sourceで公開されているもので一番有名なOP-TEEという実装があります。その実装も、先ほどお伝えしたように、Secure MonitorでRich OSとそのSecure Worldの橋渡しを行なっています。

(スライドを示し)ここのユーザー空間から実際にSecure Monitorに渡されるときに、TEEのクライアントのAPIみたいな、GlobalPlatform TEE Client APIみたいな標準化が定義されています。一方で逆にSecure OSからSecureアプリケーションに渡されるときにも、GlobalPlatform TEE Internal APIみたいな、GlobalPlatformというところが標準化しているTEEのAPIが定義されていて、その実装がここの橋渡しになっています。

(スライドを示し)そのAPIの標準化がこれになるんですけれども、TEE Client APIで実際にコンテキストをイニシャライズしたあとに、それをこっちのTEE Internal Core APIで受け取って、それぞれ5つのセッションを開始してそれを受け取って、実際の処理のInvokeCommandを渡してそれをこっちで受け取って、CloseSession、FinalizeContextというかたちで、APIが定義されています。

このTEE Internal Core APIのほうだとこれがマストで実装されていなければならないAPIになっているんですけれども、ほかにも、例えばキャッシュをフラッシュするAPIとか、いろいろ独自のAPIがいろいろ入っています。

TrustZoneの脆弱性

最後にTrustZoneの脆弱性に関する内容も少しお伝えします。今年のIEEEのS&Pで発表されていた「Understanding the Prevailing Security Vulnerabilities in TrustZone-assisted TEE Systems」という論文がかなりまとまっていました。2013年〜2018年に公表されていたCVEから124個の脆弱性を分析している論文になっていて、その脆弱性を大きく3つに分けて分類しています。

Architecturalに関わる部分では、例えばASLRにおけるメモリの保護機能の欠如みたいな、最低限必要な機能の欠如などが原因で脆弱性になってしまう分類。実装の部分でバッファオーバーフローとかによるTrustZoneのソフトウェアの実装に起因する脆弱性。あとは実際のハードウェア由来の振る舞い、サイドチャネル攻撃とかに由来する部分の3つ脆弱性に分けて分類しています。2018年までの攻撃の分析がペーパーでまとまっているので、おすすめです。

では、最後にまとめです。TrustZoneは、Normal WorldとSecure Worldに論理的にリソースを分離することによって、Normal Worldが不正にSecure Worldのリソースにアクセスできないようにすることを目的としています。

その不正アクセスができないようにするのは、NS bitの0か1かに基づいてMMUがコントロールしています。あとは、Secure Monitorなどの改ざんされたイメージの起動を防ぐために、ARM Trusted Firmwareによってシステムソフトウェアの安全な起動が保証されています。

僕の発表は以上です。ありがとうございます。