i.MX 95 でのセキュアブートに使用する署名付きのコンテナ・イメージを Secure Provisioning SDK (SPSDK) で作成し、起動する手順です。
i.MX 95 では、セキュアブートのデジタル署名アルゴリズムとして、クラシックなRSA暗号や楕円曲線デジタル署名暗号 (ECDSA)に加えて、耐量子暗号 (PQC)の ML-DSA もサポートされています。
ここでは、ECDSA と PQC ML-DSA 両方の署名認証を行うHybrid boot での実現例を見ていきます。
セキュアブート・プロセス(概念図)
SRKH : Super Root Key Hash
- 本記事は、i.MX 95 向けのLinux BSP を一度ビルド済みの前提で紹介します。
ビルド方法については以下の記事をご参照ください。
- ビルドするターゲットを、i.MX 95 のマシン名とする必要がありますが、同様の方法になります。
- [入門] Yocto Linux BSPのビルド方法 - i.MX FRDMボード編 (日本語ブログ)
- [入門] Yocto Linux BSPのビルド方法 - i.MX 8M Plus編
- 今回動作確認に使用した環境
- ハードウェア:開発ボード i.MX 95 19x19 LPDDR5 EVK
- ソフトウェア:Linux BSP Version L6.18.2-1.0.0
- ツール:SPSDK version 3.9.0, Linux 版
- eMMC/SDブートであれば、FRDM i.MX 95開発ボード(FRDM-IMX95 / LPDDR4X対応)でも同様の手順で実施することができます。
1. Linux BSP での準備
2. SPSDK のインストール
3. 鍵の作成
4. YAMLファイルの準備
5. ワークスペースの準備
6. 署名付きイメージの作成
7. 署名付きイメージの導入
8. SRKH (Super Root Key Hash) eFuse のプログラム
9. ライフサイクルを OEM Closed に更新
10. ELE イベントの確認
11. ブートローダの直接署名
eMMC/SDブートとFlexSPI NORブートでは、準備手順や実行するコマンドが一部異なります。そのため、確認したいブートデバイスに応じた手順を実施してください。
1.1 ブートローダ
BSP デフォルトでのブートローダは、eMMC/SD ブート用となっています。
FlexSPI NOR ブートの場合には、
UBOOT_CONFIG = "fspi"
u-boot の CONFIG_AHAB_BOOT を有効にしてビルドしたブートローダを使用します。
$ cd
$ source setup-environment
$ bitbake u-boot-imx -c cleansstate
$ bitbake u-boot-imx -c configure
$ bitbake u-boot-imx -c devshell
別のシェルが開きますので、u-boot コンフィグレーションを変更します。
# make O=../../build// menuconfig
- O= で指定するビルド・ディレクトリのパスは、実際の環境に合わせます。
../../build/CONFIG_AHAB_BOOT=y となっていることを確認し、元のシェルに戻ります。
# exit
元のシェルで、再ビルドを行います。
$ bitbake u-boot-imx -c compile -f
$ bitbake imx-boot
1.2 Linux カーネルとデバイスツリー
BSP でビルドされたバイナリをそのまま利用します。
- ビルドされたバイナリは、BSP の
/tmp/deploy/images/ / に作成されています。
SPSDK Installation Guide に従い、Python 仮想環境 venv を準備してインストールします。
インストール後、バージョン情報やヘルプ表示ができるかを確認します。
(venv) $ spsdk --version
(venv) $ spsdk --help
PQCプラグインも追加します。
(venv) $ pip install spsdk-pqc
ECDSA SECP384 の秘密鍵/公開鍵を、4ペア作成します。
(venv) $ mkdir -p keys/secp384r1
(venv) $ nxpcrypto -v key generate -k secp384r1 -o keys/secp384r1/srk0_secp384r1.pem
(venv) $ nxpcrypto -v key generate -k secp384r1 -o keys/secp384r1/srk1_secp384r1.pem
(venv) $ nxpcrypto -v key generate -k secp384r1 -o keys/secp384r1/srk2_secp384r1.pem
(venv) $ nxpcrypto -v key generate -k secp384r1 -o keys/secp384r1/srk3_secp384r1.pem
PQC ML-DSA の秘密鍵/公開鍵も、4ペア作成します。
(venv) $ mkdir keys/mldsa65
(venv) $ nxpcrypto -v key generate -k mldsa65 -o keys/mldsa65/srk0_mldsa65.pem
(venv) $ nxpcrypto -v key generate -k mldsa65 -o keys/mldsa65/srk1_mldsa65.pem
(venv) $ nxpcrypto -v key generate -k mldsa65 -o keys/mldsa65/srk2_mldsa65.pem
(venv) $ nxpcrypto -v key generate -k mldsa65 -o keys/mldsa65/srk3_mldsa65.pem
i.MX 95 内蔵eFuse に公開鍵のハッシュ Super Root Key Hash (SRKH) を書いたあと、イメージをビルドしなおした時は、その公開鍵とペアとなる秘密鍵で署名する必要があるので、作成したすべての鍵は保存しておきます。
秘密鍵は、第三者に開示しないようにします。
SPSDK では、YAMLファイルに、コンテナヘッダ設定や、秘密鍵、公開鍵および、署名付きイメージを構成するバイナリファイルのパスを指定します。
あわせて、今回の動作確認で使用したYAMLファイルの例もご参照ください。
YAMLファイルでのコンテナヘッダ設定や、鍵を指定する項目は、次のようになっています。
| YAMLキー | 内容 |
| srk_set | SRK Set |
| used_srk_id | SRK Selection |
| srk_revoke_mask | SRK Revoke Mask |
| gdet_runtime_behavior | GDET enablement |
| check_all_signatures | Check all signatures |
| fastboot | Fast Boot |
| fuse_version | Fuse Version |
| sw_version | SW Version |
コンテナヘッダの各フィールドは、i.MX 95 Reference Manual の、『Container header details』に記載されています。
| YAMLキー | 内容 |
| signer | クラシック 秘密鍵 |
| signer_#2 | PQC 秘密鍵 |
| srk_table | クラシック 公開鍵テーブル |
| srk_table_#2 | PQC 公開鍵テーブル |
すべてのYAMLファイルで同じ鍵を指定します。
4.1 ブートローダ用YAML ファイル
YAMLファイルのテンプレートを作成し、spl.yaml と uboot.yaml を準備します。
(venv) $ nxpimage ahab get-template -f mimx9596 -o ahab_template.yaml
(venv) $ cp ahab_template.yaml spl.yaml
(venv) $ cp ahab_template.yaml uboot.yaml
| YAML キー | 内容 |
| binary_container | ELE ブート・ファームウエア(マスク・レビジョン専用のバイナリ) |
| lpddr_imem | LPDDR4X or 5 初期化ファームウエア |
| lpddr_imem_qb | LPDDR4X or 5 初期化ファームウエア |
| lpddr_dmem | LPDDR4X or 5 初期化データ |
| lpddr_dmem_qb | LPDDR4X or 5 初期化データ |
| oei_ddr | OEI |
| system_manager | System Manager |
| spl | U-boot SPL |
| cortex_m7_app (Option) | M7 image |
| image_path (Option) | FCB copy image |
| YAML キー | 内容 |
| atf | ARM Trusted Firmware |
| uboot | U-boot |
| tee (Option) | OP-TEE OS (Option) |
4.2 FCB の取り出し - FlexSPI NOR ブートのみ
FlexSPI NOR ブート用のYAMLファイルでは、FCB (FlexSPI Configuration Block)も指定します。そのため、FlexSPI NOR ブート向けにビルドした通常の署名なしブートローダ (flash.bin) から、SPSDK コマンドにて、FCB を取り出しておきます。
i.MX 95 内蔵eFuse のFlexSPI_NOR_FCB_Offset (デフォルト 0x400) にFCB が配置されています。そのオフセットから 512 バイト分を取り出し、 fcb.bin を作成します。
(venv) $ nxpimage utils binary-image extract -b flash.bin -a 0x400 -s 0x200 -o fcb.bin
4.3 OSコンテナ用YAML ファイル
YAMLファイルのテンプレートから、os_cntr.yaml を準備します。
(venv) $ cp ahab_template.yaml os_cntr.yaml
os_cntr.yaml では、キー image_path で、Linux カーネルと使用するデバイスツリーのパスをセットし、その他必要なパラメータも設定します。
4.4 デジタル署名アルゴリズムの選択
i.MX 95 内蔵eFuse やコンテナヘッダのFlags で選択することになります。
コンテナヘッダの Flags フィールドにある "Bit 15: Check all signature" = 0x1 とすることで、eFuse のELE_BOOT_CRYPTO 設定によらず、コンテナ内にあるすべての署名を認証します。
コンテナヘッダの Flags フィールドの "Check all signature"は、YAML キー "check_all_signature" で指定します。
SPSDK でワークスペースを作成し、必要な鍵ファイル、YAML ファイル およびバイナリファイルを配置します。
5.1 ワークスペースの作成
(venv) $ nxpimage bootable-image get-templates -f mimx9596 -o workspace
5.2 鍵ファイル
鍵の作成で作ったkeys フォルダごと持ってきます。
5.3 YAML ファイル例
動作確認に使用したYAMLファイルを、imx95-spsdk-yaml-examples.tar.gz に添付しています。
5.4 バイナリファイル
Yocto Linux BSP からバイナリファイルを持ってくる場合、
YAMLファイルの例 を使用する場合、
・Linux カーネルは、Image
・デバイスツリーは、imx95.dtb
という名前で、それぞれ配置します。
5.5 eMMC / SD ブート
下記のようなファイル構成となります。
YAMLファイルの例を使用する場合、spl.yaml は、DRAMタイプにより、emmc_sd/spl-lpddr4x.yaml または spl-lpddr5.yaml から名前を変更して配置します。
上記では、ELE ブート・ファームウエア は、RevC 品 (B0マスク)用の mx95b0-ahab-container.img となっています。
5.6 FlexSPI NOR ブート
下記のようなファイル構成となります。fcb.binも必要です。
YAMLファイルの例を使用する場合、fspi_nor/から、bootable_image_fspi_nor.yaml をコピーしてきます。
また、spl_fspi_nor-lpddr5.yaml を spl.yaml に名前を変更し配置します。
上記では、ELE ブート・ファームウエア は、RevC 品 (B0マスク)用の mx95b0-ahab-container.img となっています。
署名付きブートローダと署名付き OS コンテナのイメージを、 SPSDK で作成します。
ワークスペースの準備 で作成されたディレクトリに移動して作業します。
(venv) $ cd workspace/imx_boot_flash_all/imx95-19x19-lpddr5-evk/
6.1 署名付きブートローダ
鍵ファイルとバイナリファイルを指定する spl.yaml と uboot.yaml を、bootable_image.yaml から呼び出します。
署名付きブートローダ signed_flash.bin と、SRKH eFuse プログラム用のスクリプト (*.bcf) が作成されます。
(venv) $ nxpimage -v bootable-image export --config bootable_image.yaml -o output/signed_flash.bin
下記のような情報が、表示されます。
(venv) $ nxpimage -v bootable-image export --config bootable_image_fspi_nor.yaml -o output/signed_flash.bin
下記のような情報が、表示されます。
eMMC/SDとの違いとして、FCB が先頭についているのが分かります。
イメージの検証を行うことができます。
// eMMC / SD ブート
(venv) $ nxpimage -v bootable-image verify -f mimx9596 -b output/signed_flash.bin -m serial_downloader
// FlexSPI NOR ブート
(venv) $ nxpimage -v bootable-image verify -f mimx9596 -b output/signed_flash.bin -m flexspi_nor
6.2 署名付きOSコンテナ
os_cntr.yaml の内容で、署名付き OS コンテナのイメージを作成します。
(venv) $ nxpimage -v ahab export -c os_cntr.yaml
下記のような情報が、表示されます。
イメージの検証を行うことができます。
(venv) $ nxpimage -v bootable-image verify -f mimx9596 -b output/os_cntr_signed.bin -m serial_downloader
作成した署名付きブートローダおよび署名付きOSコンテナを導入する方法です。
7.1 署名付きブートローダ
i.MX95 ボードのブートデバイスに、signed_flash.bin を書き込みます。
ボードのデバッグ・ポートとシリアル・ダウンロード・ポートを、PC に接続します。
u-boot が起動する場合には fastboot モードにします。
u-boot=> fastboot 0
もしくは、BOOT_MODE を シリアル・ダウンロード・モード として起動しておきます。
SPSDKで書き込みます。
// eMMC
(venv) $ nxpuuu write -b emmc -f mimx9596 output/signed_flash.bin
// SD
(venv) $ nxpuuu write -b sd -f mimx9596 output/signed_flash.bin
// FlexSPI NOR
(venv) $ nxpuuu write -b qspi -f mimx9596 output/signed_flash.bin
- SPSDK の nxpuuu コマンドではなく、通常の uuu または u-boot コマンドを使用して書き込むことも可能です。
7.2 署名付きOSコンテナ
あらかじめBSP イメージが書き込んであるeMMC もしくはSDカード の boot パーティションに、os_cntr_signed.bin を入れます。
u-boot コマンドで、i.MX95 の接続されたeMMC または SDカードを、USBストレージとしてみせることで、PCにマウントさせます。
シリアル・ダウンロード・ポートをPC に接続しておく必要があります。
// eMMC
u-boot=> ums mmc 0
// SDカード
u-boot=> ums mmc 1
PC にマウントされた boot パーティションに 、os_cntr_signed.bin をコピーしたあと、u-boot で Ctrl-C を押します。
もしくは、別の手段で os_cntr_signed.bin を、boot パーティションに入れておきます。
署名付きOSコンテナの起動時、下記のような表示が出ます。
CONFIG_AHAB_BOOTを有効にした u-boot では、通常のLinux Image (署名なし)ではなく、 os_cntr_signed.bin (署名付き)が使用されます。
7.3 動作確認
この段階では、i.MX95 のライフサイクルの状態は、OEM Open のため、u-boot や Linux が起動しますが、KEY HASH の検証失敗が、ELE イベントで検出されます。
8.1 eFuse 書き込み
i.MX 95 SRKH eFuse に、公開鍵のハッシュ値を書き込みます。
- 一度書き込むと元に戻せません。
- 書き込んだデバイスで、署名付きブートローダや署名付きOS コンテナを更新するときは、書き込んだ SRKH のもととなる公開鍵のペアである秘密鍵を使い署名します。
- 別の鍵ペアを使う場合には、現在のSRKH をRevoke し、4組作成しておいた鍵ペアで未使用のものを使用します。
i.MX 95 ボードのシリアル・ダウンロード・ポートをPCに接続し、 u-boot はあらかじめ fastboot モードにしておきます。
u-boot=> fastboot 0
署名付きイメージの作成で作られたSRKH eFuse のプログラミング用スクリプト(*.bcf) を使い、 SPSDK で書き込みます。
SRKH eFuse のプログラミング用スクリプトには、 i.MX 95 eFuse の word index が記載されています。
// OEM_SRKH
(venv) $ nxpele -f mimx9596 batch output/ahab_oem0_srk0_hash_nxpele.bcf
// OEM_PQC_SRKH
(venv) $ nxpele -f mimx9596 batch output/ahab_oem0_srk1_hash_nxpele.bcf
8.2 eFuse 値の確認
SPSDK の nxpele コマンドで、 eFuse のword index を指定しリードして、値を確認することができます。
// OEM_SRKH[31:0] word index = 128
(venv) $ nxpele -f mimx9596 read-common-fuse -i 128
// OEM_PQC_SRKH[511:480] word index = 463
(venv) nxpele -f mimx9596 read-common-fuse -i 463
など
- SPSDK の代わりに、U-boot コマンド もしくは System Manager モニタのコマンドで、eFuse にリード・ライトアクセスすることもできます。
- U-boot
- u-boot=> fuse read
- u-boot=> fuse prog
- System-Manager
- >$ fuse.r
- >$ fuse.w
8.3 動作確認
この段階では、i.MX 95 のライフサイクルの状態は、OEM Openですが、SRKH プログラム済みのため、改ざんがなければ、ELEイベントは検出されません。
改ざんがあっても、その部分が動作に影響しなければ、OEM Openのため起動しますが、認証の失敗が ELE イベントで検出されます。
i.MX 95 出荷直後のライフサイクルは、OEM Open です。
デバッグ終了後に、i.MX 95 のライフサイクルを OEM Closed に変更します。
OEM Closed にしたあとの留意点
- OEM Openには戻せません。
CONFIG_AHAB_BOOT=yとした u-boot を含んだブートローダで起動すると、署名の無いイメージや、不正な署名付きイメージは起動できなくなります。CONFIG_AHAB_BOOT=yとしていない u-boot を含んだブートローダでは、署名なし Linux Image で起動できてしまいますので、必ず署名付きOS コンテナ os_cntr_signed.bin で起動させるため、CONFIG_AHAB_BOOT=yとした u-boot を含んだブートローダを使用します。- 動作確認後、署名なしのLinux Image やデバイスツリーは、boot パーティションから削除します。
9.1 SPSDK
i.MX 95 ボードのシリアル・ダウンロード・ポートはPCと接続し、u-boot は、あらかじめfastboot モードにしておきます。
u-boot=> fastboot 0
SPSDK でライフサイクルを更新します。
(venv) $ nxpele -f mimx9596 forward-lifecycle-update -l OEM_CLOSED
Forward Lifecycle update ends successfully.
(venv) $
9.2 U-boot
u-boot=> ahab_close
- OEM Closed とした後、 uuu で BSP イメージ (wic ファイル) を書き込む場合にも、署名付きブートローダを使用する必要があります。
ELE (Edgelock Secure Enclave) は、i.MX 95 の内蔵ブロックで、セキュアブート時のコンテナ・イメージの認証を行います。
SPSDK および U-boot、System Manager コマンドで、ELE の状態を確認することができます。
10.1 SPSDK
シリアル・ダウンロード・ポートとPCを接続し、U-boot でfastboot モードにしてから行います。
u-boot=> fastboot 0
SPSDK でELE イベントを取得します。
(venv) $ nxpele -f mimx9596 get-events
10.2 U-boot
CONFIG_AHAB_BOOT=y としたU-boot で使用できるコマンドです。
デバイスのライフサイクルにより、OEM Open または OEM closed も表示されます。
u-boot=> ahab_status
10.3 System Manager
>$ ele events
10.4 表示例
SPSDK
U-boot (OEM open時)
System Manager
SPSDK
U-boot (OEM close後)
System Manager
既存の署名なしブートローダのバイナリに、 SPSDK で直接署名を追加することも可能です。
この場合、SPSDK がブートローダ・バイナリのコンテナから構成を解釈します。
YAML ファイルで、各イメージごとの細かい設定は指定できませんが、コンテナヘッダの設定と秘密鍵および公開鍵のパスを指定するのみで、署名付きブートローダを作成することができます。
11.1 テンプレートの作成
(venv) $ nxpimage ahab get-template -f mimx9596 -o ahab_sign.yaml --sign
(venv) $ cp ahab_sign.yaml sign.yaml
11.2 YAML ファイル
sign.yaml に、コンテナヘッダの設定と秘密鍵および公開鍵のパスを指定します。
YAMLファイルの例 を使用する場合、 direct_signing/sign.yaml をコピーしておきます。
11.3 署名の追加
既存のブートローダのバイナリ flash.bin に署名処理を行います。
// eMMC / SD
(venv) $ nxpimage ahab sign -c sign.yaml -b flash.bin -o output/flash_directsign.bin -fs output
// FlexSPI NOR
(venv) $ nxpimage ahab sign -c sign.yaml -b flash.bin -o output/flash_directsign.bin -fs output -m flexspi_nor
output/flash_directsign.bin と、SRKH eFuse のプログラミング用スクリプト output/*.bcf が作成されます。
SoC 起動イメージの保護を実現するため、i.MX 95 セキュアブートに使用する署名付きイメージを、SPSDK を使って作成し、起動するまでの流れを紹介しました。今回はi.MX 95 AHAB で新たに追加されたPQCを利用する手順例で示しました。
=========================
本投稿の「Comment」欄にコメントをいただいても、現在返信に対応しておりません。
お手数をおかけしますが、お問い合わせの際には「NXPへの技術質問 - 問い合わせ方法 (日本語ブログ)」をご参照ください。
(既に弊社NXP代理店、もしくはNXPとお付き合いのある方は、直接担当者へご質問いただいてもかまいません。)
i.MX95 でのセキュアブートに使用する署名付きのコンテナ・イメージを Secure Provisioning SDK (SPSDK) で作成し、起動する手順をハンズオン形式で学べる内容となっています。
楕円曲線デジタル署名暗号 (ECDSA)と、耐量子暗号 (PQC) ML-DSA 両方の署名認証を行うHybrid boot での実現例を紹介します。
(作業時間:半日 *一度i.MX 95向けの Linux BSP のビルドが完了している前提)