6.1.1. Arm TrustZone と TEE の活用
Linux を利用するシステムでは、自社開発したソフトウェアだけでなく複数の OSS が導入されるケースがあります。このような状況下では、自社開発したタスクだけでなく、同時にOSSのタスクが実行されることになり、システムのどこかに悪意のあるコードが含まれるのか、その可能性を排除することは困難です。仮にすべての OSS が信頼できるものであったとしても、不具合がないことを保証することはほぼ不可能であり、結局のところどのソフトウェアが脆弱性のきっかけになるかは分からないのです。
そういった背景から Arm は TrustZone 技術を導入しました。リソースアクセス制限によって敵対的なソフトウェアからソフトウェア実行環境を隔離することができます。TrustZone の導入によって、自社開発以外のソフトウェアが多数動作する状況においても、通常はセキュアワールドにその影響が及びません。TrustZone を利用したものとして、GlobalPlatform の TEE (Trusted Execution Environment) を実現するソフトウェアがいくつか存在します。TEE を活用すると secure world において信頼できるソフトウェアだけを実行させることが可能です。
では、どういったケースで TEE を採用するべきでしょうか。一概には言えませんが、情報資産とその資産を処理するライブラリなどをまとめて保護するケースで利用することが考えられます。具体的には、電子決済処理、証明書の処理、有料コンテンツの処理、個人情報の処理などで利用するケースが考えられます。
商用、OSS の TEE などいくつかの TEE 実装が存在します。Armadillo Base OS では OP-TEE を採用します。OSS である OP-TEE は Arm コア向け TEE 実装の1つです。Arm TrustZone テクノロジーによって情報資産とその処理をセキュアワールドに隔離して攻撃から保護します。OP-TEE は GlobalPlatform によって定義される TEE Client API や TEE Core API といった GlobalPlatformAPI に準拠したライブラリを提供しています。これらのAPI を利用することでユーザーはカスタムアプリケーションを開発することが可能です。imx-optee-xxx は NXP による i.MX ボートのサポート対応が含まれる OP-TEE の派生プロジェクトです。
| |
---|
OP-TEE の詳しい情報は公式のドキュメントを参照してください。 |
OP-TEE を構成する主要なリポジトリは以下のとおりです。
imx-optee-os
-
セキュアワールドで動作する TEE。optee-os の派生
imx-optee-client
-
TEE を呼び出すためのノンセキュア、セキュアワールド向けの API ライブラリ。optee-client の派生
imx-optee-test
-
OP-TEE の基本動作のテスト、パフォーマンス測定を行う。optee-test の派生。NXP 独自のテストが追加される
optee_examples
このうち、imx- というプレフィックスが付加されるリポジトリは、アップストリームのリポジトリに対して NXP による i.MX シリーズ向けの対応が入ったリポジトリになります。OP-TEE を利用するためには imx-optee-os をブートローダーに配置するだけでなく、Linux 上で動作するコンパニオン環境 (imx-optee-client) が必要です。また、TEE を利用するために CA (Client Application), TA (Trusted Application) を、imx-optee-os と imx-optee-client を用いてビルドします。必要に応じてテスト環境 (imx-optee-test) も追加してください。
| |
---|
OP-TEE git に関する詳しい情報は公式のドキュメントを参照してください。 |
6.2.1. Armadillo Base OS への組み込み
前節で説明した OP-TEE の主要なリポジトリを実際に Armdillo BaseOS に適用する場合、Armadillo Base OS とどのように関係するのか全体像を説明します。
以下が Armadillo Base OS との関係を表した全体像。
-
青色の部分は Armadillo Base OS によってカバーされる範囲
-
赤色の部分は OP-TEE を組み込むために用意しなければならない部分
-
紫色の部分は デフォルトで Armadillo Base OS に組み込まれているが更新が必要な部分
imx-optee-os を組み込む作業は煩雑です。ユーザーの手間を省くために Armadillo Base OS には常に imx-optee-os バイナリがブートローダーに組み込むように実装されています。工場出荷状態イメージや製品アップデート向け Armadillo Base OS イメージにも含まれます。しかし、セキュリティ上の懸念から OP-TEE が利用できる状態で組み込まれていません。詳しくは 「鍵の更新」 で説明します。
6.4. CAAM を活用した TEE を構築する
i.MX 8M Plus には CAAM (Cryptographic Acceleration and Assurance Module) と呼ばれる高機能暗号アクセラレータが搭載されています。CAAM は SoC 内部にあるためセキュアかつ高速に暗号処理を行うことが可能です。
OP-TEE が含まれるブートローダーをビルドしていきます。Armadillo Base OS を利用した OP-TEE のビルドの流れは以下のとおりです。
-
ブートローダーをビルドする
-
imx-optee-client をビルドする
-
TA, CA をビルドする
-
ビルド結果を集める
本マニュアルで説明するビルド環境でのディレクトリ構成の概略は以下のとおりです。
optee_examples はユーザーアプリケーションを配置する場所です。本マニュアルでは Linaro が提供するアプリケーションのサンプルプログラムである optee_examples としました。本来は各ユーザーのアプリケーションを配置する場所になります。
├── imx-boot-[VERSION]
│ ├── imx-atf
│ ├── imx-mkimage
│ ├── imx-optee-os
│ └── uboot-imx
├── imx-optee-client
├── imx-optee-test
├── optee_examples
└── out
製品マニュアルを参考にしてビルド環境の構築と、ブートローダーのソースコードの取得、
ビルドを事前に行ってください。
imx-optee-test をビルドするために必要になります。
[PC ~]$ sudo apt install g++-aarch64-linux-gnu
新しい鍵を取り込むためにブートローダーを再ビルドする必要があります。
| |
---|
uboot-imx の localversion について Armadillo-IoT ゲートウェイ G4 セキュリティガイド 1.1.0 以前では
localversion を利用したバージョン更新を説明していましたが、
SWUpdate の記述ファイル (desc) を利用した方法を推奨します。
localversion との併用は可能です。すでに運用中の方はそのままご利用いただけます。 |
ブートローダーをビルドする
次のコマンドを実行します。
デフォルトの設定ではデフォルトの鍵を利用してしまうので make 引数で鍵のパスを渡す必要があります。「鍵の更新」 で生成した鍵のパスを変数 TA_SIGN_KEY で渡します。ここでは鍵名を rsa4096 としましたが、各ユーザーの環境に合わせた鍵名と読み替えてください。
[PC ~]$ make CFG_CC_OPT_LEVEL=2 \
TA_SIGN_KEY="${PWD}/imx-boot-[VERSION]/imx-optee-os/keys/rsa4096.pem" \
-C imx-boot-[VERSION] imx-boot_armadillo_x2
| |
---|
引数 TA_SIGN_KEY で秘密鍵をわたすことで、ビルド時に TA の署名に利用されます。また、実行時の署名確認のためには公開鍵を取り出して実行バイナリに取り込みます。 |
ビルド結果をコピーしておきます。
[PC ~]$ install -D -t ${PWD}/out/usr/lib/optee_armtz \
-m644 ${PWD}/imx-boot-[VERSION]/imx-optee-os/out/export-ta_arm64/ta/*
6.4.4. imx-optee-client をビルドする
imx-optee-client は TA, CA が利用するライブラリ。アプリケーションをビルドする前にビルド必要がある。
| |
---|
imx-optee-client は imx-optee-os のビルド結果を参照しているので、事前にブートローダーをビルドする必要があります。 |
imx-optee-client をクローンする
imx-boot-[VERSION] のディレクトリと並列に配置されるように imx-optee-client をクローンして、必要に応じて適切なブランチなどをチェックアウトしてください。
[PC ~]$ git clone https://github.com/nxp-imx/imx-optee-client.git \
-b lf-5.10.72_2.2.0
imx-optee-client をビルドする
基本的な情報を参照するために TA_DEV_KIT_DIR を渡します。フォルトのターゲットでインストールも合わせて行うので DESTDIR を渡します。アプリケーションをビルドする際に API ライブラリとして利用されます。
[PC ~]$ make -C imx-optee-client \
DESTDIR="${PWD}/out" \
CROSS_COMPILE="aarch64-linux-gnu-" \
TA_DEV_KIT_DIR="${PWD}/imx-boot-[VERSION]/imx-optee-os/out/export-ta_arm64"
本来はユーザーが独自に作ったアプリケーションをビルドしますが、ここでは参考までにサンプルアプリケーション optee_examples をビルドします。アプリケーション開発の参考にしてください。
| |
---|
-
アプリケーションをビルドするためには imx-optee-os, imx-optee-client のビルド結果を参照しているので、一度は imx-boot-[VERSION], imx-optee-client をビルドする必要があります
-
optee_examples にはインストールする make ターゲットがないので、ビルド後に手動で集める作業が必要があります
|
optee_examples をクローンする
imx-boot-[VERSION] や imx-optee-client ディレクトリと並列に配置されるように optee_examples をクローンして、必要に応じて適切なブランチなどをチェックアウトしてください。
[PC ~]$ git clone https://github.com/linaro-swg/optee_examples.git \
-b 3.15.0
optee_examples をビルドする
基本的な情報を参照するために TA_DEV_KIT_DIR、TA を署名するために TA_SIGN_KEY、ライブラリ参照のために TEEC_EXPORT を渡します。インストールターゲットがないので後ほど手動でビルド結果を収集する必要があります。
[PC ~]$ make -C optee_examples \
TA_CROSS_COMPILE="aarch64-linux-gnu-" \
HOST_CROSS_COMPILE="aarch64-linux-gnu-" \
TA_DEV_KIT_DIR="${PWD}/imx-boot-[VERSION]/imx-optee-os/out/export-ta_arm64" \
TEEC_EXPORT="${PWD}/out/usr" \
TA_SIGN_KEY="$PWD/imx-boot-[VERSION]/imx-optee-os/keys/rsa4096.pem"
ビルド結果をコピーしておきます。
[PC ~]$ install -D -t ${PWD}/out/usr/lib/optee_armtz -m644 ${PWD}/optee_examples/out/ta/*
[PC ~]$ install -D -t ${PWD}/out/usr/bin -m755 ${PWD}/optee_examples/out/ca/*
6.4.6. imx-optee-test をビルドする
imx-optee-test は必ずしも必要ではありません。利用機会は限られますが、OP-TEE の基本動作を確認するため、パフォーマンスを計測するために imx-optee-test を利用することができます。組み込むかどうかの判断はお任せします。
| |
---|
アプリケーションをビルドするためには imx-optee-os, imx-optee-client のビルド結果を参照しているので、一度は imx-boot-[VERSION], imx-optee-client をビルドする必要があります。 |
imx-optee-test をクローンする
imx-boot-[VERSION] や imx-optee-client ディレクトリと並列に配置されるように imx-optee-client をクローンして、必要に応じて適切なブランチなどをチェックアウトしてください。
[PC ~]$ git clone https://github.com/nxp-imx/imx-optee-test.git \
-b lf-5.10.72_2.2.0
imx-optee-test をビルドする
基本的な情報を参照するために TA_DEV_KIT_DIR、TA を署名するために TA_SIGN_KEY、ライブラリ参照のために TEEC_EXPORT を渡します。ビルドとインストールは別のターゲットなのでそれぞれ make を実行する必要があります。
[PC ~]$ CFLAGS=-O2 make -R -C imx-optee-test \
CROSS_COMPILE="aarch64-linux-gnu-" \
TA_DEV_KIT_DIR="${PWD}/imx-boot-[VERSION]/imx-optee-os/out/export-ta_arm64" \
OPTEE_CLIENT_EXPORT="${PWD}/out/usr" \
TA_SIGN_KEY="${PWD}/imx-boot-[VERSION]/imx-optee-os/keys/rsa4096.pem"
インストールします。
[PC ~]$ find imx-optee-test/ -name "*.ta" -exec cp -a {} out/usr/lib/optee_armtz/ \;
[PC ~]$ install -D -t out/usr/bin/ imx-optee-test/out/xtest/xtest
[PC ~]$ install -D -t out/usr/lib/tee-supplicant/plugins/ \
imx-optee-test/out/supp_plugin/*.plugin
| |
---|
本リリース時点では xtest 1014 にてエラーになる問題があります。そのため環境変数で CFLAGS=-O2 を渡しています。make 引数で渡すとヘッダファイルの include 設定がなくなります。
ブートローダーのビルド時に O2 としているのも同様の理由です。 |
imx-optee-os, imx-optee-client の最小構成では以下のとおりです。
out/
|-- lib
| `-- optee_armtz
| |-- 023f8f1a-292a-432b-8fc4-de8471358067.ta
| |-- f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c.ta
| `-- fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta
`-- usr
|-- include
| |-- ck_debug.h
| |-- optee_client_config.mk
| |-- pkcs11.h
| |-- pkcs11_ta.h
| |-- tee_bench.h
| |-- tee_client_api.h
| |-- tee_client_api_extensions.h
| |-- tee_plugin_method.h
| `-- teec_trace.h
|-- lib
| |-- libckteec.a
| |-- libckteec.so -> libckteec.so.0
| |-- libckteec.so.0 -> libckteec.so.0.1
| |-- libckteec.so.0.1 -> libckteec.so.0.1.0
| |-- libckteec.so.0.1.0
| |-- libteec.a
| |-- libteec.so -> libteec.so.1
| |-- libteec.so.1 -> libteec.so.1.0.0
| |-- libteec.so.1.0 -> libteec.so.1.0.0
| `-- libteec.so.1.0.0
`-- sbin
`-- tee-supplicant
|
Dynamic TA。Linux のファイルシステムに保存される
|
|
TEE client API, TEE, internal core API
|
|
Linux 上で動作する OP-TEE の補助的な機能をもつ
|
imx-optee-test, optee_examples を含めたビルド結果は以下のとおりです。
out
`-- usr
|-- bin
| |-- optee_example_acipher
| |-- optee_example_aes
| |-- optee_example_hello_world
| |-- optee_example_hotp
| |-- optee_example_plugins
| |-- optee_example_random
| |-- optee_example_secure_storage
| `-- xtest
|-- include
| |-- ck_debug.h
| |-- optee_client_config.mk
| |-- pkcs11.h
| |-- pkcs11_ta.h
| |-- tee_bench.h
| |-- tee_client_api.h
| |-- tee_client_api_extensions.h
| |-- tee_plugin_method.h
| `-- teec_trace.h
|-- lib
| |-- libckteec.a
| |-- libckteec.so -> libckteec.so.0
| |-- libckteec.so.0 -> libckteec.so.0.1
| |-- libckteec.so.0.1 -> libckteec.so.0.1.0
| |-- libckteec.so.0.1.0
| |-- libteec.a
| |-- libteec.so -> libteec.so.1
| |-- libteec.so.1 -> libteec.so.1.0.0
| |-- libteec.so.1.0 -> libteec.so.1.0.0
| |-- libteec.so.1.0.0
| |-- optee_armtz
| | |-- 023f8f1a-292a-432b-8fc4-de8471358067.ta
| | |-- 2a287631-de1b-4fdd-a55c-b9312e40769a.ta
| | |-- 380231ac-fb99-47ad-a689-9e017eb6e78a.ta
| | |-- 484d4143-2d53-4841-3120-4a6f636b6542.ta
| | |-- 528938ce-fc59-11e8-8eb2-f2801f1b9fd1.ta
| | |-- 5b9e0e40-2636-11e1-ad9e-0002a5d5c51b.ta
| | |-- 5ce0c432-0ab0-40e5-a056-782ca0e6aba2.ta
| | |-- 5dbac793-f574-4871-8ad3-04331ec17f24.ta
| | |-- 614789f2-39c0-4ebf-b235-92b32ac107ed.ta
| | |-- 690d2100-dbe5-11e6-bf26-cec0c932ce01.ta
| | |-- 731e279e-aafb-4575-a771-38caa6f0cca6.ta
| | |-- 873bcd08-c2c3-11e6-a937-d0bf9c45c61c.ta
| | |-- 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
| | |-- a4c04d50-f180-11e8-8eb2-f2801f1b9fd1.ta
| | |-- a734eed9-d6a1-4244-aa50-7c99719e7b7b.ta
| | |-- b3091a65-9751-4784-abf7-0298a7cc35ba.ta
| | |-- b689f2a7-8adf-477a-9f99-32e90c0ad0a2.ta
| | |-- b6c53aba-9669-4668-a7f2-205629d00f86.ta
| | |-- c3f6e2c0-3548-11e1-b86c-0800200c9a66.ta
| | |-- cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.ta
| | |-- d17f73a0-36ef-11e1-984a-0002a5d5c51b.ta
| | |-- e13010e0-2ae1-11e5-896a-0002a5d5c51b.ta
| | |-- e626662e-c0e2-485c-b8c8-09fbce6edf3d.ta
| | |-- e6a33ed4-562b-463a-bb7e-ff5e15a493c8.ta
| | |-- f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c.ta
| | |-- f157cda0-550c-11e5-a6fa-0002a5d5c51b.ta
| | |-- f4e750bb-1437-4fbf-8785-8d3580c34994.ta
| | |-- fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta
| | `-- ffd2bded-ab7d-4988-95ee-e4962fff7154.ta
| `-- tee-supplicant
| `-- plugins
| `-- f07bfc66-958c-4a15-99c0-260e4e7375dd.plugin
`-- sbin
`-- tee-supplicant
ターゲット上のコンテナに展開するために、tarball で固めます。
[PC ~]$ tar -caf optee.tar.gz -C out .
| |
---|
製品マニュアルを参考にしてコンテナ作成の時に組み込むことをお勧めします。 |
SWUpdate 用のファイルをつくり、ターゲットデバイスのブートローダーを更新します。
更新後に debian コンテナを起動して OP-TEE 関連ファイルを展開します。
セットアップの完了後はテストプログラム (xtest) と
サンプルプログラム (optee_example_hello_world) を動作させます。
-
ATDE を立ち上げる
imx-boot_update.desc ファイルをつくる
SWUpdate の記述ファイル (desc) をつくります。
desc ファイルはアットマークテクノ独自の SWUpdate を制御するためのファイルです。
[ATDE ~]$ vi imx-boot_update.desc
以下の例を参考に、path などを変更してください。
# version
swdesc_option version=1
# swdesc_boot <bootfile>
swdesc_boot /path/imx-boot-[VERSION]/imx-boot_armadillo_x2
# swdesc_files [--basedir <basedir>] [--dest <dest>] <file> [<more files>]
swdesc_files --dest optee /path/optee.tar.gz
| |
---|
swdesc_option version=<version> 新しいソフトウェアのバージョンを指定します。
デバイス上のソフトウェアのバージョンより大きな値を設定すると
アップデートが実行されます。
OP-TEE を更新するたびにバージョンを上げてください。
この option を使うと uboot-imx の localversion を利用する必要はありません。 <version>: バージョンには xx.yy.zz や yyyymmdd のフォーマットが利用できます。 |
| |
---|
swdesc_option <bootfile> ブートローダーの更新のために利用します。 bootfile: 書き込むブートローダーを指定します。 |
| |
---|
swdesc_files [--basedir <basedir>] [--dest <dest>] <file> [<more files>] Linux ファイルシステム上のファイルを更新するために利用します。 dest: ファイルの書込み先を指定します。
書き込み先は、/var/app/rollback/volumes 以下に制限されます。 file: 書き込むファイルを指定します。 |
swu ファイルを作成する
以下のコマンドで swu ファイルを作ります。
[ATDE ~]$ mkswu /path/imx-boot_update.desc -o ./update_imx-boot.swu
Enter pass phrase for /home/atmark/mkswu/swupdate.key: (password を入力)
Successfully generated update_imx-boot.swu
SWUpdate を実行する
usb memory などに update_imx-boot.swu をコピーしてターゲットデバイス上で
SWUpdate を実行します。
以下のように armadillo 上で swupdate を実行してください。
アップデートが完了すると、システムは再起動します。
[armadillo ~]# swupdate -i /path/update_imx-boot.swu
Licensed under GPLv2. See source distribution for detailed copyright notices.
[INFO ] : SWUPDATE running : [main] : Running on iot-g4-es2 Revision at1
[INFO ] : SWUPDATE started : Software Update started !
[ 549.345329] exFAT-fs (mmcblk2p2): invalid boot record signature
[ 549.351277] exFAT-fs (mmcblk2p2): failed to read boot sector
[ 549.356956] exFAT-fs (mmcblk2p2): failed to recognize exfat type
[ 549.384407] F2FS-fs (mmcblk2p2): Can't find valid F2FS filesystem in 1th superblock
[ 549.392313] F2FS-fs (mmcblk2p2): Can't find valid F2FS filesystem in 2th superblock
[ 549.470793] exFAT-fs (mmcblk2p2): invalid boot record signature
[ 549.476739] exFAT-fs (mmcblk2p2): failed to read boot sector
[ 549.482478] exFAT-fs (mmcblk2p2): failed to recognize exfat type
[ 549.509020] F2FS-fs (mmcblk2p2): Can't find valid F2FS filesystem in 1th superblock
[ 549.517000] F2FS-fs (mmcblk2p2): Can't find valid F2FS filesystem in 2th superblock
[INFO ] : SWUPDATE running : [read_lines_notify] : No base os update: copying current os over
[INFO ] : SWUPDATE running : [read_lines_notify] : Waiting for btrfs to flush deleted subvolumes
[INFO ] : SWUPDATE running : [read_lines_notify] : Removing unused containers
[INFO ] : SWUPDATE running : [read_lines_notify] : swupdate triggering reboot!
| |
---|
usb memory の root に swu ファイルを置いておくと、
usb 接続時、もしくは、システム起動時に自動的に swupdate が走ります。
アップデートが完了するとシステムは再起動します。 swupdate 中に swupdate を二重起動はできません。
アップデート中はお待ちください。 |
ビルド結果をコンテナに展開する
/var/app/rollback/volumes/ 以下にまとめた tarball がコピーされます。
上記の例では /var/app/rollback/volumes/optee に展開されています。
再起動後にコンテナを起動して tarball をコンテナに展開します。
コンテナを起動します。
/dev/tee0 と /dev/teepriv0 を利用する以外は任意の設定で問題ありません。
[armadillo ~]# podman run -it --name=dev_optee --device=/dev/tee0 \
--device=/dev/teepriv0 -v "$(pwd)":/mnt docker.io/debian /bin/bash
コンテナを起動したらファイルを展開します。
[container ~]# tar xavf /path/optee.tar.gz -C /
./
./lib/
./lib/optee_armtz/
./lib/optee_armtz/b3091a65-9751-4784-abf7-0298a7cc35ba.ta
./lib/optee_armtz/731e279e-aafb-4575-a771-38caa6f0cca6.ta
./lib/optee_armtz/873bcd08-c2c3-11e6-a937-d0bf9c45c61c.ta
./lib/optee_armtz/5b9e0e40-2636-11e1-ad9e-0002a5d5c51b.ta
./lib/optee_armtz/690d2100-dbe5-11e6-bf26-cec0c932ce01.ta
./lib/optee_armtz/528938ce-fc59-11e8-8eb2-f2801f1b9fd1.ta
./lib/optee_armtz/f157cda0-550c-11e5-a6fa-0002a5d5c51b.ta
./lib/optee_armtz/d17f73a0-36ef-11e1-984a-0002a5d5c51b.ta
./lib/optee_armtz/8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
./lib/optee_armtz/c3f6e2c0-3548-11e1-b86c-0800200c9a66.ta
./lib/optee_armtz/f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c.ta
./lib/optee_armtz/b6c53aba-9669-4668-a7f2-205629d00f86.ta
./lib/optee_armtz/a734eed9-d6a1-4244-aa50-7c99719e7b7b.ta
./lib/optee_armtz/380231ac-fb99-47ad-a689-9e017eb6e78a.ta
./lib/optee_armtz/a4c04d50-f180-11e8-8eb2-f2801f1b9fd1.ta
./lib/optee_armtz/5dbac793-f574-4871-8ad3-04331ec17f24.ta
./lib/optee_armtz/023f8f1a-292a-432b-8fc4-de8471358067.ta
./lib/optee_armtz/5ce0c432-0ab0-40e5-a056-782ca0e6aba2.ta
./lib/optee_armtz/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.ta
./lib/optee_armtz/fd02c9da-306c-48c7-a49c-bbd827ae86ee.ta
./lib/optee_armtz/484d4143-2d53-4841-3120-4a6f636b6542.ta
./lib/optee_armtz/f4e750bb-1437-4fbf-8785-8d3580c34994.ta
./lib/optee_armtz/e6a33ed4-562b-463a-bb7e-ff5e15a493c8.ta
./lib/optee_armtz/e13010e0-2ae1-11e5-896a-0002a5d5c51b.ta
./lib/optee_armtz/614789f2-39c0-4ebf-b235-92b32ac107ed.ta
./lib/optee_armtz/25497083-a58a-4fc5-8a72-1ad7b69b8562.ta
./lib/optee_armtz/b689f2a7-8adf-477a-9f99-32e90c0ad0a2.ta
./lib/optee_armtz/2a287631-de1b-4fdd-a55c-b9312e40769a.ta
./lib/optee_armtz/ffd2bded-ab7d-4988-95ee-e4962fff7154.ta
./lib/optee_armtz/e626662e-c0e2-485c-b8c8-09fbce6edf3d.ta
./bin/
./bin/xtest
./usr/
./usr/lib/
./usr/lib/libteec.so.1.0.0
./usr/lib/tee-supplicant/
./usr/lib/tee-supplicant/plugins/
./usr/lib/tee-supplicant/plugins/f07bfc66-958c-4a15-99c0-260e4e7375dd.plugin
./usr/lib/libteec.a
./usr/lib/libteec.so
./usr/lib/libteec.so.1
./usr/lib/libckteec.a
./usr/lib/libteec.so.1.0
./usr/lib/libckteec.so
./usr/lib/libckteec.so.0.1.0
./usr/lib/libckteec.so.0
./usr/lib/libckteec.so.0.1
./usr/bin/
./usr/bin/optee_example_hello_world
./usr/bin/optee_example_acipher
./usr/bin/optee_example_secure_storage
./usr/bin/optee_example_aes
./usr/bin/optee_example_hotp
./usr/bin/optee_example_plugins
./usr/bin/optee_example_random
./usr/include/
./usr/include/pkcs11_ta.h
./usr/include/tee_plugin_method.h
./usr/include/tee_client_api.h
./usr/include/pkcs11.h
./usr/include/tee_bench.h
./usr/include/tee_client_api_extensions.h
./usr/include/ck_debug.h
./usr/include/optee_client_config.mk
./usr/include/teec_trace.h
./usr/sbin/
./usr/sbin/tee-supplicant
tee-supplicant を起動する
[container ~]# tee-supplicant -d
xtest で動作を確認する
xtest で OP-TEE の基本動作を確認します。以下のログは全テストをパスしたログです。
[container ~]# xtest
Run test suite with level=0
TEE test application started over default TEE instance
######################################################
#
# regression+pkcs11+regression_nxp
#
######################################################
* regression_1001 Core self tests
regression_1001 OK
: (省略)
+-----------------------------------------------------
33939 subtests of which 0 failed
114 test cases of which 0 failed
0 test cases were skipped
TEE test application done!
| |
---|
xtest の全テストをパスできない場合は環境構築から見直していただくことをお勧めします。問題が解決できないようであればサポートにご連絡ください。 |
アプリケーションを起動する
ビルド結果を展開したことで CA も TA も配置されました。目的の CA を起動してください。ここでは optee_examples の optee_example_hello_world を実行します。
[container ~]# optee_example_hello_world
D/TA: TA_CreateEntryPoint:39 has been called
D/TA: TA_OpenSessionEntryPoint:68 has been called
I/TA: Hello World!
D/TA: inc_value:105 has been called
I/TA: Got value: 42 from NW
I/TA: Increase value to: 43
I/TA: Goodbye!
Invoking TA to increment 42
TA incremented value to 43
D/TA: TA_DestroyEntryPoint:50 has been called
| |
---|
D/TA: や I/TA: といった OP-TEE のログが出力されないケース OP-TEE OS は uart を直接叩いてます。Linux の仕組みでは出力していないため、
ssh や syslog などを利用してもログを閲覧できません。 |
| |
---|
tee-supplicant は OP-TEE の linux 環境のコンパニオンプロセスです。
OP-TEE を利用するためにはなくてはならないものです。
自動起動することをお勧めします。詳しくは製品マニュアルを参考にしてください。 |
xtest を利用することで AES, SHA アルゴリズムの OP-TEE OS のパフォーマンスを測定することができます。
AES のパフォーマンスを計測するために次のコマンドを実行します。この結果は例になります。
[container ~]# xtest --aes-perf
min=113.753us max=191.881us mean=116.426us stddev=4.10202us (cv 3.5233%) (8.38786MiB/s)
SHA のパフォーマンスを計測するためのコマンドを実行します。この結果も例になります。
[container ~]# xtest --sha-perf
min=50.876us max=123.003us mean=52.8036us stddev=2.4365us (cv 4.61427%) (18.494
6.6. Edgelock SE050 を活用した TEE を構築する
NXP Semiconductors の EdgeLock SE050 は IoT アプリケーション向けのセキュアエレメントです。様々なアルゴリズムに対応した暗号エンジン、セキュアストレージを搭載します。GlobalPlatform によって標準化されている Secure Channel Protocol 03 に準拠し、バスレベル暗号化 (AES)、ホストとカードの相互認証 (CMAC ベース) を行います。
OP-TEE で SE050 を用いるユースケースとしては、IoT アプリケーション向けに特化された豊富な機能を活用した上で、ホスト側の処理を守りたい場合に利用することが考えられます。OP-TEE を組み合わせることで SE050 へアクセスする部分、保存された情報資産を取り出して実際に処理する部分を守ることができます。
| |
---|
ユーザーが SE050 にアクセスする場合は、OP-TEE の TEE Client API や TEE Core API といった GlobalPlatformAPI を呼び出すことになります。デバイスの変更などの状況で比較的容易に移植が可能になります。 |
| |
---|
SE050 の詳細については以下の NXP Semiconductors のページから検索して、ご確認ください。 |
6.6.1. OP-TEE 向け plug-and-trust ライブラリ
NXP Semiconductors が開発するライブラリ plug-and-trust を利用してSE050 にアクセスします。OP-TEE への移植は Foundries.io によって行われ、Github にて公開されています。現状、SE050 の全ての機能を使えるわけではありません。主に暗号強度が弱い鍵長が無効化されています。
現状で対応する処理:
-
RSA 2048, 4096 encrypt/decrypt/sign/verify
-
ECC sign/verify
-
AES CTR
-
RNG
-
SCP03 (i2c communications between the processor and the device are encrypted)
-
DieID generation
-
cryptoki integration
| |
---|
OP-TEE 向け plug-and-trust の詳細の情報は以下を参照してください。 |
| |
---|
本ガイドで利用したバージョンは以下のとおりです。 -
plug-and-trust: 0.0.2
-
imx-optee: lf-5.10.72_2.2.0 (3.15.0ベース)
-
trusted-firmware-a: lf_v2.4 (2.4ベース)
|
基本的には CAAM の場合と同様の流れになる。
-
ブートローダーをビルドする
-
imx-optee-client をビルドする
-
TA, CA をビルドする
-
ビルド結果を集める
ディレクトリ構成の概略は以下のとおりです。
├── imx-boot-[VERSION]
│ ├── imx-atf
│ ├── imx-mkimage
│ ├── imx-optee-os
│ └── uboot-imx
├── imx-optee-client
├── imx-optee-test
├── optee_examples
├── plug-and-trust
└── out
OP-TEE 向け plug-and-trust をビルドするために必要なパッケージをインストールします。
[PC ~]$ sudo apt install cmake
6.6.4. OP-TEE 向け plug-and-trust をビルドする
OP-TEE 向け plug-and-trust をクローンする
imx-boot-[VERSION] や imx-optee-client ディレクトリと並列に配置されるように OP-TEE 向け plug-and-trust をクローンして、必要に応じて適切なブランチなどをチェックアウトしてください。
[PC ~]$ git clone https://github.com/foundriesio/plug-and-trust.git -b optee_lib
OP-TEE 向け plug-and-trust をビルドする
[PC ~]$ mkdir -p plug-and-trust/optee_lib/build
[PC ~]$ cd plug-and-trust/optee_lib/build
[PC ~/plug-and-trust/optee_lib/build]$ cmake \
-DCMAKE_C_FLAGS="-mstrict-align -mgeneral-regs-only" \
-DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
-DOPTEE_TREE="${PWD}/../../../imx-boot-[VERSION]/imx-optee-os" ..
-- The C compiler identification is GNU 10.2.1
-- The CXX compiler identification is GNU 10.2.1
: (省略)
-- Generating done
-- Build files have been written to: /path/plug-and-trust/optee_lib/build
[PC ~/plug-and-trust/optee_lib/build]$ make
make
Consolidate compiler generated dependencies of target se050
[ 4%] Building C object CMakeFiles/se050.dir/path/plug-and-trust/hostlib/hostLib/libCommon/infra/global_platf.c.o
[ 8%] Building C object CMakeFiles/se050.dir/path/plug-and-trust/hostlib/hostLib/libCommon/infra/sm_apdu.c.o
: (省略)
[100%] Linking C static library libse050.a
[100%] Built target se050
6.6.5. imx-optee-os のコンフィグの修正
SE050 を crypto driver として利用するためにコンフィグを修正する。
SE050 向けにビルドするために imx-boot-[VERSION]/Makefile を追加する。
$(OPTEE)/out/tee.bin: $(OPTEE)/.git FORCE
$(MAKE) -C $(OPTEE) O=out ARCH=arm PLATFORM=imx CFG_WERROR=y \
PLATFORM_FLAVOR=mx8mpevk \
CFG_NXP_SE05X=y \
CFG_IMX_I2C=y \
CFG_CORE_SE05X_I2C_BUS=2 \
CFG_CORE_SE05X_BAUDRATE=400000 \
CFG_CORE_SE05X_OEFID=0xA200 \
CFG_IMX_CAAM=n \
CFG_NXP_CAAM=n \
CFG_CRYPTO_WITH_CE=y \
CFG_STACK_THREAD_EXTRA=8192 \
CFG_STACK_TMP_EXTRA=8192 \
CFG_NUM_THREADS=1 \
CFG_WITH_SOFTWARE_PRNG=n \
CFG_NXP_SE05X_PLUG_AND_TRUST_LIB=~/plug-and-trust/optee_lib/build/libse050.a \
CFG_NXP_SE05X_PLUG_AND_TRUST=~/plug-and-trust/
コンフィグの修正に関する詳細
|
SE050 を利用するために有効にする
|
|
imx-i2c ドライバ を有効にする
|
|
CAAM は無効化する
|
|
AES や SHA は高速な Arm CE を利用する
|
|
スタックを通常よりも多く消費するためにスタックを増量する
|
|
スレッドによる複数のコンテキストに対応していないためスレッドを 1 つとする
|
|
ハードウェア乱数発生器を利用するために無効にする
|
|
SE050 のドライバの実装は OP-TEE 向け plug-and-trust ライブラリ内に存在する
|
| |
---|
-
SE050 の host 接続用 I2C は最大 3.2 MHz (high speed)ですが、i.MX 8M Plus の i2c の最大周波数は 400kHz のため、遅い通信速度で実装されています
-
CAAM と SE050 の共存は、SE050 を有効にすることによって CAAM の個別のドライバの依存関係が不正になるため、実行時にエラーになる問題があります
|
Armadillo は消費電力の削減のためサスペンド時に SE050 を Deep Power-down モードに設定してパワーゲーティングしています。
SE050 を Linux の起動前、あるいは Linux がサスペンド中に利用するためには、i.MX 8M Plus に接続されている SE050 の ENA ピンをアサートする必要があります。
ENA ピンをアサートすると SE050 は一定時間の後に起動するので SE050 を利用すためには若干の待ち時間が必要となります。
OP-TEE OS は起動時にドライバの初期化等を行う実装になっています。
そのため、OP-TEE OS が起動する前に生存している SPL (Secondary Program Loader) で Deep Power-down を解除することで待ち時間を稼いでいます。
以下はシステムの起動と SE050 の関係を示したシーケンス図。
ENA をアサートするために以下のように変更する
diff --git a/board/atmark-techno/armadillo_x2/spl.c b/board/atmark-techno/armadillo_x2/spl.c
index fd886970f805..3aed04ccf2b2 100644
--- a/board/atmark-techno/armadillo_x2/spl.c
+++ b/board/atmark-techno/armadillo_x2/spl.c
@@ -111,6 +111,11 @@ static struct fsl_esdhc_cfg usdhc_cfg[2] = {
{USDHC3_BASE_ADDR, 0, 8},
};
+#define SE_RST_N IMX_GPIO_NR(1, 12)
+static iomux_v3_cfg_t const se_rst_n_pads[] = {
+ MX8MP_PAD_GPIO1_IO12__GPIO1_IO12 | MUX_PAD_CTRL(NO_PAD_CTRL),
+};
+
int board_mmc_init(bd_t *bis)
{
int i, ret;
@@ -254,6 +259,11 @@ void spl_board_init(void)
clock_enable(CCGR_GIC, 1);
#endif
+ imx_iomux_v3_setup_multiple_pads(se_rst_n_pads,
+ ARRAY_SIZE(se_rst_n_pads));
+ gpio_request(SE_RST_N, "se_rst_n");
+ gpio_direction_output(SE_RST_N, 1);
+
puts("Normal Boot\n");
}
また、Linux で suspend を使用する場合は suspend 時に SE050 が無効化されないようにするため
se_en の dtb ノードを無効化します(linux 5.10.205-r0 以降)。
diff --git a/arch/arm64/boot/dts/freescale/armadillo_iotg_g4-customize.dts b/arch/arm64/boot/dts/freescale/armadillo_iotg_g4-customize.dts
index dbf416b532b3..b36adb8b13d8 100644
--- a/arch/arm64/boot/dts/freescale/armadillo_iotg_g4-customize.dts
+++ b/arch/arm64/boot/dts/freescale/armadillo_iotg_g4-customize.dts
@@ -12,5 +12,6 @@
#include "imx8mp-pinfunc.h"
-// Replace this empty section by your configuration
-&{/} {};
+&se_en {
+ status = "broken";
+};
6.6.7. imx-optee-os の imx-i2c ドライバの修正
imx-optee-os の imx-i2c ドライバには i.MX 8M Plus の対応が入っていないため、レジスタ等の定義を追加する必要がある。imx-optee-os には lf-5.10.y_2.0.0 からSE050 ドライバが取り込まれている。
以下のように修正する。
diff --git a/core/arch/arm/plat-imx/conf.mk b/core/arch/arm/plat-imx/conf.mk
index b4fbfed5..3f6388f3 100644
--- a/core/arch/arm/plat-imx/conf.mk
+++ b/core/arch/arm/plat-imx/conf.mk
@@ -555,7 +555,7 @@ endif
else
-$(call force,CFG_CRYPTO_DRIVER,n)
-$(call force,CFG_WITH_SOFTWARE_PRNG,y)
+#$(call force,CFG_CRYPTO_DRIVER,n)
+#$(call force,CFG_WITH_SOFTWARE_PRNG,y)
ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP)))
diff --git a/core/arch/arm/plat-imx/registers/imx8m.h b/core/arch/arm/plat-imx/registers/imx8m.h
index 9b6a50ee..59fcea88 100644
--- a/core/arch/arm/plat-imx/registers/imx8m.h
+++ b/core/arch/arm/plat-imx/registers/imx8m.h
@@ -42,6 +42,17 @@
#define IOMUXC_I2C1_SDA_CFG_OFF 0x480
#define IOMUXC_I2C1_SCL_MUX_OFF 0x214
#define IOMUXC_I2C1_SDA_MUX_OFF 0x218
+#elif defined(CFG_MX8MP)
+#define I2C1_BASE 0x30a20000
+#define I2C2_BASE 0x30a30000
+#define I2C3_BASE 0x30a40000
+
+#define IOMUXC_I2C1_SCL_CFG_OFF 0x460
+#define IOMUXC_I2C1_SDA_CFG_OFF 0x464
+#define IOMUXC_I2C1_SCL_MUX_OFF 0x200
+#define IOMUXC_I2C1_SDA_MUX_OFF 0x204
+#define IOMUXC_I2C1_SCL_INP_OFF 0x5A4
+#define IOMUXC_I2C1_SDA_INP_OFF 0x5A8
#endif
#endif /* __IMX8M_H__ */
diff --git a/core/drivers/imx_i2c.c b/core/drivers/imx_i2c.c
index a318c32c..a9dab31c 100644
--- a/core/drivers/imx_i2c.c
+++ b/core/drivers/imx_i2c.c
@@ -34,6 +34,16 @@
/* Clock */
#define I2C_CLK_CGRBM(__x) 0 /* Not implemented */
#define I2C_CLK_CGR(__x) CCM_CCRG_I2C##__x
+#elif defined(CFG_MX8MP)
+/* IOMUX */
+#define I2C_INP_SCL(__x) (IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8)
+#define I2C_INP_SDA(__x) (IOMUXC_I2C1_SDA_INP_OFF + ((__x) - 1) * 0x8)
+#define I2C_INP_VAL(__x) (((__x) == 1 || (__x) == 2) ? 0x2 : 0x4)
+#define I2C_MUX_VAL(__x) 0x010
+#define I2C_CFG_VAL(__x) 0x1c6
+/* Clock */
+#define I2C_CLK_CGRBM(__x) 0 /* Not implemented */
+#define I2C_CLK_CGR(__x) CCM_CCRG_I2C##__x
#elif defined(CFG_MX6ULL)
/* IOMUX */
#define I2C_INP_SCL(__x) (IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8)
@@ -182,7 +192,7 @@ static void i2c_set_bus_speed(uint8_t bid, int bps)
vaddr_t addr = i2c_clk.base.va;
uint32_t val = 0;
-#if defined(CFG_MX8MM)
+#if defined(CFG_MX8MM) || defined(CFG_MX8MP)
addr += CCM_CCGRx_SET(i2c_clk.i2c[bid]);
val = CCM_CCGRx_ALWAYS_ON(0);
#elif defined(CFG_MX6ULL)
以下は imx プラットフォームの makefile の問題です。回避するためにコメントアウトします。
|
imx プラットフォームで CAAM 以外の crypto driver を利用することを想定していない
|
|
CAAM の HWRNG を利用しないということは PRNG を使うことしか想定しない
|
6.6.8. ビルドとターゲットボードへの組み込み
修正した後は、ビルドからターゲットボードへの組み込みまで CAAM 向けの OP-TEE と同様の手順で作業することが可能です。 「ブートローダーを再ビルドする」 の作業から開始して組み込みしてください。
「OP-TEE 向け plug-and-trust ライブラリ」 で説明したように一部のアルゴリズムに制限があります。そのため xtest の全てのテスト項目をパスするわけではありません。以下に失敗するテスト項目を列挙する。
仕様どおりのエラー:
対応していない鍵長のためにエラー:
-
regression 4006 Test TEE Internal API Asymmetric Cipher operations
-
regression 4007 rsa.1 Generate RSA-256 key
-
regression 4011 Test TEE Internal API Bleichenbacher attack
-
pkcs11 1021.3 RSA-1024: Sign & verify - oneshot - CKM_MD5_RSA_PKCS
-
pkcs11 1022.2 RSA-1024: Sign & verify - oneshot - RSA-PSS/SHA1
-
pkcs11 1023.2 RSA OAEP key generation and crypto operations
optee os の不具合 (既知の問題):
-
regression 4009 Test TEE Internal API Derive key ECDH
-
regression 6018 Large object
-
pkcs11 1019.3 P-256: Sign & verify - oneshot - CKM_ECDSA_SHA1
以下は特に問題はないが時間がかかるためにフリーズしているかのように見える。
-
regression 1006 Secure time source
-
regression nxp 0001, regression_nxp_0003
| |
---|
xtest を行う際にはデフォルトでテストに失敗しても先に進む設定となっています。ただ、時間のかかるテストは無効にすることも可能です。 [container ~]# xtest -x 1006 -x regression_nxp_0003 |
OP-TEE のアーキテクチャの概要を説明する。ここでは i.MX 8M Plus に搭載される Cortex-A53 コアのアーキテクチャである aarch64 を前提に話を進める。
以下にのシステム図を示す。
以下のコンポーネントによってシステムが構成される。概要と主な責務について説明する。
OP-TEE
-
GlobalPlatform の TEE 実装。secure EL1 に配置される
Trusted Firmware-A
-
Linaro によって開発される Secure monitor の実装
-
secure state と non-secure state の遷移管理、PSCI に準拠した電源管理などを担当する
-
optee dispatcher と呼ばれる OP-TEE の呼び出しモジュールを内部に持つ
Client Application (CA)
Trusted Application (TA)
tee-supplicant
-
Linux user 空間で動作する OP-TEE を補うプロセス。目的は Linux のリソースを OP-TEE OS が利用するため
TEE を呼び出すフローについて説明する。
CA が OP-TEE 上の TA とのセッションを確立する流れ
Linux 上の CA が、セッションを開くために uuid を指定して TEE Client API を呼び出す
-
システムコールで tee driver が呼ばれる
-
tee driver は セキュアモニタコールで Trusted Firmware-A (ATF) 上の OP-TEE dispacher を呼び出す
OP-TEE dispatcher は optee vector table に登録されている OP-TEE のハンドラを呼び出す
-
OP-TEE OS は自ら SEL1 に落ちて、内部処理をしてから、ここまでの逆順で tee-supplicant を呼び出す
-
tee-supplicant は uuid を基に TA をロードして共有メモリに配置して OP-TEE OS を呼び出す
-
OP-TEE は TA をロードする
-
セッションができる
CA が TEE Client API を通して TA 上である処理を実行する流れ
Linux 上の CA が TEE Client API を呼び出す
-
システムコールで tee driver が呼ばれる
-
tee driver は セキュアモニタコールで Trusted Firmware-A (ATF) 上の OP-TEE dispacher を呼び出す
-
OP-TEE dispatcher は optee vector table に登録されている OP-TEE のハンドラを呼び出す
-
ハンドラ (OP-TEE OS) は自ら SEL1 に落ちる。内部処理をしてから、SEL0 に落ちて TA を呼び出す
-
TA は API の引数を基にある処理を実行する
-
ここまでの逆順で CA まで戻る
| |
---|
より詳しい内容については公式ドキュメントをご覧ください。 |
セキュリティ関連の領域を含めた i.MX 8M Plus の物理メモリマップを次に示します。
imx-optee-os のメモリマップを次に示します。デバッグ等にお役立てください。
表6.1 OP-TEE メモリマップ
type | virtual address | physical address | size | description |
---|
TEE_RAM_RX/RW | 0x5600_0000..
0x561f_ffff | 0x5600_0000..
0x561f_ffff | 0x0020_0000 (smallpg) | OP-TEE text + data セクション |
IO_SEC | 0x5620_0000..
0x5620_ffff | 0x32f8_0000..
0x32f8_ffff | 0x0001_0000 (smallpg) | TZASC |
SHM_VASPACE | 0x5640_0000..
0x583f_ffff | 0x0000_0000..
0x01ff_ffff | 0x0200_0000 (pgdir) | OP-TEE dynamic shared memory area, va の確保のみ |
RES_VASPACE | 0x5840_0000..
0x58df_ffff | 0x0000_0000..
0x009f_ffff | 0x00a0_0000 (pgdir) | OP-TEE 予約領域 (late mapping), va の確保のみ |
IO_SEC | 0x58e0_0000..
0x591f_ffff | 0x3020_0000..
0x305f_ffff | 0x0040_0000 (pgdir) | AIPS1(GPIO1, GPT, IOMUXC など) |
IO_NSEC | 0x5920_0000..
0x595f_ffff | 0x3080_0000..
0x30bf_ffff | 0x0040_0000 (pgdir) | AIPS3(UART2, CAAM, I2C など) |
IO_SEC | 0x5960_0000..
0x597f_ffff | 0x3880_0000..
0x389f_ffff | 0x0020_0000 (pgdir) | GICv3 |
TA_RAM | 0x5980_0000..
0x5b1f_ffff | 0x5620_0000..
0x57bf_ffff | 0x01a0_0000 (pgdir) | TA ロード、実行領域 |
NSEC_SHM | 0x5b20_0000..
0x5b5f_ffff | 0x57c0_0000..
0x57ff_ffff | 0x0040_0000 (pgdir) | OP-TEE contiguous shared memory area |