UEFIの機能の一つに,
あなたのブートローダーとカーネルを見守るセキュアブート
「セキュアブート
セキュアブートが機能しているかどうかは,dmesg
コマンドの内容で確認できます
$ dmesg | grep Secure [ 0.000000] Secure boot enabled
- ※1
- この出力を行うコードはUbuntuのカーネルには存在するものの,
アップストリームのカーネルには存在しません。Ubuntu以外のディストリビューションでも汎用的に確認したいとなると, たとえば 「 /sys/
」firmware/ efi/ efivars/ SecureBoot* の5バイト目が1かどうかで判断するという方法があります。
セキュアブートの仕組み
Ubuntuのセキュアブート対応を解説する前に,
セキュアブートを有効化すると,
- Platform Key (PK)
- Key Exchange Key (KEK)
- db/
dbx
- ※2
- 以降は単に
「鍵」 と記述し, 対になる秘密鍵については明示的に 「秘密鍵」 と表現します。 - ※3
- UEFI Spec 「30.
3 Firmware/ OS Key Exchange: creating trust relationships」 - ※4
- UEFI Spec 「7.
2 Variable Services」
「Platform Key」
「Key Exchange Key」
「db」
- ※5
- プラットフォームによっては
「dbr」 や 「dbt」 といった変数もあります。 「dbr」 はOSリカバリー時に参照する署名データベースです。 「dbt」 はタイムスタンプを保存する変数でUEFI 2. 4で追加されました。 「dbt」 を使うと 「特定の鍵に対してこのタイムスタンプ以降に署名されたバイナリのみ実行を不許可にする」 ことが実現できます。ちなみにいずれの変数にも 「PKDefault」 や 「dbDefault」 といった, ファームウェアの初期化時に設定する変数も存在します。
セキュアブートによる起動の流れ
UEFIファームウェアの実装の一つであるOVMFを参考に,DxeImageVerificationHandler()
において,
- 実行するバイナリから署名データを取り出す
- 署名データがない場合はバイナリのSHA256ハッシュを計算する
- dbxにハッシュもしくは署名データ,
署名した人の公開鍵のいずれかが存在したら実行を拒否する - dbにハッシュもしくは署名データ,
署名した人の公開鍵のいずれかが存在したら実行を許可する
つまりセキュアブートが有効化された環境で起動時に参照するUEFI変数はdbxとdbのみです。この変数が正しく設定されていれば,
UEFIの実行バイナリはMicrosoft Windowsと同じPE/file
コマンドを使えば,
$ file /usr/lib/shim/shim.efi.signed /usr/lib/shim/shim.efi.signed: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows
- ※6
- UEFI Spec 「30.
2.2 Embedded Signatures」
- ※7
- PEヘッダー領域にある
「Optional Header Windows-Specific Fields」 のSubsystemフィールドを見ることで, どのタイプのWindows向けのバイナリかを判定できます。このタイプの中にはEFIアプリケーションやEFIドライバー, Xboxなども含まれているのです。 file
コマンドではこのフィールドからバイナリが「EFI application」 用であると判定しています。