組み込みデバイスへの攻撃は様々な方向から行われます。ある方向のセキュリティ対策が強固な場合、攻撃者は回避可能な別の方向がないのか模索します。攻撃者のコードを何らかの方法でデバイスに組み込んで対策を回避するのが、単純ですが有効な方法でしょう。IoT デバイスはネットワーク上のサービスとデータのやり取りを行います。通信路の暗号化、サーバーとデバイスの相互認証などの対策を講じたとしても、IoT デバイス上にあるソフトウェアに攻撃者のコードを組み込むことで対策を回避してシステムに侵入される可能性があるのです。
セキュアブートは、起動ソフトウェアのディジタル署名を用いて正規ソフトウェアであることを確認してから起動する処理のことです。攻撃者によって作られた不正なコードを実行前に検出することができます。セキュアブートはチェーンオブトラスト (chain of trust) と表裏一体に実装されます。チェーンオブトラストとは、その名の通り、信頼を繋いでいく形態のことを指します。ルートオブトラストと呼ばれる基礎となる情報から枝葉のように繋がれた情報を認証していくことで、繋がれた個々のコンポーネントだけでなくシステムを信頼できるものにしてくれます。セキュアブートは、起動時にソフトウェアを順番に認証することで信頼を次に繋いでいるのです。セキュアブートの範囲をどこまでにするかによりますが、起動時に認証されたソフトウェアで別の情報を認証すれば、チェーンオブトラストを繋げていくことができます。また、IoT デバイスとクラウドサービスから構成されるような広範囲に及ぶシステムは特に信頼が必要になります。信頼できるセキュリティ基盤を構築するためには、構成するソフトウェアが正規のリリース物であることを確認することが重要になります。チェーンオブトラストを採用することでより信頼できる IoT システムとなり得るのです。
では、どういったケースでセキュアブートを採用するべきでしょうか。セキュアブートはセキュアな組み込みデバイスを実現する上で最初のステップにするべき技術です。しかし、導入するのであればコスト面にも配慮することが必要でしょう。まず、製造時の追加コストが必要です。鍵等を書き込む工程が必要になります。ただ書き込めばよいわけではなく、漏洩があってはいけないので物理的な隔離などセキュアに書き込む必要があります。メンテナンスにも追加のコストが必要です。ソフトウェアのリリース時にはソフトウェアの署名が必要になります。こちらも、物理的な隔離などの漏洩、汚染対策が必要になります。また、どこまでやるかによりますが、定期的な鍵の更新、インシデントや製品寿命による鍵のリボーケーションなどのメンテナンスコストが必要になってきます。費用対効果を検討してからの導入をお勧めします。
HAB (High Assurance Booting) は、NXP が提供するセキュアブートの実装です。i.MX 8M Plus の BootROM には HABv4 が組み込まれます。デフォルトでは無効な状態になっていますが、一度、eFuse に情報を書き込むことでセキュアブートが有効になり、それ以降、有効な状態のまま変更不可能になります。HABv4 で規定する仕様では次の情報をブートローダーイメージに追加することで BootROM が起動時にブートローダーの認証を行います。
-
CSF (Command Sequence File)、IVT (Image Vector Table)
-
SRK (Super Root Key)、CSF、IMG 署名確認鍵
-
イメージの署名
NXP は署名ツールとして CST (Code Signing Tool) をリリースしています。本来、署名範囲などは環境によって様々な実装がなされるべきなので署名ツール自体にはその辺りの仕様が含まれません。ブートローダーの実装仕様に依存します。Armadillo Base OS で採用される uboot-imx のセキュアブート処理では、Trusted Firmware-A (ATF)、OP-TEE OS、Linux カーネルイメージまでが認証の対象になります。署名に関する概要は以下のとおりです。
-
署名確認用の鍵は X.509 証明書に対応する
署名は RSA/ECC に対応する
-
RSA 1024, 2048, 3072, 4096 bits
-
ECC NIST P-256, NIST P-384, NIST P-521
-
署名のダイジェストは SHA256 のみ
| |
---|
HAB の詳しい仕様は以下を参照してください。 |
まず、セキュアブートをセットアップするために必要な環境を構築していきます。
ここで利用する署名環境の構成は以下のとおりです。
表5.1 署名環境
ツール/パッケージ | 説明 |
---|
ATDE(Atmark Techno Development Environment) | 提供元 : アットマークテクノ
Armadillo シリーズの開発環境として VMware イメージとして配布されます |
CST(Code Signing Tool) | 提供元 : NXP
HAB の署名を行うツールや鍵を生成するツールを含みます |
mkswu パッケージ | 提供元 : アットマークテクノ
Armadillo Base OS のファームウェアアップデートの仕組みである SWUpdate 用のアップデートファイルを生成するツールを含みます |
build-rootfs-[VERSION].tar.gz | 提供元 : アットマークテクノ
Armadillo Base OS のルートファイルシステムを生成するツールを含みます
Alpine Linux をベースにアットマークテクノのパッケージを加えた構成になります |
imx-boot-[VERSION].tar.gz | 提供元 : アットマークテクノ
ブートローダーのソースコードや、セキュアブート用のイメージをつくるスクリプトを含みます |
baseos-[VERSION].tar.zst | 提供元 : アットマークテクノ
Armadillo Base OS のルートファイルシステムのビルド済みバイナリ |
NXP から署名ツールをダウンロードします
以下のサイトからダウンロードします。
| |
---|
-
ダウンロードには NXP サイトへのユーザー登録が必要になります
-
本書作成時点では v3.4.1 を利用しました。
2023 年 6 月時点で最新の v3.3.2 では、ブートローダーの暗号化が利用出来ませんので、必要な場合はサポートにご連絡ください。
|
ツールを展開します。
[ATDE ~]$ tar -xaf IMX_CST_TOOL_NEW.tgz
5.3.4. アップデートファイル作成ツール (mkswu) を準備する
mkswu は SWUpdate に対応したアップデートファイルを生成するツールです。
製品マニュアルを参考に ATDE をセットアップしてください。
| |
---|
セキュアブートに対応する mkswu は 4.0-1 以上になります。 |
| |
---|
SWU イメージの暗号化 SWU イメージはデフォルト設定では暗号化されません。
通信路は TLS で守られても、ファイルで保管されているときには平文なので
SWU イメージ内にある機密情報が漏洩する可能性があります。
SWU イメージに漏洩すると問題のある情報資産を含めるときには必ず暗号化するべきです。 Armadillo-IoT ゲートウェイ G4/Armadillo-X2 の製品マニュアル内の「最初に行う設定」を
実施するときには、以下の質問では y と答えてください。 アップデートイメージを暗号化しますか? (N/y) |
バージョンの確認方法は以下のとおりです。
[ATDE ~]$ dpkg -l mkswu
ii mkswu 6.4-1
5.3.5. Armadillo Base OS イメージの取得
署名や暗号化の対象であるブートローダーや Linux は、
アットマークテクノからビルド済みイメージが配布されています。
アットマークテクノのサイトから最新イメージをダウンロードしてください。
| |
---|
本書作成時点で利用したパッケージは以下のとおりです。 -
imx-boot-2020.04-at24.tar.gz
-
baseos-x2-3.20.3-at.4.tar.zst
-
build-rootfs-v3.20-at.4.tar.gz
|
Armadillo Base OS を展開します。
[ATDE ~]$ mkdir -p baseos
[ATDE ~]$ tar xaf baseos-x2-[VERSION].tar.zst -C baseos
|
[VERSION] はバージョンによって変化します
|
ブートローダーを展開します。
[ATDE ~]$ tar xaf imx-boot-[VERSION].tar.gz
|
[VERSION] はバージョンによって変化します
|
ビルドツールを展開します。
[ATDE ~]$ tar xaf build-rootfs-[VERSION].tar.gz
|
[VERSION] はバージョンによって変化します
|
ディレクトリ構成の一部抜粋は以下のとおりです。
├── baseos
├── build-rootfs-[VERSION]
├── cst_3.4.1
│ ├── crts
│ ├── keys
│ └── linux64/bin
├── imx-boot-[VERSION]
├── mkswu
└── secureboot
|
[VERSION] はそれぞれのバージョンによって変化します
|
|
ブートローダーに組み込む自己証明書群が配置される
|
|
鍵の生成ツール、生成された鍵が配置される
|
|
ビルド済み署名ツールが配置される
|
|
swu 作成に利用される。
|
|
ビルド結果が配置される。ビルド前にはないディレクトリ
|
セキュアブート用の PKI tree を作っていきます。
生成する鍵とその証明書は以下のとおりです。
表5.2 セキュアブート用の鍵と証明書
name | description | file name |
---|
CA 鍵ペア | ルート CA | CA1_sha256_[alg]_v3_ca_crt |
SRK 鍵ペア | Super Root Key 用の鍵ペア | SRK[n]_sha256_[alg]_v3_ca_key |
CSF 鍵ペア | CSF 用の鍵ペア | CSF[n]_sha256_[alg]_v3_usr_key |
IMG 鍵ペア | イメージ用の鍵ペア | IMG[n]_sha256_[alg]_v3_usr_key |
SRK 証明書 | CA 鍵によって署名されたSRK 公開鍵を含んだ証明書 | SRK[n]_sha256_[alg]_v3_ca_crt |
CSF 証明書 | SRK によって署名された CSF 公開鍵を含んだ証明書 | CSF[n]_sha256_[alg]_v3_usr_crt |
IMG 証明書 | SRK によって署名された IMG 公開鍵を含んだ証明書 | IMG[n]_sha256_[alg]_v3_usr_crt |
-
[alg]: アルゴリズム (RSA: 1024/2048/3072/4096, ECC: prime256v1/secp384r1/secp521r1)
-
[n]: n = 1,2,3,4
| |
---|
署名鍵のデフォルト設定は ECC secp521r1 となっています。
鍵の種類などの設定は imx-boot-[VERSION]/secureboot.conf にあります。
変更する場合は 「secureboot.conf の設定方法」 を参照してください。 |
実際に署名鍵を生成していきます。
ここでは既存の CA 証明書を利用せずに鍵を生成します。
以下のコマンドを実行してください。
[ATDE ~]$ ./imx-boot-[VERSION]/secureboot.sh init_srk
秘密鍵のパスワードを求められるので入力してください。
Passphrase used for key generation (will be written in plain text on filesystem)
| |
---|
CST の詳細の情報は cst 内の docs ディレクトリにある CST_UG.pdf をご参照ください。 |
ファイルがあるかどうかで鍵が生成されたことを確認してください。
以下はデフォルト設定である ECC secp521r1 の鍵を生成した場合の結果になります。
cst-3.3.1
├── crts
│ ├── CA1_sha256_secp521r1_v3_ca_crt.der
│ ├── CA1_sha256_secp521r1_v3_ca_crt.pem
│ ├── CSF1_1_sha256_secp521r1_v3_usr_crt.der
│ ├── CSF1_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── CSF2_1_sha256_secp521r1_v3_usr_crt.der
│ ├── CSF2_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── CSF3_1_sha256_secp521r1_v3_usr_crt.der
│ ├── CSF3_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── CSF4_1_sha256_secp521r1_v3_usr_crt.der
│ ├── CSF4_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── IMG1_1_sha256_secp521r1_v3_usr_crt.der
│ ├── IMG1_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── IMG2_1_sha256_secp521r1_v3_usr_crt.der
│ ├── IMG2_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── IMG3_1_sha256_secp521r1_v3_usr_crt.der
│ ├── IMG3_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── IMG4_1_sha256_secp521r1_v3_usr_crt.der
│ ├── IMG4_1_sha256_secp521r1_v3_usr_crt.pem
│ ├── SRK1_sha256_secp521r1_v3_ca_crt.der
│ ├── SRK1_sha256_secp521r1_v3_ca_crt.pem
│ ├── SRK2_sha256_secp521r1_v3_ca_crt.der
│ ├── SRK2_sha256_secp521r1_v3_ca_crt.pem
│ ├── SRK3_sha256_secp521r1_v3_ca_crt.der
│ ├── SRK3_sha256_secp521r1_v3_ca_crt.pem
│ ├── SRK4_sha256_secp521r1_v3_ca_crt.der
│ ├── SRK4_sha256_secp521r1_v3_ca_crt.pem
│ ├── SRK_1_2_3_4_fuse.bin
│ └── SRK_1_2_3_4_table.bin
└── keys
├── CA1_sha256_secp521r1_v3_ca_key.der
├── CA1_sha256_secp521r1_v3_ca_key.pem
├── CSF1_1_sha256_secp521r1_v3_usr_key.der
├── CSF1_1_sha256_secp521r1_v3_usr_key.pem
├── CSF2_1_sha256_secp521r1_v3_usr_key.der
├── CSF2_1_sha256_secp521r1_v3_usr_key.pem
├── CSF3_1_sha256_secp521r1_v3_usr_key.der
├── CSF3_1_sha256_secp521r1_v3_usr_key.pem
├── CSF4_1_sha256_secp521r1_v3_usr_key.der
├── CSF4_1_sha256_secp521r1_v3_usr_key.pem
├── IMG1_1_sha256_secp521r1_v3_usr_key.der
├── IMG1_1_sha256_secp521r1_v3_usr_key.pem
├── IMG2_1_sha256_secp521r1_v3_usr_key.der
├── IMG2_1_sha256_secp521r1_v3_usr_key.pem
├── IMG3_1_sha256_secp521r1_v3_usr_key.der
├── IMG3_1_sha256_secp521r1_v3_usr_key.pem
├── IMG4_1_sha256_secp521r1_v3_usr_key.der
├── IMG4_1_sha256_secp521r1_v3_usr_key.pem
├── SRK1_sha256_secp521r1_v3_ca_key.der
├── SRK1_sha256_secp521r1_v3_ca_key.pem
├── SRK2_sha256_secp521r1_v3_ca_key.der
├── SRK2_sha256_secp521r1_v3_ca_key.pem
├── SRK3_sha256_secp521r1_v3_ca_key.der
├── SRK3_sha256_secp521r1_v3_ca_key.pem
├── SRK4_sha256_secp521r1_v3_ca_key.der
└── SRK4_sha256_secp521r1_v3_ca_key.pem
| |
---|
生成した鍵は今後も利用するものです。
壊れにくい、セキュアなストレージにコピーしておくことをお勧めします。 |
| |
---|
鍵の更新は計画性を持って行ってください。
たとえば開発時のみ利用する鍵、運用時に利用する鍵を使い分ける。
また、鍵は定期的に更新が必要です。以下を参考にしてください。 |
生成が終わったら、次のコマンドを実行して鍵のハッシュ値を確認して、
結果を控えておいて下さい。後ほどデバイス上で efuse を書く際に利用します。
[ATDE ~]$ ./imx-boot-[VERSION]/secureboot.sh print_srk_fuse
以下のように表示されます。
あくまで例でハッシュ値は生成された鍵毎に異なります。このまま利用しないでください。
Use the following commands in uboot to set root key hash in OTP:
fuse prog -y 6 0 0xC04FA990 0x6C4BCFCC 0x90DAC78E 0x6C6CED49
fuse prog -y 7 0 0x535C7B3E 0x2695B4D4 0x9B3D028E 0x9FF5EFFB
fuse prog -y 0 0 0x200
For testing it is possible to temporarily override fuses instead,
but this only validates the last part of the boot:
fuse override 6 0 0xC04FA990 0x6C4BCFCC 0x90DAC78E 0x6C6CED49
fuse override 7 0 0x535C7B3E 0x2695B4D4 0x9B3D028E 0x9FF5EFFB
以上で、環境構築を終わります。
ここではセキュアブートを有効にする方法を説明します。
5.5.1. uboot-imx のセキュアブートの実装仕様
セキュアブートの実装は uboot-imx のガイドに準拠しています。
詳しい仕様は以下を参照してください。
取得したソースツリー内にドキュメントがあります。
セキュアブートのセットアップの流れは以下のとおりです。
PC 上の作業
事前準備
ビルド
Armadillo-IoT ゲートウェイG4/Armadillo-X2 上の作業
以下のコマンドでブートローダーをビルドし、そのブートローダーに署名を付加します。
[ATDE ~]$ cd imx-boot-[VERSION]
[ATDE ~/imx-boot-[VERSION]]$ ./secureboot.sh imxboot
ビルド後に以下のイメージが作られれば成功です。
[ATDE ~/imx-boot-[VERSION]]$ ls ../secureboot
secureboot/imx-boot_armadillo_x2.signed
| |
---|
imx-boot_armadillo_x2.signed は SRK の異なるボードには利用できません。
誤って書き込まないようご注意ください。 |
5.5.4. 署名済み Linux カーネルイメージの作成
secureboot.conf を開発環境に合わせて更新していきます。
[ATDE ~]$ vi imx-boot-[VERSION]/secureboot.conf
Linux カーネルとデバイスツリーブロブがある場所を参照するように変更します。
LINUX_IMAGE="$SCRIPT_DIR/../baseos/boot/Image"
LINUX_DTB="$SCRIPT_DIR/../baseos/boot/armadillo_iotg_g4.dtb"
最後に、Linux カーネルイメージを作ります。
[ATDE ~]$ cd imx-boot-[VERSION]
[ATDE ~/imx-boot-[VERSION]]$ ./secureboot.sh linux
ビルド後に以下のイメージがあれば成功です。
[ATDE ~/imx-boot-[VERSION]]$ ls ../secureboot
Image.signed
まず、ルートファイルシステムに組み込むために、
署名された Linux カーネルのイメージをビルド用のリソースディレクトリに配置します。
[ATDE ~]$ cp secureboot/Image.signed build-rootfs-[VERSION]/ax2/resources/boot/Image
組み込むファイルの準備が終わったので、次にルートファイルシステムをビルドします。
[ATDE ~]$ cd build-rootfs-[VERSION]
[ATDE ~/build-rootfs-[VERSION]]$ ./build_rootfs.sh
以下のファイルがあればルートファイルシステムのビルドは成功しています。
以下は例なので、ファイル名などはバージョンや日付によって変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE].tar.zst
5.5.6. セキュアブートセットアップ用 SD ブートディスクの作成
SD ブートするための起動イメージを作ります。
[ATDE ~/build-rootfs-[VERSION]]$ sudo ./build_image.sh
以下のファイルができていれば成功です。ファイルに含まれる日付やバージョンは
変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE].img
次に、上記の起動イメージを使って SD ブートで初回書き込みを行うためのディスクイメージを
作成します。
ディスクイメージの作成には、xxhash と btrfs-progs が必要です。
以下のコマンドを実行してインストールしてください。
[ATDE ~/build-rootfs-[VERSION]]$ sudo apt install xxhash btrfs-progs
ディスクイメージの作成は、上記の起動イメージ作成時に使用したコマンドを使って引数を変えることで可能です。
--installer には上記の起動イメージを指定します。--boot には生成したブートローダーを指定します。
[ATDE ~/build-rootfs-[VERSION]]$ sudo ./build_image.sh \
--installer baseos-[VERSION].[DATE].img \
--boot ../secureboot/imx-boot_armadillo_x2.signed
以下のファイルができていれば成功です。ファイルに含まれる日付やバージョンは
変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE]-installer.img
上記で作成した SD ブートイメージを、製品マニュアルを参考にして SD カードに書き込んでください。
SD ブート用の SD カードの作成が終わったら、
次からは実際に「Armadillo-IoT ゲートウェイ G4/Armadillo-X2 上の作業」を行います。
ここではストレージを暗号化する方法を説明します。
Armadiilo Base OS では、ストレージの暗号化に LUKS2 (Linux Unified Key Setup)
を採用しました。CAAM を用いた方法もありますが、CAAM は AES XTS モードを
サポートしておらず、AES CBC/ECB モードのみサポートされています。
パフォーマンスが極端に悪いので、CAAM を利用せずに LUKS2 で ARM Cryptographic
extension を利用しています。
LUKS2 に与える鍵は CAAM の Black key 技術によって保護されます。
Black key はデバイス固有の鍵を利用してファイルを暗号化することができます。
デバイス固有の鍵を利用しているので、Black key を別のボートにコピーしても、
鍵を利用することはできません。
Black key をフル機能で利用するためには、セキュアブートが必須です。
Armadillo Base OS ではストレージの 2 つの領域の暗号化をサポートします。
-
アプリケーションを配置するコンテナのファイルシステム
-
Armadioo Base OS のルートファイルシステム
build-rootfs のスクリプト (build_image.sh) では、
1 (USERFS) か 1+2 (ALL) の設定が可能です。
ストレージ暗号化のセットアップの流れは以下のとおりです。
PC 上の作業
事前準備
ビルド
Armadillo-IoT ゲートウェイG4/Armadillo-X2 上の作業
以下のコマンドでブートローダーをビルドし、そのブートローダーに署名を付加します。
[ATDE ~]$ cd imx-boot-[VERSION]
[ATDE ~/imx-boot-[VERSION]]$ ./secureboot.sh imxboot
ビルド後に以下のイメージが作られれば成功です。
[ATDE ~/imx-boot-[VERSION]]$ ls ../secureboot
secureboot/imx-boot_armadillo_x2.signed
| |
---|
imx-boot_armadillo_x2.signed は SRK の異なるボードには利用できません。
誤って書き込まないようご注意ください。 |
5.6.4. ストレージ暗号化対応の署名済み Linux カーネルイメージの作成
まず、initrd 用のルートファイルシステムをビルドします。
[ATDE ~]$ cd build-rootfs-[VERSION]
[ATDE ~/build-rootfs-[VERSION]]$ ./build_rootfs.sh
以下のファイルがあればルートファイルシステムのビルドは成功しています。
以下は例なので、ファイル名などはバージョンや日付によって変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE].tar.zst
次に、initrd の作成します。
ストレージ暗号化に対応するためには、通常の Armadillo Base OS にはない、
暗号鍵などの設定を行うための initrd が必要になります。
[ATDE ~/build-rootfs-[VERSION]]$ sudo ./build_initrd.sh --lock
| |
---|
build-rootfs バージョン 3.19-at.2 以降では --lock を使う場合にこの initrd で以下の制限が入ります: -
エラーの場合に shell を提供しない。
-
eMMC 以外では起動できない。
-
暗号化されている rootfs 以外では起動できない。
SD カードなどでも使う場合にロックせずにビルドしてください。 |
以下のファイルがあれば initrd のビルドは成功しています。
以下は例なので、ファイル名などはバージョンや日付によって変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
initrd-baseos-[VERSION].[DATE].zst
次に、secureboot.conf を開発環境に合わせて更新していきます。
[ATDE ~]$ vi imx-boot-[VERSION]/secureboot.conf
Linux カーネルとデバイスツリーブロブがある場所を参照するように変更します。
LINUX_IMAGE="$SCRIPT_DIR/../baseos/boot/Image"
LINUX_DTB="$SCRIPT_DIR/../baseos/boot/armadillo_iotg_g4.dtb"
上記で作った initrd を参照するように設定を変更します。
LINUX_INITRD="$SCRIPT_DIR/../build-rootfs-[VERSION]/initrd-baseos-[VERSION].[DATE].zst"
最後に、Linux カーネルイメージを作ります。
[ATDE ~]$ cd imx-boot-[VERSION]
[ATDE ~/imx-boot-[VERSION]]$ ./secureboot.sh linux
ビルド後に以下のイメージが更新されていれば成功です。
[ATDE ~/imx-boot-[VERSION]]$ ls ../secureboot
Image.signed
SD ブート用の署名済み Linux カーネルイメージも後に作成するので、それと区別するために
ストレージ暗号化対応の署名済み Linux カーネルのイメージ名を変更しておきます。
[ATDE ~/imx-boot-[VERSION]]$ mv ../secureboot/Image.signed ../secureboot/Image.signed-locked
ルートファイルシステムをビルドします。
[ATDE ~]$ cd ~/build-rootfs-[VERSION]
[ATDE ~/build-rootfs-[VERSION]]$ ./build_rootfs.sh
以下のファイルがあればルートファイルシステムのビルドは成功しています。
以下は例なので、ファイル名などはバージョンや日付によって変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE].tar.zst
5.6.6. ストレージ暗号化対応のセキュアブートセットアップ用 SD ブートディスクの作成
secureboot.cnf を編集します。
[ATDE ~/build-rootfs-[VERSION]]$ vi ../imx-boot-[VERSION]/secureboot.conf
initrd を使用しないように参照先を変更します。
LINUX_INITRD=""
SD ブート用の Linux カーネルを作成します。
[ATDE ~/build-rootfs-[VERSION]]$ cd ~/imx-boot-[VERSION]
[ATDE ~/imx-boot-[VERSION]]$ ./secureboot.sh linux
ビルド後に以下のイメージが更新されていれば成功です。
[ATDE ~/imx-boot-[VERSION]]$ ls ../secureboot
Image.signed
SD ブート用の Linux カーネルのイメージを配置します。
[ATDE ~/imx-boot-[VERSION]]$ cd
[ATDE ~]$ mkdir -p build-rootfs-[VERSION]/ax2/image_installer/boot
[ATDE ~]$ cp secureboot/Image.signed build-rootfs-[VERSION]/ax2/image_installer/boot/Image
SD ブートするための起動イメージを作ります。
[ATDE ~]$ cd build-rootfs-[VERSION]
[ATDE ~/build-rootfs-[VERSION]]$ sudo ./build_image.sh
以下のファイルができていれば成功です。ファイルに含まれる日付やバージョンは
変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE].img
次に、上記の起動イメージを使って SD ブートで初回書き込みを行うためのディスクイメージを
作成します。
ディスクイメージの作成には、xxhash と btrfs-progs が必要です。
以下のコマンドを実行してインストールしてください。
[ATDE ~/build-rootfs-[VERSION]]$ sudo apt install xxhash btrfs-progs
ディスクイメージの作成は、上記の起動イメージ作成時に使用したコマンドを使って引数を変えることで可能です。
--installer には上記の起動イメージを指定します。--boot には生成したブートローダーを指定します。
[ATDE ~/build-rootfs-[VERSION]]$ sudo ./build_image.sh \
--encrypt all \
--installer baseos-[VERSION].[DATE].img \
--boot ../secureboot/imx-boot_armadillo_x2.signed \
--boot-linux ../secureboot/Image.signed-locked
| |
---|
ストレージの暗号化を行う範囲は 2 通り選択可能です。 --encrypt オプション -
userfs : アプリケーション領域
-
all : アプリケーション領域と Linux rootfs 領域
|
以下のファイルができていれば成功です。ファイルに含まれる日付やバージョンは
変化します。
[ATDE ~/build-rootfs-[VERSION]]$ ls
baseos-[VERSION].[DATE]-installer.img
上記で作成した SD ブートイメージを、
製品マニュアルを参考にして SD カードに書き込んでください。
SD ブート用の SD カードの作成が終わったら、
次からは実際に「Armadillo-IoT ゲートウェイ G4/Armadillo-X2 上の作業」を行います。
5.7. Armadillo-IoT ゲートウェイ G4/Armadillo-X2 上の作業
以下は作業の流れです。
セキュアブート、暗号化セキュアブート、ストレージの暗号化で共通の作業になります。
以降はアップデート処理によって自動的にセットアップが行われます。
5.7.1. Armadillo-IoT ゲートウェイ G4/Armadillo-X2 の準備
Armadillo IoT G4/Armadillo-X2 の電源を投入する前に 以下の作業を行ってください。
-
CON1(SD インターフェース)に作った SD カードを挿入する
-
JP1 ジャンパーをショート(SD ブートに設定)します。
また、minicom などのシリアル通信ソフトウェアを起動して、デバッグ入出力を
受け付けられるようにしておいてください。
電源を投入するとすぐに以下のように uboot からデバッグ出力されます。
その間にシリアル通信ソフトウェア上で何らかのキーを押して、
uboot の プロンプトに入ってください。
Hit any key to stop autoboot: 2
u-boot=>
| |
---|
uboot プロンプトへの遷移に間に合わなかった場合は、
そのままの状態 (SD カードを挿したまま、JP1 をショート)で
電源を切って再投入後に再試行して下さい。 |
セキュアブートを有効にするためには、i.MX 8M Plus の eFuse に SRK のハッシュ値を
書く必要があります。i.MX 8M Plus の
OCOTP (On-chip One-Time Programmable Element Controller) のレジスタ経由で
書き込むことになります。uboot-imx には OCOTPA へのアクセスを行う
fuse コマンドがあります。
以下は手順のはじめに出てきた secureboot.sh print_srk_fuse の結果です。
あくまで例なのでハッシュ値は生成された鍵毎に異なります。
このまま入力しないでください。
u-boot=> fuse prog -y 6 0 0xC04FA990 0x6C4BCFCC 0x90DAC78E 0x6C6CED49
u-boot=> fuse prog -y 7 0 0x535C7B3E 0x2695B4D4 0x9B3D028E 0x9FF5EFFB
u-boot=> fuse prog -y 0 0 0x200
| |
---|
eFuse は OTP なので一度作業を行うと変更はできません。注意して作業してください。 |
| |
---|
ハッシュ値は生成された鍵毎にことなります。例の値をそのまま書かないで下さい。 |
次に、これまでのビルド作業や実機上の作業を簡単に確認するために、
HAB の状態を確認します。
次のステップである close 処理を行うとセキュアブートに対応したファームウェア
でしか起動できなくなります。
まだ、close 処理されていない状態ではセキュアブートの必要がないので、
問題の解析がしやすくなります。
まず、再起動します。
u-boot=> reset
uboot のプロンプトで以下のコマンドで確認してください。
以下は正常時のログになります。
u-boot=> hab_status
Secure boot disabled
HAB Configuration: 0xf0, HAB State: 0x66
No HAB Events Found!
|
HAB Events が無いことを確認してください。
|
異常時の場合は以下のようなログになります。
u-boot=> hab_status
Secure boot disabled
HAB Configuration: 0xf0, HAB State: 0x66
--------- HAB Event 1 -----------------
event data:
0xdb 0x00 0x08 0x45 0x33 0x11 0xcf 0x00
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_CSF (0x11)
CTX = HAB_CTX_CSF (0xCF)
ENG = HAB_ENG_ANY (0x00)
--------- HAB Event 2 -----------------
:(省略)
| |
---|
問題が発生した場合 原理確認などを行っているケースでは作業内容に何かしらの問題がある
可能性があります。ログで今までの作業内容を見直してください。
製造ラインなどで同じ作業を繰り返しているケースでは問題は発生しないはずですが、
個体不良の解析のためにここでチェックすることをお勧めします。 |
SRK ハッシュを書いただけでは署名確認に失敗しても起動自体は継続されます。
close 処理を行うことで署名確認に失敗すると起動に失敗するようになります。
| |
---|
開発フェーズなどでセキュアブート処理を確認する場合は、
この close 処理をスキップすることをすることをお勧めします。 |
| |
---|
i.MX 8M plus 内にある SNVS (Secure Non-Volatile Storage) で利用される鍵は、
close 処理をしないとテスト用の鍵が使われます。
テスト用の鍵はデバイス間で共通なため、そのままでは簡単に復号できてしまいます。
close 処理を行うことで、デバイスに固有な鍵を利用するようになります。 |
close 処理は以下のコマンドで efuse を書き込むことで行います。
u-boot=> fuse prog -y 1 3 0x2000000
セキュアブートが可能であるかを確認します。
U-Boot を再起動して、もう一度 U-Boot のプロンプトに入ります。
u-boot=> reset
U-Boot のプロンプト上で以下のコマンドを実行します。
u-boot=> hab_status
Secure boot enabled
HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!
|
セキュアブートは enabled になっていることを確認してください。
|
|
HAB Events が無いことを確認してください。
|
次に、アップデート作業をはじめるためにリセットします。
今後の作業は全て自動的に行われます。
u-boot=> reset
以下のログが表示されたら、電源が入った状態で JP1 ジャンパーをショート
(SD ブートに設定)を解除してください。
Finished writing mmc. powering off now
[ 36.772661] imx2-wdt 30280000.watchdog: Device shutdown: Expect reboot!
[ 36.779641] reboot: Power down
最終的に Linux のログインプロンプトが表示できたら作業は完了です。
万が一、電源断などで作業が中断してしまった場合に作業を完了させる方法に
ついて説明します。
まず、電源を切った状態で 「Armadillo-IoT ゲートウェイ G4/Armadillo-X2 の準備」 が維持されていること
を確認してください。そのうえで、状況に応じて以下の作業を行ってください。
-
SRK ハッシュを書いていない場合は、「SRK ハッシュの書き込み」
から作業をやり直します
-
close 処理を完了していない場合は、SRK ハッシュの書き込みをスキップしてください
-
ファームウェアの書き込みが完了していない場合は、SRK ハッシュの書き込みと
close 処理をスキップします。
具体的な手順としては、電源を投入した直後 (だいたい数秒後) に電源が入った状態で
JP1 ジャンパーのショートを解除して、処理が完了するのを待ってください
最終的に立ち上がってきたら、次の動作確認に進んでください。
ストレージの暗号化が成功したかどうかは、
Armadillo IoT G4/Armadillo-X2 上で以下のコマンドを実行することで確認できます。
TYPE が crypt となっているパーティションが暗号化されています。
[armadillo ~] # lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
mmcblk2 179:0 0 14.8G 0 disk
|-mmcblk2p1 179:1 0 301M 0 part
| `-rootfs_0 253:0 0 300M 0 crypt /live/rootfs
|-mmcblk2p2 179:2 0 301M 0 part
|-mmcblk2p3 179:3 0 50M 0 part
| `-mmcblk2p3 253:1 0 49M 0 crypt /var/log
|-mmcblk2p4 179:4 0 200M 0 part
| `-mmcblk2p4 253:2 0 199M 0 crypt /opt/firmware
`-mmcblk2p5 179:5 0 14G 0 part
`-mmcblk2p5 253:3 0 14G 0 crypt /var/tmp
/var/app/volumes
/var/app/rollback/volumes
/var/lib/containers/storage_readonly
Linux カーネルが立ち上がることを確認してください。
Linux カーネルまで立ち上がらない場合、uboot-imx のコマンドで
HAB の状態を確認することができます。
Linux 起動まで正常な起動ログ
: (省略)
Booting from mmc ...
## Checking Image at 40480000 ...
Unknown image format!
53522 bytes read in 22 ms (2.3 MiB/s)
Authenticate image from DDR location 0x40480000...
Secure boot enabled
HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!
## Flattened Device Tree blob at 45000000
Booting using the fdt blob at 0x45000000
Using Device Tree in place at 0000000045000000, end 0000000045010111
Starting kernel ...
: (省略)
|
セキュアブートが有効な場合に表示されます
|
|
問題がない場合はイベントが表示されません
|
ブートローダーに問題がある場合の起動ログ
: (省略)
spl: ERROR: image authentication unsuccessful
### ERROR ### Please RESET the board ###
: (省略)
Linux カーネルイメージに問題がある場合の起動ログ
: (省略)
Authenticate image from DDR location 0x40480000...
bad magic magic=0x14 length=0xa1 version=0x0
bad length magic=0x14 length=0xa1 version=0x0
bad version magic=0x14 length=0xa1 version=0x0
Error: Invalid IVT structure
Allowed IVT structure:
IVT HDR = 0x4X2000D1
IVT ENTRY = 0xXXXXXXXX
IVT RSV1 = 0x0
IVT DCD = 0x0
IVT BOOT_DATA = 0xXXXXXXXX
IVT SELF = 0xXXXXXXXX
IVT CSF = 0xXXXXXXXX
IVT RSV2 = 0x0
Authenticate Image Fail, Please check
: (省略)
|
認証に失敗しています
|
u-boot コマンドの hab_status
問題がない場合
u-boot=> hab_status
Secure boot enabled
HAB Configuration: 0xcc, HAB State: 0x99
No HAB Events Found!
Linux カーネルイメージの署名確認で問題がある場合
u-boot=> hab_status
Secure boot disabled
HAB Configuration: 0xf0, HAB State: 0x66
--------- HAB Event 1 -----------------
event data:
0xdb 0x00 0x14 0x45 0x33 0x0c 0xa0 0x00
0x00 0x00 0x00 0x00 0x40 0x1f 0xdd 0xc0
0x00 0x00 0x00 0x20
STS = HAB_FAILURE (0x33)
RSN = HAB_INV_ASSERTION (0x0C)
CTX = HAB_CTX_ASSERT (0xA0)
ENG = HAB_ENG_ANY (0x00)
5.9. セットアップ完了後のアップデートの運用について
コンテナ内のアプリケーションのアップデートはセットアップとは関係なく、
とくに特別な対応なしで通常どおりの方法でアップデートが可能です。
製品マニュアルを参考にしてください。
ブートローダーや Linux カーネルを更新するのは若干の違いがあります。
以下のオプションをつけることが必要になります。
ブートローダーの更新 (encrypted_imxboot_update.desc)
[ATDE ~/mkswu]$ mkswu encrypted_imxboot_update.desc -o update_boot.swu
Linux カーネルの更新 (encrypted_rootfs_linux_update.desc)
[ATDE ~/mkswu]$ mkswu encrypted_rootfs_linux_update.desc -o update_linux.swu
5.10.1. secureboot.conf の設定方法
secureboot.conf はセキュアブートイメージ生成スクリプト secureboot.sh
の設定ファイルです。以下はコンフィグの一部です。
-
CST_ECC
既存の CA 証明書を利用するかどうかを設定する
-
CST_KEYLEN, CST_KEYTYPE
-
鍵長を設定する
表5.4 セキュアブート用の鍵の種類
Algorithm | CST_KEYLEN | CST_KEYTYPE |
---|
RSA 1024 | 1024 | 1024_65537 |
RSA 2048 | 2048 | 2048_65537 |
RSA 3072 | 3072 | 3072_65537 |
RSA 4096 | 4096 | 4096_65537 |
EC NIST P-256 | p256 | prime256v1 |
EC NIST P-384 | p384 | secp384r1 |
EC NIST P-521 | p521 | secp521r1 |
-
CST_SOURCE_INDEX
-
SRK は最大 4 本まで持つことができます。この設定ではどの SRK を利用するのか設定します。
設定値は 0 はじまりで、0 がデフォルトです。
-
CST_UNLOCK_SRK
-
SRK のリボーク時に利用します。デフォルト設定では攻撃や事故の防止のために、
リボークができない状態になっています。#CST_UNLOCK_SRK=y のコメントを外すことで
リボークが可能な状態になります。
-
LINUX_IMAGE,LINUX_DTB
-
FIT イメージに組み込むための Linux kernel イメージとデバイスツリーブロブ (DTB) の絶対パス。
-
LINUX_DTB_OVERLAYS
-
Linux 向けの Device tree オーバーレイ用ファイルを組み込むために利用する。いったん、Linux の device mapper を利用してルートファイルシステムを暗号化してしまうと、ブートローダーでは鍵がないとファイルを読むことができない。そのために FIT イメージに組み込んでおくためのオプション。/boot/overlays.conf にも同様の修正を加えてください。
以下は例です。組み込みたいファイルを追加してください。
LINUX_DTB_OVERLAYS=(
armadillo_iotg_g4-nousb.dtbo
armadillo_iotg_g4-sw1-wakeup.dtbo
)
-
LINUX_INITRD
-
暗号化されたルートファイルシステムを復号するための処理を行うための initrd の絶対パス。encrypted boot を利用しない場合には設定は不要です。
以下にブートローダーの署名済みイメージと展開先についての例を示します。緑色の部分が BootROM によって署名検証される部分、橙色の部分は SPL によって署名検証される部分になります。
Linux の署名済みイメージと展開先の例は以下のとおりです。水色の部分は U-Boot によって署名検証される部分になります。
以下に SPL (Secondary Program Loader) のブートフローの概要を示します。点線で囲っている部分はセキュアブートで有効になる処理です。
U-Boot のブートフローの概要は以下のとおりです。SPL と同様に点線で囲っている部分はセキュアブートで有効になる処理です。
5.10.5. ファームウェアアップデートのフロー
何らかのインシデント対応による鍵更新、また、鍵の定期更新などが必要な場合、その時点で利用している鍵を無効化して、別の鍵に切り替えることが可能です。ただし、その場合は複数 (i.MX 8M Plus の場合、最大 4 つ) の SRK が書かれていることが前提となります。
5.10.6.1. SRK の無効化 (revocation)
ここでは SRK1 (index 0) から SRK2 (index 1) に変更する例を説明します。
secureboot.conf の revocation のロックを解除する設定を有効にします
デフォルトでは eFuse の revoke レジスタはロックされているので書き込みできません。
ロックは HAB の設定で解除することができます。常にロックを解除すると攻撃者に
悪用される可能性があるので通常はロックされるべきです。
imx-boot-[VERSION}/secureboot.conf を開いて、CST_UNLOCK_SRK=y のコメントを
外してください。
secureboot.conf の詳細については 「secureboot.conf の設定方法」 を参照してください。
[ATDE ~]$ vi imx-boot-[VERSION]/secureboot.conf
署名済みイメージを書き込む
環境に合わせて、署名済みか、暗号化+署名済みのイメージを作成して、
イメージを書き込んでください。
-
再起動
Unlock を確認する
再起動時の uboot-imx のプロンプトを立ち上げてレジスタ値を確認します。
以下のコマンドを実行してください。bit1 (SRK_REVOKE_LOCK) が落ちていると
Unlock 状態です。
u-boot=> md 0x30350050 1
30350050: 00007dbc
|
7dbc の bit 1 が落ちているので unlock 状態
|
SRK を無効化する
ビットフィールドはビットは 0 はじまりで、鍵の番号は 1 はじまり (1,2,3,4) になります。
bit0 が SRK1、bit1 が SRK2、bit2 が SRK3、bit3 が SRK4 です。
| |
---|
以下のコマンドはあくまで例なので、そのまま実行しないで下さい。 |
SRK1 を無効化する場合は以下のコマンドを実行してください。最終引数が無効化する鍵の設定値です。
u-boot=> fuse prog 9 3 1
ここでは SRK1 (index 0) から SRK2 (index 1) に変更する例を説明します。
SRK の変更
secureboot.conf の CST_SOURCE_INDEX を 0 から 1 に変更してください。
secureboot.conf の詳細については 「secureboot.conf の設定方法」 を参照してください。
[ATDE ~]$ vi imx-boot-[VERSION]/secureboot.conf
再署名する
環境に合わせて、署名済みか、暗号化+署名済みのイメージを作成して、
イメージを書き込んでください。