市場出荷に向けてデバッグ機能を閉じる

ここでは、デバッグ機能を閉じる方法とその影響について説明します。

デバッグ機能は開発の効率を向上させるために開発フェーズではなくてはならないもの です。製品が市場に出荷されると市場不良の解析にも効果を発揮します。 しかし、開発者にとって便利であるということは、同時に攻撃者にとっても 便利な解析手段となり得ます。 想定される製品の運用形態によって、デバッグ機能が必須である運用形態もあります。 セキュリティリスクとのトレードオフになる可能性があるので、有効にするかどうかを 検討することをお勧めします。

[重要項目]

デバッグ機能を閉じることは開発者と攻撃者だけでなく、アットマークテクノによる 解析についてもトレードオフになります。閉じられたインターフェースを利用した解析が できなくなることをご留意いただきますようお願いします。

7.1. JTAG を無効化する

Armadillo-IoT ゲートウェイ G4/Armadillo-X2 の出荷時は、JTAG ポートは有効なままで出荷されます。 当たり前ですが JTAG が有効なままだと攻撃者のコードを走らせたり、 メモリをダンプして鍵を抜いたり、平文データを抜いたりと何でも可能です。 市場に出荷される最終段階では JTAG を無効化することをお勧めします。

i.MX 8M Plus では Secure JTAG を有効/無効にする設定と、Secure JTAG 有効時の 3つのモードの設定があります。

Secure JTAG 無効

完全に JTAG が利用できない状態になります。

Secure JTAG 有効 (default)

  1. JTAG enable mode (default)

    • 認証無しで JTAG を有効化できる
  2. Secure JTAG mode

    • チャレンジ & レスポンス認証によって JTAG を有効化できる
  3. No debug mode

    • バウンダリースキャンやパワーモードステータスビットの可視化などテストや ボード接続のチェックを行うための機能を除き、すべてのJTAG機能が無効となる
[注記]

Secure JTAG については詳しくは以下を参照してください。 efuse の情報もあります。

また、内部バスのトレースも無効にすることができます。

必要とするセキュリティレベルに合わせて設定してください。 JTAG を無効化する設定は efuse なので一度書き込むと、そのデバイスの設定を 戻すことはできません。

起動時に uboot のプロンプトを立ち上げて以下のコマンドを実行してください。

Secure JTAG を無効化

[21]:

  • 0 (0x000000): Secure JTAG is enabled (default)
  • 1 (0x200000): Secure JTAG is disabled
u-boot=> fuse prog -y 1 3 0x200000

Secure JTAG の設定

[23:22]:

  • 00 (0x000000): JTAG enable mode (default)
  • 01 (0x400000): Secure JTAG mode
  • 11 (0xc00000): No debug mode
u-boot=> fuse prog -y 1 3 value

内部バスのトレースの無効化を行う

[20]:

  • 0 (0x000000): bus tracing is enabled (default)
  • 1 (0x100000): kill trace enable
u-boot=> fuse prog -y 1 3 0x100000

7.2. SD boot を無効化する

SD boot は SD メディアを挿すだけで起動する便利な機能です。その反面、 SD メディアの盗難や流出によってシステムへの侵入、SD boot を利用した セキュアブート鍵に対する攻撃が考えられます。これらのリスクは、SD boot を無効に することで排除することが可能です。しかし、SD boot はシステムの復旧の役割も 担っています。SD boot を無効化することによって、eMMC boot が起動できない 状態に 陥った場合、合わせてJTAG の無効化が合わせて設定されていると、二度と復旧すること ができないデバイスになる (廃棄するしかない)可能性があることを考慮してください。 SD boot を無効化する設定は efuse なので一度書き込むと、そのデバイスの設定を 戻すことはできません。

ブートモードを eMMC ブートに固定することで SD boot の無効化を実現します。 固定するためには i.MX 8M Plus のハードウェアピンへの参照を無効化して、 efuse のみを起動時に参照するようにします。

以下が efuse (BOOT_MODE_FUSES = 2) のみを参照するための条件になります。 BOOT_MODE_PINS を利用するとハードウェアの攻撃を受ける可能性があるので、 FORCE_BT_FROM_FUSE を 1 にするべきです。

以下はブートモードに関係するポートと efuse です。

BOOT_MODE_PINS: hardware pins

BOOT_MODE_FUSES (0x470[15:12]):

  • 2: USDHC3 (eMMC boot only, SD3 8-bit)

FORCE_BT_FROM_FUSE (0x480[20]):

  • 0: Boot Mode pins
  • 1: Boot from programmed fuses

BT_FUSE_SEL (0x470[28]):

  • 0: Boot mode configuration is taken from GPIOs.
  • 1: Boot mode configuration is taken from fuses.
[注記]

efuse の詳しい仕様は以下を参照してください。

以上のことを理解した上で SD boot を無効化する場合は、 起動時に uboot のプロンプトを立ち上げて以下のコマンド起動してください。

BOOT_MODE_FUSES (0x470[15:12]):

  • 2 (0x2000): USDHC3 (eMMC boot only, SD3 8-bit)
u-boot=> fuse prog -y 1 3 0x2000

FORCE_BT_FROM_FUSE (0x480[20]):

  • 0 (0x000000): Boot Mode pins (default)
  • 1 (0x100000): Boot from programmed fuses
u-boot=> fuse prog -y 2 0 0x100000

BT_FUSE_SEL (0x470[28]):

  • 0 (0x00000000): Boot mode configuration is taken from GPIOs.(default)
  • 1 (0x10000000): Boot mode configuration is taken from fuses.
