Shimはセキュアブートでバイナリをどのように検証しますか?


3

UEFIシムローダー

shimは、実行時に別のアプリケーションを開いて実行しようとする簡単なEFIアプリケーションです。最初に、標準EFI LoadImage()StartImage()呼び出しを介してこれを実行しようとします。これらが失敗した場合(たとえば、セキュアブートが有効になっていて、バイナリが適切なキーで署名されていないため)、組み込みの証明書に対してバイナリを検証します。これが成功し、バイナリまたは署名キーがブラックリストに登録されていない場合、shimはバイナリを再配置して実行します。

セキュアブートオプションが有効になっているときに検証手順がどのように行われるかを理解するために読んでいます。

vmlinuz * -genericと* -generic.efi.signedの違い

セキュアブートは実際にどのように機能しますか?

Linux用EFIブートローダーの管理:セキュアブートの制御

これで手順は次のようになります。

シムは、最初にマシンのファームウェアによって実行されます。ここで、shimはブートローダーを実行する必要があります。私が理解していないのは、shimがバイナリを検証する方法ですか?たとえば、上記の引用段落では、shimは標準EFI LoadImage()を介して他のアプリケーションを起動しようStartImage()とし、これが失敗すると、shimは組み込み証明書からバイナリを検証しようとします。この組み込み証明書はシムに属しますか?本質的に、シムがマシンオーナーキーマネージャー(MOK)と呼ばれるのはなぜですか?バイナリを検証するための独自のキーのデータベースがあるためです。

簡単に言えば、マシンのファームウェアには、NVRAMにバイナリを検証するための独自のキーのデータベースがあり、シムにはバイナリを検証するための独自のキーのデータベースがありますか?

ブートローダーが検証および実行された後、ブートローダーは、たとえばファームウェアのキーのデータベースから、ブートする必要のある署名付きカーネルのキーを見つけるためにどこを探しますか?

回答:


4

あなたが正しく推測きたように、SHIMからロードしようLoadImage()StartImage()最初に。次に、EFIは署名が一致することを検証します(内部SecureBootメカニズムの使用により)。をLoadImage()返したEFI_SECURITY_VIOLATION場合、システムは内部証明書からstage2(この場合はGRUB2)のフォールバックロードを試みます。

この証明書はコンパイル時にシステムに組み込まれます。この場合、Canonicalによって行われました。この証明書binwalk、または類似のユーティリティを使用してSHIMから抽出できます。

事実上、これによりSecureBoot shimはキャッシュに保存された検証済みの署名を取得でき、それによりshimGRUBが前述の証明書で署名されたことを確認できます。そうだった場合、GRUBは正常に起動します。

可能な限りシムは、システムキーを使用します-理由であるLoadImage()とは、StartImage()最初に使用されています。動作しない場合にのみ、SHIMは独自の内部証明書でstage2をロードしようとします。チェーンの一部で呼び出されるこのコード(の一部)をここで見ることができます。verify_bufferhandle_image

検証チェーン全体は次のようになります。

  1. システムハッシュとMOKリストを確認する
  2. バイナリがブラックリストに載っていないことを確認してください
  3. MOK / BIOSホワイトリストを介してバイナリをチェックしてみてください
  4. ビルドキーとSHIM独自の内部キーで定義されている内部署名をチェックします。

MOK ManagerがMOKデータベースそのものではないことも重要です。後者は、EFIファームウェアによって維持されます。これは、フラッシュ中に製造元に追加/削除するコマンドと、オペレーティングシステム(この場合はshim)のコマンドを受け取ります。shim前述のコンパイルされたキーの非常に短いリストのみを保存して、ブートを許可します-その他はすべてEFIファームウェアで処理する必要があります。


「動作しない場合にのみ、SHIMは独自の内部証明書を使用してstage2をロードしようとします。」シムが別のバイナリに代わって証明書を提供することでUEFIをだますと言うのは正しいですか?ただし、UEFIはだまされていますが、SHIMは独自のキーチェックを実行します。つまり、2つのチェックがあります(1)UFEIキー検証(最初)、これが失敗したとき(2)SHIMはUEFIに独自の証明書を提供し、UEFIのキーを使用せずに独自のキー検証を実行し、代わりにSHIMに静的に組み込まれます。
-direprobs

正直なところ、SHIMが何をしているのかを理解することはできません。私が知る限り、SHIMは独自の証明書を使用してUEFIを欺き、見つかったもの(署名されたもの)を勝手に実行します。または、少なくとも、それが私が現在理解している方法です。
カズウルフ

4

Kaz Wolfeの答えはかなり良いですが、私はいくつかの点を強調し、拡大したいと思います。

私が最後にチェックしたとき、Shimは基本的に、一種の並行セキュアブート検証機能を提供しました。GRUBはEFIプログラムではないLinuxカーネルを起動するように設計されています。したがって、Shimは、後続プログラムがShimを呼び出してバイナリが署名されていることを確認できるように、EFIに自身を登録します。Shimは次の2つの方法のいずれかで行います。

  • Shimの組み込みキー-Ubuntuの一部として提供されるものを含むほとんどのShimバイナリには、組み込みのセキュアブートキーが含まれています。UbuntuのShimには、UbuntuのGRUBおよびLinuxカーネルを検証するCanonicalの公開キーが含まれています。したがって、このキーはRAMに保存され、これらが進むにつれて一時的になります。Shimの主なポイントは、後続のプログラム(GRUB)がセキュアブートタイプの検証を実行できるようにすることですが、GRUBは実際にセキュアブートの検証を実行しません。Shimがなければ、CanonicalはGRUBのすべての新しいリリースとすべての新しいLinuxカーネルに署名するためにMicrosoftに依存する必要があります。
  • マシン所有者キー(MOK) -MOKは基本的にShimの組み込みキーの拡張ですが、通常のユーザーが操作するためのものです。Canonicalのキーで署名されていないバイナリを起動する場合は、MOKを使用できます。MOKは、ファームウェアの組み込みセキュアブートキーと同様に、NVRAMに保存されます。MokManagerと呼ばれるプログラムを介して、NVRAMに簡単に追加できます。MOKをNVRAMに入れることは、ほとんどの人が気にしないほど面倒であり、多くの人が問題を抱えています。参照した私のページで説明されているように、セキュアブートサブシステムを完全に制御するよりも簡単です(Linux用EFIブートローダーの管理:セキュアブートの制御)。

