セキュアブートを一時しのぎにしないためのwolfBootのカスタマイズ

wolfBootは、あらゆるタイプの組み込みシステムに対応する汎用セキュアブートローダーです。wolfBoot は当初 32ビットマイクロコントローラーをターゲットにしていました。しかし、今や広範囲に渡るシステムやアーキテクチャ上でセキュアブートソリューションを実装するための完全なフレームワークに成長しました。 これは主にwolfBoot のモジュール性と柔軟性によるものであり、ソリューションを簡単に再構築し、最も特殊なケースにも適応させることが可能です。

この記事では、過去に当社が実際に行ったカスタマイズの例をいくつか紹介します。

外部デバイスに保存されているイメージの更新

このタイプのカスタマイズはおそらく最も一般的です。wolfBoot は、外部ストレージデバイスやそれに類するものとして抽象化できるデバイスとのインターフェイス、つまり「ext_flash」インターフェイスを提供します。 wolfBootは、このインターフェイスを備えるドライバー経由で指定のストレージデバイスのコンテンツにアクセスします:

ext_flash_lock()
ext_flash_write()
ext_flash_read() 
ext_flash_erase()
ext_flash_unlock()

マイクロプロセッサベースの組み込みシステムでは、さまざまなサポートデバイス (USB、SD、eMMC、SSD など) 上のカーネルイメージにアクセスするには、多くの場合、特定のドライバーが必要な「外部」デバイスとして利用することが唯一のソリューションとなります。マイクロコントローラーアーキテクチャには、通常、(コード実行の目的には使えない)永続ストレージとして使用できる外部NOR SPI/QSPIフラッシュメモリが統合されています。

wolfBootには、数種類のSPIフラッシュメモリチップを直接サポートする追加レイヤーがあります。SPIサポートもext_flash APIインターフェイスの上に実装されており、別のレベルの抽象化を提供します。この場合、SPIコントローラを使用して新しいターゲットに移植するには、次のSPI転送関数群を実装するだけですみます。SPIレイヤーは、このインターフェイスを介してフラッシュにアクセスするために必要な関数をリンクします。

spi_init()
spi_cs_on() 
spi_cs_off() 
spi_read() 
spi_write() 
spi_release()

SPIアクセスは、不揮発性メモリやそれ以外をwolfBootで利用できるようにするための手段の 1 つにすぎません。

近隣システムからオンデマンドでダウンロードされたイメージを更新

設計上の選択により、wolfBoot にはストレージデバイスと内部フラッシュメモリへのアクセス以外のネットワークスタックや通信機能は含まれていません。これは、攻撃対象領域が非常に小さくなるため、セキュリティの観点からも利点であり、安全性の観点からも、すべての構造とコードフローが理解しやすく予測可能に保たれます。

場合によっては、ブート段階で他のシステムとの通信が必要となることがあります。これは、ファームウェアイメージや受信したアップデートが別の場所に保存され、2 番目のパーティション用のスペースを確保するためにフラッシュメモリを分割することを避けたい場合に使われる方法です。このような場合、wolfBoot は、隣接システムからファームウェアイメージを取得するために通信チャネル (通常は UART や SPI などのシリアル バス経由) をオープンする必要があります。実際、これは、wolfBootが非対称マルチプロセッサシステムまたは複数の異種コアを備えた一般的なシステムでブートプロシージャを保護する場合にはかなり一般的な要件です。

wolfBoot からリモートコンテンツにアクセスするための推奨される方法は、アドレス指定可能な仮想メモリ空間を抽象化するカスタムext_flashドライバーを定義することです。wolfBootコードベースには、提供されているuart_flash_server POSIXアプリケーションに接続するクライアントエンドポイントを実行するext_uartドライバーのサンプルが含まれています。このサンプルでは、署名および暗号化されたファイルをエクスポートし、wolfBootがそのファイルを処理およびステージングします。EXT_UARTは、外部フラッシュのサポートを物理ストレージのサポートと仮想化された抽象化の両方に拡張できるモードの 1 つです。

サードパーティツールと連携した鍵プロビジョニング

鍵プロビジョニングでは、ファームウェアイメージに署名するためのメインの秘密鍵を生成、保存、および使用するサードパーティ製のツールと連携する場合があります。wolfBootとともに配布される鍵ツールの柔軟性のおかげで、署名プロセス内で鍵ペアを生成またはインポート (公開形式で) することができます。公開鍵は実行時に wolfBootによって利用できるようにアクセスできる必要がありますが、秘密鍵は各本物のファームウェアのヘッダーに署名するために使用されます。 実際の署名操作は、2 つのフェーズに分割することで、マニフェストヘッダーの構成から独立させることができます。この方法では、署名は外部ツールによってのみ実行され、更新操作中にwolfBootが秘密鍵にアクセスすることはありません。 署名手順をカスタマイズする可能性の詳細については、wolfBoot 署名ツールのドキュメントを参照してください。

鍵を「安全な保管庫(secure vault)」に保管

 ファームウェア認証に使用する公開鍵を永続メモリの安全な書き込み保護領域に保存することは、適切なセキュアブートメカニズムにとって最も重要なセキュリティ要件です。多くの場合、書き込み禁止領域からwolfBootを実行し、公開鍵をブートローダーコードとともに C言語の配列に保存しておけば十分です。これは、wolfBoot に実装されているデフォルトのメカニズムです。 keygenツールは公開鍵を生成またはインポートするときに、公開鍵のローカルアーカイブのコピーを2つ作成します。ブートローダーイメージにビルドされるC言語の配列 (keystore.c)、および同じ構造をバイナリ形式で含むバイナリファイル (keystore.der)です。

