REFInd
セキュアブートとは、UEFI 規格に含まれているセキュリティ機能であり、プリブートプロセスに保護レイヤを追加するために設計されました。起動時の実行を許可/禁止されているバイナリの暗号署名されたリストを保持することにより、マシンのコアブートコンポーネント (ブートマネージャ、カーネル、initramfs) が改ざんされていないという信頼性を高めるのに役立ちます。
なので、セキュアブートは、コンピュータ環境をセキュアに保つ試みの一環、あるいはそれを補完するものであるとみなせます。システムの暗号化のような他のソフトウェアのセキュリティ対策では簡単にカバーできない攻撃対象領域を減らしますが、完全に異なったものであり、それらに依存していません。セキュアブートは、独自の長所と短所を備えた、現在のセキュリティ慣例の一つの要素として独立しています。
目次
- 1 セキュアブートの状態を確認する
- 2 インストールメディアを起動する
- 3 セキュアブートを実現する
- 3.1 自分の鍵を使う
- 3.2 署名済みのブートローダを使う
- 4 セキュアブートを保護する
- 5 ヒントとテクニック
- 6 参照
セキュアブートの状態を確認する
OS の起動前
OS の起動前にセキュアブートの状態を確認するには、ファームウェアのセットアップ画面を見る必要があります。すでにマシンが起動済みであれば、ほとんどの場合再起動する必要があります。
起動プロセス中に特別なキーを押すことでファームウェアのセットアップ画面にアクセスできます。それがどのキーかはファームウェアに依りますが、通常 Esc
、F2
、Del
のどれかです。もしかするとその他のファンクションキーかもしれません。ファームウェアによっては、どのキー押すべきかが起動プロセスの開始時に短い時間表示されます。通常、マザーボードのマニュアルにキーが記載されています。マシンの電源を入れたらすぐに(スクリーンが表示されるよりも前に)キーを押して、そのまま押し続ける必要があるかもしれません。
ファームウェアのセットアップ画面に入ったら、意図せずに設定を変更してしまわないよう気をつけてください。通常、セットアップ画面の下部に案内指示や設定の短いヘルプがあります。セットアップ自体はいくつかのページから構成されているかもしれません。それらのページの中から正しい場所に移動する必要があります。設定は単に「セキュアブート」と表示されるかもしれません(これでオン/オフを設定できます)。
OS の起動後
systemd を使用するシステム上では、systemd-boot でセキュアブートの状態を簡単に確認できます:
$ bootctl status System: Firmware: UEFI 2.70 (American Megatrends 5.15) Secure Boot: enabled Setup Mode: user Boot into FW: supported ...
ここでは、セキュアブートが有効化され強制されていることがわかります。他に取りうる値は、"Secure Boot" は disabled
、"Setup Mode" は setup
です(例)。
マシンがセキュアブートで起動されているかどうかを調べる他の方法は、以下のコマンドを使用することです:
$ od --address-radix=n --format=u1 /sys/firmware/efi/efivars/SecureBoot*
セキュアブートが有効化されている場合、このコマンドは5桁の数値を出力し、最後の値が 1
となります。例えば:
6 0 0 0 1
しかし、機能が不十分なブートローダを使用している場合、(ファームウェアで有効になっている場合でも) カーネルがセキュアブートを検出できない場合があります。これは、システムの起動直後にカーネルのメッセージを確認することで確認できます:
# dmesg | grep -i secure
[ 0.013442] Secure boot disabled [ 0.013442] Secure boot could not be determined
セキュアブートが検出された場合、カーネルメッセージは Secure boot enabled
となります。
インストールメディアを起動する
公式の Arch インストールイメージはセキュアブートをサポートしていません (FS#53864)。Arch インストールメディアのセキュアブートサポートは archlinux-2013.07.01-dual.iso
で初めて追加されました。しかし、その後 archlinux-2016.06.01-dual.iso
で削除されました。その時、prebootloader は、未署名の EFI バイナリを使用する efitools に置き換えられました。それ以降、公式のインストールメディアにセキュアブートのサポートが追加されることはありませんでした。
インストールメディアをセキュアブートのシステムでブートするには、セキュアブートを無効化するか、イメージを変更して署名されたブートローダを追加する必要があります。
Archboot イメージはインストールメディアでセキュアブートを使用する手段を提供します。
セキュアブートを無効化する
セキュアブートの機能は UEFI インターフェイスを通して無効化できます。ファームウェアの設定画面にアクセスする方法は #OS の起動前 で説明されています。
ホットキーが使用できず Windows が起動する場合、次の方法で強制的にファームウェア設定を開くように再起動できます (Windows 10 の場合): Settings > Update & Security > Recovery > Advanced startup (Restart now) > Troubleshoot > Advanced options > UEFI Firmware settings > restart。
一部のマザーボード (例: Packard Bell 製ノートパソコンや最近の Xiaomi ノートパソコン) では、管理者パスワードを設定しないとセキュアブートを無効化できません (無効化した後に管理者パスワードは消去できます)。Rod Smith の Secure Boot 無効化に関する記事 も参照。
インストールイメージを再パックする
#ブートローダを PreLoader に置き換える を見てください。
インストールメディアを編集する
USB インストールメディアを使用している場合、そのメディア上の EFI システムパーティションを手動で編集してセキュアブートのサポートを追加することが可能です。
USB ドライブを挿入し、EFI システムパーティションをマウントしてください:
# mount /dev/disk/by-label/ARCHISO_EFI /mnt
そして、#署名済みのブートローダを使う の指示に従って、署名済みのブートローダをインストールしてください。例えば、#PreLoader をインストールするには:
# mv /mnt/EFI/BOOT/BOOTx64.EFI /mnt/EFI/BOOT/loader.efi # cp /usr/share/preloader-signed/PreLoader.efi /mnt/EFI/BOOT/BOOTx64.EFI # cp /usr/share/preloader-signed/HashTool.efi /mnt/EFI/BOOT/HashTool.efi
セキュアブートを実現する
セキュアブートの理想的なセットアップを実現するにはいくつか条件があります:
- UEFI がほぼ信頼されていて(しかし、いくつかのよく知られた批判と脆弱性[1]がある)、必ず強力なパスワードで保護されていること。
- メーカー/サードパーティーのデフォルトの鍵は、セキュアブートのセキュリティモデルを大幅に弱化させることが判明しているので、使用しないこと。[2]
- セキュアブートによって確立された信頼の鎖をブート中に維持して攻撃面を減らすために、マイクロコード(必要な場合)と initramfs を含む、ユーザ署名済み結合 EFISTUB カーネルイメージ(ブートマネージャ無し)を UEFI が直接ロードすること。
- マシンへ物理的にアクセスできる誰かが、カーネルイメージの作成と署名プロセスで使用されるツールとファイルにアクセスしたり改ざんしたりできないようにするために、ドライブの完全暗号化を使用すること。
- TPM を使うことでさらに改善することができるかもしれませんが、ツールやサポートの問題がこれを難しくしています。
- GRUB ブートローダを使うには、セキュアブートを有効化する前に追加の手順が必要になります。詳細は GRUB#セキュアブートサポート を参照してください。
シンプルかつ完全に自立したセットアップは #自分の鍵を使う で説明されています。一方、#署名済みのブートローダを使う では、サードパーティにより署名された中間ツールを使用します。
自分の鍵を使う
セキュアブートでは以下の鍵が使われます:
- Platform Key (PK)
- トップレベル鍵
- Key Exchange Key (KEK)
- Signature Database や Forbidden Signatures Database の更新に署名するのに使われる鍵
- Signature Database (db)
- EFI バイナリに署名するのに使われる鍵やハッシュが含まれます
- Forbidden Signatures Database (dbx)
- EFI バイナリを拒否リストに追加するために使われる鍵やハッシュが含まれます
より詳細な説明は The Meaning of all the UEFI Keys を見てください。
セキュアブートをを使用するには最低でも PK, KEK, db 鍵が必要です。KEK, db, dbx 証明書は複数追加できますが、Platform Key はひとつしか使えません。
Secure Boot を "User Mode" にすると、上位の鍵を使用してアップデートに署名しないかぎり鍵を更新できなくなります (sign-efi-sig-list を使用)。Platform key は自分自身で署名することができます。
現在の変数をバックアップする
新しい鍵を作成したり EFI 変数を変更したりする前に、現在の変数をバックアップしておくことを推奨します。そうすれば、エラーが発生した場合に変数を復元できます。
主要なセキュアブートの変数4つを全てバックアップするには、efitools パッケージをインストールし、以下のコマンドを実行してください:
$ for var in PK KEK db dbx ; do efi-readvar -v $var -o old_${var}.esl ; done
新しいコンピュータやマザーボードでこれらのコマンドを実行する場合、抽出される変数はおそらくマイクロソフトにより提供されたものでしょう。
ファームウェアを "Setup Mode" にする
Platform Key が削除されると、セキュアブートは Setup Mode になります。ファームウェアを Setup Mode にするには、ファームウェア設定ユーティリティに入り、証明書を削除/クリアするオプションを探してください。設定ユーティリティに入る方法は #OS の起動前 で説明されています。
sbctl でプロセスをアシスト
sbctl は、セキュアブートをセットアップしたりファイルを署名したりするユーザーフレンドリーな方法です。
使用するには sbctl をインストールしてください。upstream README と sbctl(8) も参照してください。
キーを作成・登録する
始める前に、ファームウェアの設定画面に行き、セキュアブートのモードを Setup mode にしてください。これはデバイスごとに異なります。
ログインし直したら、セキュアブートの状態を確認してください:
$ sbctl status
sbctl がインストールされておらず、セキュアブートが無効化されていることを確認できるはずです。
次に、カスタムのセキュアブート鍵を作成してください:
# sbctl create-keys
あなたの鍵を Microsoft の鍵と一緒に UEFI に登録してください:
# sbctl enroll-keys -m
セキュアブートの状態を再び確認してください:
$ sbctl status
sbctl がインストールされているはずです。しかし、あなたの鍵でブートファイルを署名するまで、セキュアブートは動作しません。
署名
セキュアブートを動作させるために署名が必要なファイルを確認します:
# sbctl verify
次に、署名されていないすべてのファイルに署名します。通常、カーネルとブートローダーには署名が必要です。例えば:
# sbctl sign -s /boot/vmlinuz-linux # sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI
署名が必要なファイルは、システムのレイアウト、カーネル、ブートローダーによって異なります。
これで完了です! システムを再起動し、ファームウェアの設定でセキュアブートをオンに戻してください。ブートローダーとOSがロードされれば、セキュアブートは機能しているはずです。以下のコマンドで確認してください:
$ sbctl status
pacman フックを使って自動的に署名する
sbctl には、Linux カーネル、systemd、ブートローダーがアップデートされたときに自動的にすべての新規ファイルを署名する pacman フックが同梱されています。
手動による手順
efitools をインストールする
以下のほぼ全てのセクションで、efitools パッケージがインストールされている必要があります。
鍵の生成
鍵を生成するには以下の手順を行ってください:
秘密鍵と複数の形式の証明書を作成する必要があります:
.key
- EFI バイナリと EFI 署名リストの署名に必要な PEM 形式の秘密鍵。
.crt
- sbsign(1)、sbvarsign(1)、sign-efi-sig-list(1) で必要な PEM 形式の証明書。
.cer
- ファームウェアが使用する DER 形式の証明書。
.esl
- sbvarsign(1) や efi-updatevar(1)、KeyTool、ファームウェアのための EFI 署名リストの証明書。
.auth
- efi-updatevar(1) や sbkeysync、KeyTool、ファームウェアのための認証ヘッダが付いた EFI 署名リストの証明書 (つまり、署名済みの証明書アップデートファイル)。
所有者を識別する GUID を作成してください:
$ uuidgen --random > GUID.txt
Platform key:
$ openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Platform Key/" -out PK.crt $ openssl x509 -outform DER -in PK.crt -out PK.cer $ cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl $ sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth
"User Mode" で Platform Key を削除できるようにするために空のファイルを署名してください:
$ sign-efi-sig-list -g "$(< GUID.txt)" -c PK.crt -k PK.key PK /dev/null noPK.auth
Key Exchange Key:
$ openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Key Exchange Key/" -out KEK.crt $ openssl x509 -outform DER -in KEK.crt -out KEK.cer $ cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl $ sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth
Signature Database key:
$ openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=my Signature Database key/" -out db.crt $ openssl x509 -outform DER -in db.crt -out db.cer $ cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl $ sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth
ヘルパースクリプト
便利なヘルパースクリプトがこのトピックの参照メージの著者により提供されています[3](python が必要です)。簡単に編集されたバージョンも sbkeysAUR としてパッケージングされています。
スクリプトを使うには、安全な場所にフォルダを作成し(例えば、後で sbupdate-gitAUR を使って unified カーネルイメージを作成し署名する予定なのであれば /etc/efi-keys/
)、スクリプトを実行してください:
# mkdir /etc/efi-keys # cd !$ # curl -L -O https://www.rodsbooks.com/efi-bootloaders/mkkeys.sh # chmod +x mkkeys.sh # ./mkkeys.sh 鍵に埋め込む Common Name を入力 (例: "Secure Boot")
これは様々な形式で必要なファイルを生成します。
ファームウェアに鍵を登録する
db、KEK、PK 証明書を登録するには、以下に述べる方法のうち1つを使ってください。
sbkeysync を使う
sbsigntools をインストールしてください。そして、以下のディレクトリ構造を持つ /etc/secureboot/keys
ディレクトリを作成してください:
/etc/secureboot/keys ├── db ├── dbx ├── KEK └── PK
例えば、以下のように:
# mkdir -p /etc/secureboot/keys/{db,dbx,KEK,PK}
そして、先程生成した .auth ファイルをそれぞれの場所にコピーしてください(例えば、PK.auth
は /etc/secureboot/keys/PK
へといった感じです)。
sbkeysync
がシステムの UEFI に加える変更を確認したい場合は、以下を使用してください:
# sbkeysync --pk --dry-run --verbose
最後に、sbkeysync
を使って鍵を登録してください。
# sbkeysync --verbose # sbkeysync --verbose --pk
次の起動時に、UEFI は User Mode に戻り、セキュアブートポリシーを強制するはずです。
ファームウェアのセットアップユーティリティを使う
FAT でフォーマットされたファイルシステム (EFI システムパーティション が使えます) に noPK.auth
ファイルを除いて *.cer
、*.esl
、*.auth
をすべてコピーしてください。
ファームウェアのセットアップユーティリティを起動し、db、KEK、PK 証明書を登録してください。ファームウェアのインターフェイスは様々です。鍵を登録する方法の例は Replacing Keys Using Your Firmware's Setup Utility を見てください。
使用するツールがサポートしていれば、.cer よりも .auth と .esl を使用することを推奨します。
KeyTool を使う
KeyTool.efi
は efitools パッケージに含まれています。それを ESP にコピーしてください。鍵を登録した後にこのツールを使うには、sbsign
で署名してください。
# sbsign --key db.key --cert db.crt --output esp/KeyTool-signed.efi /usr/share/efitools/efi/KeyTool.efi
ファームウェアのセットアップユーティリティかブートローダか UEFI シェルを使って KeyTool-signed.efi
を起動して、鍵を登録してください。
KeyTool メニューオプションの説明は Replacing Keys Using KeyTool を見てください。
EFI バイナリに署名する
セキュアブートを有効化(つまり "User Mode" に)すると、署名した EFI バイナリ(例: アプリケーション、ドライバ、Unified カーネルイメージ)しか起動できなくなります。
sbsigntools を使う
sbsigntools をインストールして、sbsign(1) で EFI バイナリに署名してください。
カーネルとブートマネージャに署名するには、sbsign を使用してください。例えば:
# sbsign --key db.key --cert db.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux # sbsign --key db.key --cert db.crt --output esp/EFI/BOOT/BOOTx64.EFI esp/EFI/BOOT/BOOTx64.EFI
mkinitcpio のポストフックでカーネルに署名する
mkinitcpio のポストフックを使って、initramfs の生成時にカーネルイメージに署名することもできます。
/etc/initcpio/post/kernel-sbsign
#!/usr/bin/env bash kernel="$1" [[ -n "$kernel" ]] || exit 0 # use already installed kernel if it exists [[ ! -f "$KERNELDESTINATION" ]] || kernel="$KERNELDESTINATION" keypairs=(/path/to/db.key /path/to/db.crt) for (( i=0; i<${#keypairs[@]}; i+=2 )); do key="${keypairs[$i]}" cert="${keypairs[(( i + 1 ))]}" if ! sbverify --cert "$cert" "$kernel" &>/dev/null; then sbsign --key "$key" --cert "$cert" --output "$kernel" "$kernel" fi done
/path/to/db.key
と /path/to/db.crt
の部分は、カーネルの署名に使用するキーペアへのパスに置き換えてください。
systemd-boot を使用する場合、この手順を半自動的に行う専用の pacman フックが存在します。
mkinitcpio のポストフックで unified カーネルイメージに署名する
Unified カーネルイメージ#セキュアブート用の UKI への署名 章を参照してください。
sbupdate による完全に自動化された unified カーネルの生成と署名
sbupdate は、Arch Linux で unified カーネルイメージの生成と署名を自動化するために特別に作られたツールです。このツールは、pacman フックを通してカーネルのインストール・削除・アップデートを処理します。
sbupdate-gitAUR をインストールして、プロジェクトのホームページにある手順に従って設定してください。[4]
設定したら、イメージを生成するために sbupdate
を root として実行してください。
鍵をアップデートする
一度セキュアブートを "User Mode" にしたら、KEK, db, dbx を変更するには上位の鍵による署名が必要です。
例えば、db 鍵を新しいものに置き換えたい場合:
- 新しい鍵を作成
- EFI 署名リストに変換
- EFI 署名リストに署名
- 署名された証明書アップデートファイルを登録
$ cert-to-efi-sig-list -g "$(< GUID.txt)" new_db.crt new_db.esl $ sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db new_db.esl new_db.auth
db 鍵を置き換えるかわりに Signature Database に別の鍵を追加したい場合、-a
オプションを使う必要があります (sign-efi-sig-list(1) を参照):
$ sign-efi-sig-list -a -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db new_db.esl new_db.auth
new_db.auth
が作成されたら登録してください。
他のオペレーティングシステムとデュアルブートする
Microsoft Windows
"Microsoft Windows Production PCA 2011" 鍵を UEFI セキュアブート変数に登録しない場合、カスタム、個人の鍵で Windows のブートローダー (EFI/Microsoft/Boot/bootmgfw.efi
) を署名しても、Windows を起動することは通常不可能です:
bootmgfw.efi
に "Microsoft Windows Production PCA 2011" とあなたの独自のセキュアブート DB 鍵の両方の署名 (つまり、2つの署名) が含まれている場合、INSYDE Corp. 4096.01 (UEFI Version 2.31, Version F.70, Release Date: 07/18/2016, BIOS Revision 15.112, Firmware Revision: 29.66) のような UEFI ファームウェア実装は、bootmgfw.efi
を起動せず、セキュリティ違反エラー (Selected boot image did not authenticate. Press ENTER to continue.
) を発生させます: このような UEFI ファームウェア実装は、おそらく1番目の署名だけは読み込むことができるでしょうが、2番目の署名は無理でしょう。2番目の署名の証明書だけが UEFI セキュアブート変数に登録されているので、セキュアブートの検証が失敗するのです。bootmgfw.efi
ファイルの "Microsoft Windows Production PCA 2011" 証明書が strip/削除されていて、さらにあなたの独自のセキュアブート DB 鍵の署名だけがそのファイルに追加されている場合、UEFI はそのファイルを起動するでしょう。しかし、Windows はリカバリ/回復環境を起動してしまいます: Windows は Windows 環境が破損していると報告するでしょう (bootmgfw.efi
ファイルの "Microsoft Windows Production PCA 2011" 署名が存在しないからです)。
なので、Windows とデュアルブートするには
- 選択肢1:
bootmgfw.efi
のハッシュをDB
変数の許可ハッシュリストに追加する必要があります。そして、Windows アップデートがbootmgfw.efi
を変更するたびに毎回DB
変数をアップデートする必要があります。これはかなり面倒くさいうえ、エラーが発生しやすく、Microsoft によってサポートされている方法ではありません。さらに、このようなセットアップでは Bitlocker は正しく動作しないでしょう (Windows パーティションを復号化するために毎回 Bitlocker が回復パスワードを尋ねてきます)。 - 選択肢2: Micosoft の証明書を UEFI セキュアブート変数に追加する必要があります。Microsoft は2つの
DB
証明書と1つのKEK
証明書を持っています (日本語訳ページ):- Microsoft Windows Production PCA 2011 証明書 は、Windows OS をロードできるようにするために、
DB
変数に含めなければなりません。 - Microsoft Corporation UEFI CA 2011 証明書 (またの名を Microsoft 3rd Party UEFI CA 証明書) は、UEFI ドライバやオプションの ROM、shim などのサードパーティのバイナリを使用するために、
DB
変数に含めるべきです。 - Microsoft Corporation KEK CA 2011 証明書は、「
DBX
を更新して問題のあるイメージの失効を有効に」し「署名された新しい Windows イメージの準備をするためにDB
を更新する」ために、KEK
変数に含めるべきです。しかし、"Microsoft Corporation KEK CA 2011" 証明書がなくとも、Windows は起動するでしょう。
- Microsoft Windows Production PCA 2011 証明書 は、Windows OS をロードできるようにするために、
Microsoft の GUID (77fa9abd-0359-4d32-bd60-28f4e78f784b
) を使用して Microsoft の DER 形式 DB
証明書の EFI Signature Lists を作成し、それらのリストを1つのファイルにまとめてください:
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_db.esl MicWinProPCA2011_2011-10-19.crt $ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_UEFI_db.esl MicCorUEFCA2011_2011-06-27.crt $ cat MS_Win_db.esl MS_UEFI_db.esl > MS_db.esl
任意 (Microsoft の UEFI セキュアブート要件を厳密に満たすために): Microsoft の GUID (77fa9abd-0359-4d32-bd60-28f4e78f784b
) を使って Microsoft の DER 形式 KEK
証明書の EFI Signature List を作成してください:
$ sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_KEK.esl MicCorKEKCA2011_2011-06-24.crt
DB
変数のアップデートを KEK
を使って署名してください。sign-efi-sig-list
を -a
オプションで使用してください (-a
オプションは DB
証明書を置き換えるのではなく 追加 します):
$ sign-efi-sig-list -a -g 77fa9abd-0359-4d32-bd60-28f4e78f784b -k KEK.key -c KEK.crt db MS_db.esl add_MS_db.auth
任意 (Microsoft の UEFI セキュアブート要件を厳密に満たすために): KEK
変数のアップデートを PK
で署名してください。sign-efi-sig-list
を -a
オプションで使用してください (-a
オプションは KEK
証明書を置き換えるのではなく 追加 します):
$ sign-efi-sig-list -a -g 77fa9abd-0359-4d32-bd60-28f4e78f784b -k PK.key -c PK.crt KEK MS_Win_KEK.esl add_MS_Win_KEK.auth
#ファームウェアに鍵を登録する に従い、UEFI セキュアブートデータベース変数に add_MS_db.auth
を登録してください。Microsoft の UEFI セキュアブート要件を厳密に満たしたい場合は、add_MS_Win_KEK.auth
も登録してください。
署名済みのブートローダを使う
署名済みのブートローダーを使うというのは Microsoft の鍵で署名されたブートローダーを使うということです。署名済みのブートローダーとしては PreLoader と shim が存在します。どちらも他の EFI バイナリ (通常のブートローダー) をチェインロードします。Microsoft は未署名のあらゆるバイナリを自動起動するブートローダーに署名しないことになっているため、PreLoader と shim は Machine Owner Key リストと呼ばれるホワイトリストを使っています。バイナリの SHA256 ハッシュあるいはバイナリの署名鍵が MokList に存在する場合、バイナリが起動されますが、存在しない場合はハッシュや鍵を登録するための鍵管理ユーティリティが起動します。
PreLoader
起動時に PreLoader は loader.efi
を実行しようとします。MokList に loader.efi
のハッシュが存在しない場合、PreLoader は HashTool.efi
を起動します。HashTool で起動したい EFI バイナリのハッシュ、つまりブートローダー (loader.efi
) とカーネルを登録する必要があります。
PreLoader をセットアップする
preloader-signedAUR パッケージをインストールして PreLoader.efi
と HashTool.efi
をブートローダーのディレクトリにコピーしてください。systemd-boot の場合、以下を実行:
# cp /usr/share/preloader-signed/{PreLoader,HashTool}.efi esp/EFI/systemd
そしてブートローダーのバイナリをコピーして loader.efi
に名前を変更します。systemd-boot の場合、以下を実行:
# cp esp/EFI/systemd/systemd-bootx64.efi esp/EFI/systemd/loader.efi
最後に、PreLoader.efi
を起動する NVRAM エントリを新しく作成してください:
# efibootmgr --unicode --disk /dev/sdX --part Y --create --label "PreLoader" --loader /EFI/systemd/PreLoader.efi
X
は EFI システムパーティションのドライブ文字に、Y
は同じくパーティション番号に置き換えてください。
上記のエントリは起動リストの一番最初に追加する必要があります。efibootmgr
コマンドで確認して、必要であればブートローダーの設定を変更してください。
フォールバック
カスタム NVRAM エントリの起動に問題が発生する場合、HashTool.efi
と loader.efi
を UEFI によって自動的に起動されるデフォルトのブートローダーの場所にコピーしてください:
# cp /usr/share/preloader-signed/HashTool.efi esp/EFI/BOOT/ # cp esp/EFI/systemd/systemd-bootx64.efi esp/EFI/BOOT/loader.efi
PreLoader.efi
を上書きコピーして、名前を変更します:
# cp /usr/share/preloader-signed/PreLoader.efi esp/EFI/BOOT/BOOTx64.EFI
Windows にしか対応しない非協力的な UEFI 実装の場合、PreLoader.efi
を Windows で使用されるデフォルトローダーの場所にコピーしてください:
# mkdir -p esp/EFI/Microsoft/Boot # cp /usr/share/preloader-signed/PreLoader.efi esp/EFI/Microsoft/Boot/bootmgfw.efi
上と同じように、HashTool.efi
と loader.efi
を esp/EFI/Microsoft/Boot
にコピーしてください。
セキュアブートを有効にした状態でシステムを起動したら、上のセクションの手順に従って loader.efi
と /vmlinuz-linux
(あるいは使用している他のカーネルイメージ) を登録します。
起動途中で使用するには?
Failed to Start loader... I will now execute HashTool.
というメッセージが表示されるでしょう。loader.efi
と vmlinuz.efi
のハッシュを登録するために HashTool を使用するには、以下の手順を踏んでください。以下の手順では、リマスタリングされた archiso インストールメディアのタイトルについて仮定をおいています。実際のタイトルはブートローダのセットアップに依存します。
- OK を選択してください
- HashTool のメインメニューで、Enroll Hash を選択し、
\loader.efi
を選んで Yes で確定してください。再び Enroll Hash とarchiso
を選択し archiso のディレクトリに入って、vmlinuz.efi
を選択し、Yes で確定してください。そして、Exit を選択してブートデバイスの選択メニューに戻ってください。 - ブートデバイスの選択メニューで、Arch Linux archiso x86_64 UEFI CD を選んでください。
PreLoader を除去する
preloader-signedAUR をアンインストールし、コピーしたファイルを削除して、設定を元に戻します。systemd-boot の場合、以下を実行:
# rm esp/EFI/systemd/{PreLoader,HashTool}.efi # rm esp/EFI/systemd/loader.efi # efibootmgr --unicode --bootnum N --delete-bootnum # bootctl update
N
は PreLoader.efi
を起動するために作成した NVRAM のブートエントリに置き換えてください。efibootmgr
コマンドで確認を行なって、必要に応じてブート順序を修正してください。
登録したハッシュを削除する
MOK データベースに登録されたハッシュのエントリは NVRAM の容量を少し圧迫します。空き容量を増やしたり、時代遅れなプログラムが起動しないようにしたりするために、場合によっては使用しないハッシュを削除する必要があるでしょう。
efitools をインストールし、KeyTool.efi
をコピーしてください:
# cp /usr/share/efitools/efi/KeyTool.efi esp/EFI/systemd/KeyTool.efi
PreLoader を起動するよう設定すれば、KeyTool のエントリが現れます。これで、MOK データベース内のハッシュを編集することができます。
shim
起動時に shim は grubx64.efi
を実行しようとします。MokList に grubx64.efi
のハッシュあるいは署名鍵が存在しない場合、shim は mmx64.efi
を起動します。MokManager で起動したい EFI バイナリ (ブートローダー (grubx64.efi
) とカーネル) のハッシュか署名鍵を登録する必要があります。
shim をセットアップする
shim-signedAUR をインストールしてください。
現在のブートローダーの名前を grubx64.efi
に変更してください:
# mv esp/EFI/BOOT/BOOTx64.EFI esp/EFI/BOOT/grubx64.efi
shim と MokManager を ESP 上のブートローダーのディレクトリにコピーしてください; shimx64.efi
はブートローダの以前のファイル名を使ってください:
# cp /usr/share/shim-signed/shimx64.efi esp/EFI/BOOT/BOOTx64.EFI # cp /usr/share/shim-signed/mmx64.efi esp/EFI/BOOT/
最後に、BOOTx64.EFI
を起動する新しい NVRAM エントリを作成してください:
# efibootmgr --unicode --disk /dev/sdX --part Y --create --label "Shim" --loader /EFI/BOOT/BOOTx64.EFI
shim は、MokList に格納されている Machine Owner Key やハッシュによってバイナリを認証することができます。
- Machine Owner Key (MOK)
- EFI バイナリに署名するためにユーザが生成し利用する鍵
- hash
- EFI バイナリの SHA256 ハッシュ
ハッシュを用いるのは単純ですが、ブートローダやカーネルをアップデートするたびに、MokManager 内のそれらのハッシュを追加する必要があります。MOK では鍵を一度追加するだけで済みますが、ブートローダとカーネルをアップデートするたびに、それらに署名する必要があります。
shim でハッシュを使う
shim は、MokList に grubx64.efi
の SHA256 ハッシュが存在しない場合、mmx64.efi
を起動します。
MokManager で Enroll hash from disk を選択してから grubx64.efi
を探して MokList に追加してください。同じようにカーネルの vmlinuz-linux
も追加してください。完了したら Continue boot を選択してください。ブートローダーが起動してカーネルが起動します。
shim で鍵を使う
sbsigntools をインストールしてください。
以下のファイルが必要です:
.key
- EFI バイナリに署名するための PEM 形式の秘密鍵。
.crt
- sbsign で使うための PEM 形式の証明書。
.cer
- MokManager で使うための DER 形式の証明書。
Machine Owner Key を作成:
$ openssl req -newkey rsa:4096 -nodes -keyout MOK.key -new -x509 -sha256 -days 3650 -subj "/CN=my Machine Owner Key/" -out MOK.crt $ openssl x509 -outform DER -in MOK.crt -out MOK.cer
(grubx64.efi
という名前の) ブートローダーとカーネルに署名:
# sbsign --key MOK.key --cert MOK.crt --output /boot/vmlinuz-linux /boot/vmlinuz-linux # sbsign --key MOK.key --cert MOK.crt --output esp/EFI/BOOT/grubx64.efi esp/EFI/BOOT/grubx64.efi
ブートローダーとカーネルをアップデートするたびに上記の署名が必要です。カーネルの署名は pacman フック で自動化できます。例えば:
/etc/pacman.d/hooks/999-sign_kernel_for_secureboot.hook
[Trigger] Operation = Install Operation = Upgrade Type = Package Target = linux Target = linux-lts Target = linux-hardened Target = linux-zen [Action] Description = Signing kernel with Machine Owner Key for Secure Boot When = PostTransaction Exec = /usr/bin/find /boot/ -maxdepth 1 -name 'vmlinuz-*' -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q "signature certificates"; then /usr/bin/sbsign --key MOK.key --cert MOK.crt --output {} {}; fi' ; Depends = sbsigntools Depends = findutils Depends = grep
MOK.cer
を FAT でフォーマットされたファイルシステムにコピーしてください (EFI システムパーティション を使うことができます)。
再起動してセキュアブートを有効にしてください。shim は MokList に grubx64.efi
を署名するときに使った証明書がない場合、mmx64.efi
を起動します。
MokManager で Enroll key from disk を選択してから MOK.cer
を探して MokList に追加してください。完了したら Continue boot を選択してください。ブートローダーが起動して、Machine Owner Key で署名されたバイナリを起動できるようになります。
shim で鍵と GRUB を使う
手順は GRUB#Shim-lock を見てください。
登録されたハッシュ/鍵を削除する
MOK データベースに登録されたハッシュ/鍵のエントリは、NVRAM の領域を少しずつ圧迫していきます。領域を節約し、古いプログラムがブートされないようにするために、使っていないハッシュ/鍵は削除すると良いかもしれません。
MOK データベースは mokutil で管理できます。
登録された鍵とハッシュを一覧表示する:
# mokutil --list-enrolled
データベースからハッシュを削除する。ここで入力するパスワードは、MOK マネージャで削除の確認を行う際に再び尋ねられます。
# mokutil --delete-hash <削除するハッシュ> Input password:
データベースから鍵を削除する:
# mokutil --delete MOK.cer
次回のブート時に削除されるハッシュ/鍵を一覧表示する:
# mokutil --list-delete
次回のブート時に、登録/削除するハッシュ/鍵のオプション付きで MOK マネージャが初期化されます。詳細は mokutil(1) を参照してください。
shim を除去する
shim-signedAUR をアンインストールして、コピーした shim と MokManager のファイルを削除してブートローダーを元の名前に戻してください。
セキュアブートを保護する
マシンに物理アクセスできる者がセキュアブートを無効化してしまうことを阻止する唯一の方法は、ファームウェアの設定をパスワードで保護することです。
ほとんどの UEFI ファームウェアはそのような機能を提供します。通常、ファームウェア設定の「セキュリティ」セクションにその項目があるはずです。
ヒントとテクニック
ISO の再パック
libisoburn と mtools を使うことで、公式のインストールイメージを展開したり、再パックしたりできます。この方法で、カスタムの鍵か署名済みのブートローダを使ってセキュアブートをサポートするイメージを作成することができます。
公式の ISO をカスタムの鍵で署名する
ブートローダー (BOOTx64.EFI
と BOOTIA32.EFI
)、カーネル、UEFI シェルを ISO から抽出し、それらを署名し、署名済みファイルを ISO に再パックすることで、カスタムの鍵で公式の ISO にセキュアブートサポートを追加できます。
まず、関連するファイルと El Torito ブートイメージを抽出してください:
$ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \ -extract_boot_images ./ \ -extract /EFI/BOOT/BOOTx64.EFI BOOTx64.EFI \ -extract /EFI/BOOT/BOOTIA32.EFI BOOTIA32.EFI \ -extract /shellx64.efi shellx64.efi \ -extract /shellia32.efi shellia32.efi \ -extract /arch/boot/x86_64/vmlinuz-linux vmlinuz-linux
mkarchiso によって使用されている xorrisofs(1) のオプション -rational-rock
は、ISO 9660 のファイルを読み取り専用にし、これは抽出後も維持されます。ファイルを書き込み可能にし、変更できるようにしましょう:
$ chmod +w BOOTx64.EFI BOOTIA32.EFI shellx64.efi shellia32.efi vmlinuz-linux
ファイルを署名してください。sbsigntools を使って署名する場合、以下のようにできます:
$ sbsign --key db.key --cert db.crt --output BOOTx64.EFI BOOTx64.EFI $ sbsign --key db.key --cert db.crt --output BOOTIA32.EFI BOOTIA32.EFI $ sbsign --key db.key --cert db.crt --output shellx64.efi shellx64.efi $ sbsign --key db.key --cert db.crt --output shellia32.efi shellia32.efi $ sbsign --key db.key --cert db.crt --output vmlinuz-linux vmlinuz-linux
ブートローダーと UEFI シェルを eltorito_img2_uefi.img
にコピーしてください。これは EFI システムパーティションとして使用され、El Torito UEFI ブートイメージとしてリストアップされます。eltorito_img2_uefi.img
のサイズは固定されていますが、丸め/アライメントのためや予約済みセクタに対処するために mkarchiso によって 1 MiB の空き領域が追加されています。なので、署名によるサイズ増は問題にはならないはずです。
$ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI BOOTIA32.EFI ::/EFI/BOOT/ $ mcopy -D oO -i eltorito_img2_uefi.img shellx64.efi shellia32.efi ::/
変更された El Torito UEFI ブートイメージを使って ISO を再パックし、署名されたブートローダーのファイル、UEFI シェル、カーネルを ISO 9660 に追加してください:
$ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \ -outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \ -boot_image any replay \ -append_partition 2 0xef eltorito_img2_uefi.img \ -map BOOTx64.EFI /EFI/BOOT/BOOTx64.EFI \ -map BOOTIA32.EFI /EFI/BOOT/BOOTIA32.EFI \ -map shellx64.efi /shellx64.efi \ -map shellia32.efi /shellia32.efi \ -map vmlinuz-linux /arch/boot/x86_64/vmlinuz-linux
完成した archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso
を起動してみてください。
ブートローダを PreLoader に置き換える
公式の ISO イメージにセキュアブートのサポートを追加するもう一つの方法は、ブートローダを抽出し、それを #PreLoader で置き換えることです。
まず、ブートローダと El Torito ブートイメージを抽出してください。
$ osirrox -indev archlinux-YYYY.MM.DD-x86_64.iso \ -extract_boot_images ./ \ -cpx /EFI/BOOT/BOOTx64.EFI ./
BOOTx64.efi
ファイルを PreLoader に置き換えてください:
$ mv BOOTx64.EFI loader.efi $ cp /usr/share/preloader-signed/PreLoader.efi BOOTx64.EFI $ cp /usr/share/preloader-signed/HashTool.efi HashTool.efi
新しいファイルをブートイメージに追加してください:
$ mcopy -D oO -i eltorito_img2_uefi.img BOOTx64.EFI loader.efi HashTool.efi ::/EFI/BOOT/
最後に、変更されたブートイメージと新しいブートローダファイルを使って ISO を再パックしてください。
$ xorriso -indev archlinux-YYYY.MM.DD-x86_64.iso \ -outdev archlinux-YYYY.MM.DD-x86_64-Secure_Boot.iso \ -boot_image any replay \ -append_partition 2 0xef eltorito_img2_uefi.img \ -map_l ./ /EFI/BOOT/ BOOTx64.EFI loader.efi HashTool.efi
参照
- Understanding the UEFI Secure Boot Chain by tianocore
- Wikipedia:Unified Extensible Firmware Interface#Secure boot
- Dealing with Secure Boot by Rod Smith
- Controlling Secure Boot by Rod Smith
- UEFI secure booting (part 2) by Matthew Garrett
- UEFI Secure Boot by James Bottomley
- efitools README
- Will your computer's "Secure Boot" turn out to be "Restricted Boot"? — Free Software Foundation
- Free Software Foundation recommendations for free operating system distributions considering Secure Boot
- Intel's UEFI Secure Boot Tutorial
- Secure Boot, Signed Modules and Signed ELF Binaries
- 国家安全保障局のドキュメント: UEFI Defensive Practices Guidance と機密を解かれたUEFI Secure Boot customization
- sbkeysync & maintaining uefi key databases by Jeremy Kerr
- Secure your boot process: UEFI + Secureboot + EFISTUB + Luks2 + lvm + Arch Linux (2020-07)
- How is hibernation supported, on machines with UEFI Secure Boot? (Security StackExchange)
- Authenticated Boot and Disk Encryption on Linux by Lennart Poettering (2021-09-23)