ほとんどの場合、MOKは使用されません。WindowsとUbuntuをデュアルブートする場合は、おそらくファームウェアの組み込みキーとUbuntuのShimバイナリに埋め込まれたキーでうまくいくでしょう。別のLinuxディストリビューションを追加したり、独自のカーネルをコンパイルしたり、GRUB以外のブートローダーを使用したり、サードパーティのカーネルモジュールを使用したい場合は、MOKを使用します。

これらの2つのソースに加えて、ファームウェアにはセキュアブートキーも組み込まれています。Shimがこれらのキーを使用するかどうかは思い出せません。それは考え暗黙的にそれがEFIの使用している場合は、それらを使用LoadImage()してStartImage()コール(それがないが、私はこの答えのコンテキストを検討していません)。私の記憶では、GRUBがコールバックしてカーネルが署名されているかどうかを確認するときに、独自の検証コードはファームウェアのセキュアブートキーを使用しませんが、それを正しく覚えていない可能性があります。

Shimがセキュアブートシステムにどのように統合されるかについては、最後に確認しましたが、そうではありませんでした。IIRCは、その後続プログラム(GRUB)を起動するために、Tianocore UEFIサンプル実装のコードの簡略版に似た独自のバイナリ読み込みコードを実装しています。このコードは、Shimの独自のセキュアブート検証コードを呼び出します。このコードは、組み込みキーとローカルMOKリストに対してバイナリをチェックし、バイナリを起動します。(ファームウェアの独自のセキュアブートキーを使用することもありますが、私はそうは思いません。)GRUBがロードされると、Shimのバイナリ検証機能を呼び出して、Linuxカーネルを検証します。 EFIがEFIプログラムを起動する方法)。したがって、Shimは実際にはファームウェアにあまり深く統合されていません。1つまたは2つの機能を後続のプログラムで使用できるようにするだけです。LoadImage()そして、StartImage()EFI機能変わりません。

とはいえ、EFIは通常のEFIシステムコールを置換または補完する方法を提供し、一部のツールはこれらの方法を使用します。たとえば、Shimの機能と同様のことを行うツールであるPreLoaderプログラムは、ファームウェアにさらに深く統合されました。通常のUEFIセキュアブートキー MOKの両方StartImage()をチェックするように、破損または廃止された機能にパッチを適用して修正するように設計されたEFIシステムコールを使用しました。PreLoaderは道端でかなり落ちています。その開発者とShimの開発者は、標準のLinuxセキュアブートツールとしてPreLoaderではなくShimに焦点を当てるために協力しています。知る限りでは、ShimはPreLoaderのより深いUEFI統合を採用していません。ただし、コードを非常に詳しく調べてからしばらく経ちましたので、これについては時代遅れかもしれません。とはいえ....

私自身のrEFIndブートマネージャは、PreLoaderプログラムから取得したコードを使用して、Shimのバイナリ検証コードをUEFIの通常の検証サブシステムに「接着」します。したがって、図のrEFIndを使用してLoadImage()StartImage()最初にShim認証コードを使用してEFIプログラムを起動して呼び出し、それが失敗した場合、標準のUEFIセキュアブート認証を次に呼び出します。gummiboot / systemd-bootブートマネージャーは、同様のことを行います。両方のプログラムがこれを行うのは、EFIスタブローダーを介してLinuxカーネルを起動するためです。つまり、EFI LoadImage()StartImage()呼び出しに依存するためです。これは、独自の方法でLinuxカーネルを起動するフルブートローダーであるGRUBとは対照的です。したがって、GRUBは、ShimのキーまたはローカルMOKリストを認識するためにこれらのEFIシステムコールを必要としません。

これが物事を明確にするのに役立つことを願っていますが、どうなるかはわかりません。このすべての作業の詳細は非常に乱雑であり、詳細に対処してからしばらく経ちました。そのため、私自身の考えは整理されていません。


確かに、セキュアブートがセキュリティを確保することを意図している場合、その複雑さは望ましくないだけです。幸いなことに、私のファームウェアでは、必要に応じてキーを追加および操作できますが、いくつかのカーネルモジュールには独自のキーがないため、セキュアブートを無効にします。
-direprobs

また、驚くべきことに、dbキーをチェックしたときに、そこにCanonical署名があります。おそらく、このCanonicalキーはGrubの検証に使用されるのでしょうか?そして、あなたの答えから私が理解していることは、UFEIのシステムコールにパッチを適用できる可能性があるということですか?
-direprobs

1
Canonicalのキーは一部のコンピューターのファームウェアに含まれていますが、これはまれです。(私自身はASUS P8 H77-Iマザーボードでしか見ていません。)そのようなコンピューターは、Shimを使用せずにセキュアブートを有効にすると、UbuntuのGRUBを直接起動できます。サードパーティのカーネルモジュールに自分で署名できます。1つのアプローチについては、この質問に対する私の答えをご覧ください。はい、多くのEFIシステムコールはEFIプログラムによって修正できます。
ロッドスミス

@Rob Smith私はAsusを持っています。
-direprobs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.