u-boot=> fuse prog -y 1 3 0x10000000

7.3. BOOT_CFG_LOCK について

efuse はビットの状態によってはビットを書き換えてしまうことが可能です。 また、i.MX 8M Plus は RAM にシャドウされた値を参照しています。

攻撃者によって efuse やシャドウの変更によって、デバイスの挙動を変えられてしまう 可能性があります。 i.MX 8M Plus には efuse をロックする機能があります。 出荷前にロックすることをお勧めします。

BOOT_CFG_LOCK は 0x470-4B0 の範囲の efuse をロックすることができます。 本手順書で言及している efuse 以外も範囲に含まれます。影響範囲を確認してから の作業をお勧めします。

ロック範囲については以下を参照してください。

[注記]

efuse の詳しい仕様は以下を参照してください。

efuse のロック を行う場合は 起動時に uboot のプロンプトを立ち上げて、 以下のコマンドを実行してください。

  • 00 (0x0): no protect (default)
  • 01 (0x4): WP (write protect)
  • 10 (0x8): OP (overridden protect)
  • 11 (0xc): OP (overridden protect) and WP (write protect)
u-boot=> fuse prog -y 0 0 0xc

7.4. u-boot の環境変数の変更を制限する

Armadillo Base OS の u-boot は eMMC の固定の領域から環境変数を読み取っています。

本来の使い方ではユーザーはその eMMC の領域に書込みできませんが、eMMC が外部から変更されたとしても Linux が正しいシーケンスで起動するようにしたい場合は、 u-boot の環境変数をある程度ロックした方が安全です。

imx-boot バージョン 2020.04-at23 以降では、uboot-imx/configs/x2_defconfigCONFIG_ENV_WRITEABLE_LIST=y を追加すると、変更可能と明示した環境変数以外は変更できなくなります。

その変更可能の環境変数のリストは uboot-imx/include/configs/armadillo_x2.h ファイルの CFG_ENV_FLAGS_LIST_STATIC で設定します。

提供しているコンフィグでは、以下の環境変数が変更可能です:

  • upgrade_availablebootcount: ロールバック機能に必要な変数です。ロールバック機能を無効にする場合は必ず upgrade_available のデフォルト値も空にしてください。
  • encrypted_update_available, dek_spl_offsetdek_fit_offset: 暗号化されている imx-boot の書込みに必要な変数です。 imx-boot を暗号化しない場合は削除できますが、残したままでも影響ありません。
  • ethaddr, eth1addr, ethactethprime: ネットワークコマンド関連の変数です。デフォルトのブートコマンドにネットワークを使用してませんので動作に影響ありません。

また、Linux を起動して fw_printenv 等を使用しても Linux 側ではデフォルト値や変更可能の環境変数リストは把握していないので信頼性が低いです。 変数の値に疑いがある場合は u-boot の prompt で確認してください。

設定を行った後に 「署名済みブートローダーの作成」「署名済みの暗号化ブートローダーの作成」 の手順どおりにリビルドすると、CFG_ENV_FLAGS_LIST_STATIC にリストされている環境変数以外は変更できなくなります。

7.5. u-boot プロンプトを無効にする

Armadillo Base OS の u-boot はデフォルトで autoboot が有効になっています。 autoboot が有効な状態では決まったディレイ (bootdelay) の間キー入力を待ち、 入力がなければ自動的に bootcmd を実行して Linux を起動します。 一方、決まった時間にキー入力があるとプロンプトが表示されて、 様々なコマンドを実行することができます。 これらのコマンドはとても便利なものですが、攻撃者にとっても 攻撃を仕掛けるために有効な手段となり得ます。 ここでは、決まった時間待つ処理を無効化する方法を説明します。

bootdelay
  • 2 : デフォルト。2秒待つ
  • 0 : 待ち時間なし。ただしキー入力でプロンプトが表示される
  • -1 : autoboot が無効
  • -2 : 待ち時間なし。キー入力も無効

「u-boot の環境変数の変更を制限する」 の手順を行った場合は imx-boot の uboot-imx/configs/x2_defconfig に「CONFIG_BOOTDELAY=-2」を追加して変更してください。

環境変数が変更可能な場合は Armadillo Base OS の /boot/uboot_env.d/no_prompt の様なファイルを作って、 そちらに変数を設定すれば今後のアップデートにも適用されます。

詳細は製品マニュアルを参考にしてください。

[armadillo ~]# vi /boot/uboot_env.d/no_prompt 1
# bootdelay を -2 に設定することで u-boot のプロンプトを無効化します
bootdelay=-2
[armadillo ~]# persist_file -v /boot/uboot_env.d/no_prompt 2
'/boot/uboot_env.d/no_prompt' -> '/mnt/boot/uboot_env.d/no_prompt'
[armadillo ~]# fw_setenv -s /boot/uboot_env.d/no_prompt 3
Environment OK, copy 0
[armadillo ~]# fw_printenv | grep bootdelay 4
bootdelay=-2

1

コンフィグファイルを生成します。

2

ファイルを永続化します。

3

変数を書き込みます。swupdate で書き込む場合は自動的に行われています。

4

書き込んだ変数を確認します。

[警告]

「u-boot の環境変数の変更を制限する」 を行ってない場合に CONFIG_BOOTDELAY は無視されます。 必ず CONFIG_ENV_WRITEABLE_LIST も設定するか、/boot/uboot_env.d で設定してください。

[ティップ]

ここで説明した以外にもいくつかの方法があります。 ソースコードにドキュメントがあります。 以下を参照してください。

imx-boot-[VERSION]/uboot-imx/doc/README.autoboot