keystore.cを除外してメモリ上の配列データに公開鍵を保存することを止めることもできます。その代わとして、keystore.derのコンテンツを専用の安全なストレージまたは書き込み保護されたストレージにアップロードする方法をとることができます。wolfBoot が実行時に安全な保管庫にアクセスするためのドライバーの提供が必要です。そのドライバーは、公開鍵、そのサイズ、およびそのアクセス許可マスクを取得するための 3 つの関数をエクスポートするAPIを提供します。キーストアに別の抽象化レイヤーを使用すると、従来のセキュアエレメントやTPMインタラクションを超えてカスタマイズできるインターフェイスが提供され、実行時に公開鍵を処理するためのより複雑な構造を設計できます。キーストア構造に関する詳細については、wolfBootドキュメントページを参照してください。

固有のパーティション/イメージと鍵の組み合わせ

複数段階のブートレイアウトは非常に複雑になる場合があります。私たちの開発チームは、さまざまなレベルのアクセス許可を持つ一連のパーティションとファームウェアイメージを含むブートプロセスを初めて設計する際に、多くのことを学びました。それ以来、公開鍵の特定のサブセットで認証されたファームウェアを使用して、複数のアクターがパーティションの 1 つのサブセットのみを更新できるようにする必要があるいくつかのシナリオに対処してきました。

次のシナリオを考えてみましょう。

セキュアブートローダーと以下の2つのパーティションを備えた組み込みデバイス:

  • 「システム」パーティション (おそらく TEE からセキュア モードで実行)
  • 「アプリケーション」パーティション(登録済みユーザーがアップロードできる構成可能なソフトウェアを含む)

この場合、2 つの個別の鍵が必要です。ユーザーはアプリケーション パーティションの署名付きアップデートのみを送信できる必要があり、メーカーはシステムソフトウェア (および必要に応じてブートローダー自体) をアップデートできる必要があります。この場合の 2 つのレベルの特権には 2 つの個別の鍵ペアが必要です。最初の鍵ペアはユーザーに関連付けることができ、より大きな権限を持つ 2 番目の鍵ペアはメーカーが保持する必要があります。

最新の wolfBootは、キーストア構造のおかげで、最大 15 のターゲットパーティションをサポートしており、これらの各パーティションは、キーストアからの 1 つ以上の公開鍵を使用して認証できます。

wolfBootのファームウェアパッケージは常に0~15の識別番号 (id) に関連付けられており、ファームウェアをインストールする必要があるパーティションを示します。上で説明したシナリオでは、「システム」は id=1 を持ち、「アプリケーション」ソフトウェアは id=2 に関連付けられます。wolfBootは、自己更新手順、つまり、wolfBoot自体の新しい (署名された) バージョンを含むパッケージを更新するために id=0 を予約します。 このメカニズムにより、更新メカニズムはすべての更新の一時ストレージとして同じ更新パーティションを使用できるようになります。これは、wolfBootが受信パッケージを解析し、マニフェストヘッダーを解析して、正しい鍵を使用してパッケージを処理するためです。前述したキーストア内の公開鍵オブジェクト要素には、各鍵を単一のターゲットパーティションIDに関連付けるビットマスクが含まれています。

「非セキュア」ブート

wolfBootは、公開鍵アルゴリズムと鍵サイズのさまざまな組み合わせをサポートします。ただし、要件によっては、ファームウェア認証を外したい場合もあります。wolfBootは、SIGN=NONEを指定してコンパイルした場合には署名検証部分のみが除外されて適切に動作します。更新を容易にするための他の機能はすべて保持され、失敗した場合はロールバックし、SHAを使用した転送後のファームウェアイメージの整合性を検証します。つまり、wolfBootは非セキュア ブートローダーとして使用できます。その際には、フットプリントは数KBで、起動時間への影響はほとんどありません。リソースとCPUサイクルの量が限られている非常に小規模な低電力システムで特に役立ちます。

ライブラリとしての wolfBoot: 従来のブートローダーにセキュア ブートを追加

当社の顧客には、古い製品やデバイスをアップグレードし、以前のバージョンのレガシー ソフトウェアを再利用しながら、セキュアブートソリューションの追加を意味するセキュリティ要件への対応を進めおられる方も多くいらっしゃいます。

新しいブートローダーの開発をスクラッチから開始することは、開発とテストの観点からは過小評価されることが多い作業です。多くの開発チームは、長年にわたって保守され、現場に展開されてきた既存のソリューションに依存しています。一部のカスタムブートローダーソリューションにはネットワーク通信が含まれており、場合によっては独自のプロトコルやデータリンクを使用するため、定番の wolfBoot に統合するには多大な労力が必要になります。一方、これらのレガシー ソリューションのほとんどには、暗号化セキュアブートを実装するために必要なセキュリティ機能がありません。

この理由から、wolfBootをライブラリとして構築する方法を導入しました。ビルドアップ、ステージング、特定のハードウェア アクセス、カスタマイズされたフローを含むブートローダー実装全体を提供する代わりに、「ライブラリとしての wolfBoot」はどこにでも完全に移植可能で、マニフェストヘッダーの解析、バージョン管理の確認、ロードまたはマッピングされたイメージの検証を行うための簡単なインターフェイスを提供します。提供されたキーストアに対する整合性と信頼性を確保するためにメモリ内に保存されます。ホスト上の主要なツールは、形式が同じままであり、ハードウェアやアーキテクチャから完全に独立しているため、wolfBootのフルインストールの場合とまったく同じ方法で使用できます。wolfBootをライブラリとして使用する方法の詳細については、ライブラリAPIに関するドキュメント ページを確認してください。

原文:https://www.wolfssl.com/customized-ad-hoc-secure-boot-wolfboot/