はじめに (対象読者・この記事でわかること)
この記事は、Linuxシステムのセキュリティ強化に関心のあるシステム管理者、組み込み開発者、そしてカスタムカーネルのセキュアな運用を目指すエンジニアを対象としています。特に、UEFIセキュアブート環境下でカスタムLinuxカーネルを安全に起動させたいと考えている方に役立つ内容です。
この記事を読むことで、UEFIセキュアブートの基本的な概念、Linuxカーネルイメージにデジタル署名を行うための具体的な手順、および署名済みカーネルをセキュアブートが有効なシステムで動作させる方法を理解し、実践できるようになります。これにより、起動時のマルウェア感染やカーネル改ざんのリスクを低減し、より堅牢なシステムを構築するための基礎知識と実践的なスキルを習得できます。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 * Linuxの基本的な操作(コマンドライン操作、パッケージ管理、ファイルシステム操作) * UEFI(Unified Extensible Firmware Interface)の基本的な理解 * 公開鍵暗号方式の基礎知識(証明書、秘密鍵、公開鍵の概念) * OpenSSLコマンドの基本的な使用経験
セキュアブートとは? なぜLinuxカーネルに署名が必要なのか
セキュアブートは、UEFIファームウェアの一部として提供されるセキュリティ機能で、システムの起動プロセス中に実行されるソフトウェア(UEFIドライバー、ブートローダー、オペレーティングシステムカーネルなど)が、信頼できる発行元によって署名され、改ざんされていないことを検証します。これにより、悪意のあるコードやマルウェアがシステムの起動プロセスに介入し、制御を奪うことを防ぎます。
Linuxカーネルに署名が必要な主な理由は以下の通りです。
- マルウェアからの保護: 署名されていない、あるいは改ざんされたカーネルが起動することを防ぎます。これにより、ブートキットやルートキットといった低レベルのマルウェアが、OSが起動する前にシステムの制御を奪うことを困難にします。
- システム信頼性の確保: 組織内で特定のカスタムカーネルを使用する場合、それが正規のものであることを保証します。サプライチェーン攻撃などによるカーネルのすり替えを防ぎ、システムの信頼性を高めます。
- 規制遵守: 一部の業界や政府機関では、システムの起動プロセス全体のセキュリティを保証することが求められる場合があります。セキュアブートは、その要件を満たすための重要な要素です。
セキュアブートの仕組みは、以下の主要なキーとデータベースに依存します。
- Platform Key (PK): プラットフォーム所有者(通常はOEM)が所有し、Key Exchange Key (KEK) の署名に使用されます。
- Key Exchange Key (KEK): オペレーティングシステム(OS)ベンダーやユーザーが所有し、許可された署名データベース (DB) や禁止署名データベース (DBX) の更新を署名するために使用されます。
- Allowed Signature Database (DB): 信頼できるUEFIアプリケーション、ブートローダー、OSカーネルなどの公開鍵やハッシュを格納します。DBに登録されたものだけが実行を許可されます。
- Forbidden Signature Database (DBX): 既知の不正なUEFIアプリケーションやブートローダーの公開鍵やハッシュを格納します。DBXに登録されたものは実行が拒否されます。
Linux環境では、通常、ShimブートローダーがUEFIファームウェアのDBに登録され、ShimがMOK (Machine Owner Key) リストと呼ばれる独自の信頼データベースを参照してGRUBやカーネルを検証するという二段階の検証プロセスが用いられます。これにより、UEFIファームウェアのDBを直接変更することなく、カスタムカーネルやブートローダーを柔軟に運用することが可能になります。
セキュアブート対応Linuxカーネルイメージパッケージの作成手順
ここでは、セキュアブートに対応したLinuxカーネルイメージを準備し、署名して起動可能にする具体的な手順を解説します。今回は、Shimブートローダーを介してカスタムカーネルを起動するシナリオを想定します。
ステップ1: 署名用証明書と鍵の準備
セキュアブートで使用するデジタル署名のために、公開鍵基盤 (PKI) の設定を行います。ここでは、OpenSSLを使用して必要なCA (Certificate Authority) 証明書と署名用の鍵を作成します。
Bash# 作業ディレクトリの作成 mkdir -p ~/secureboot_keys cd ~/secureboot_keys # 1. CA (Certificate Authority) 鍵と証明書の作成 # CA秘密鍵の生成 (パスフレーズを設定することを推奨) openssl genrsa -aes256 -out PK.key 4096 # CA証明書(自己署名)の生成 openssl req -new -x509 -key PK.key -out PK.crt -days 3650 -subj "/CN=My Secure Boot PK/" # KEK秘密鍵の生成 openssl genrsa -aes256 -out KEK.key 4096 # KEK証明書(CAによって署名)の生成 openssl req -new -key KEK.key -out KEK.csr -subj "/CN=My Secure Boot KEK/" openssl x509 -req -in KEK.csr -CA PK.crt -CAkey PK.key -out KEK.crt -days 3650 -CAcreateserial # DB秘密鍵の生成 (カーネル署名に使用) openssl genrsa -aes256 -out DB.key 4096 # DB証明書(CAによって署名)の生成 openssl req -new -key DB.key -out DB.csr -subj "/CN=My Secure Boot DB/" openssl x509 -req -in DB.csr -CA KEK.crt -CAkey KEK.key -out DB.crt -days 3650 -CAcreateserial # 証明書と鍵をEFIが読み取れる形式 (.esl) とキー交換用 (.auth) に変換 cert_to_esl() { GUID=$(uuidgen) openssl x509 -in "$1" -outform DER -out "${1%.crt}.der" efi-readvar -g "$GUID" -c "${1%.crt}.der" -o "${1%.crt}.esl" } cert_to_esl PK.crt cert_to_esl KEK.crt cert_to_esl DB.crt # 注意: PK.key, KEK.key, DB.key は厳重に管理してください。 # PK.crt, KEK.crt, DB.crt はシステムのMOKリストやUEFI DBに登録するための公開鍵です。
uuidgen コマンドがない場合は、sudo apt install uuid-runtime (Debian/Ubuntu) または sudo dnf install util-linux-ng (Fedora) でインストールしてください。
efi-readvar コマンドがない場合は、sudo apt install efiutils (Debian/Ubuntu) または sudo dnf install efi-utils (Fedora) でインストールしてください。
ステップ2: Linuxカーネルの準備と設定
カスタムカーネルをビルドする場合、セキュアブート関連の設定が有効になっているか確認します。特に重要なのは、CONFIG_EFI_SECUREBOOT_SIGNATURE_REPOSITORY です。これが有効になっていると、カーネル自身にUEFI署名データベースを埋め込むことができます(ただし、Shimを使用する場合は必須ではありません)。
既存のディストリビューションカーネルを使用する場合は、通常、必要な設定はすでに有効になっています。この場合、ビルドステップはスキップし、既存のカーネルイメージ (vmlinuz) を取得します。
カスタムカーネルをビルドする場合の例:
1. カーネルソースの取得
bash
git clone https://github.com/torvalds/linux.git
cd linux
make defconfig # または既存の設定をコピー
2. .config ファイルの編集(必要に応じて)
make menuconfig を実行し、Processor type and features -> EFI runtime service support -> EFI Secure Boot signature repository (CONFIG_EFI_SECUREBOOT_SIGNATURE_REPOSITORY) を確認します。通常、Shimを使う場合はGRUBが署名されているだけで十分であり、カーネル自体にDBを埋め込む必要はありませんが、EFI Stubを使って直接カーネルをブートする場合は必要になります。
3. カーネルのビルド
bash
make -j$(nproc) bzImage modules
make modules_install
ビルドされたカーネルイメージは arch/x86/boot/bzImage にあります。
ステップ3: カーネルイメージへの署名
sbsign ツールを使って、カーネルイメージにデジタル署名を行います。Shimブートローダーを使用する場合、Shim自体がUEFIファームウェアによって検証され、ShimがMOKリストの鍵を使ってGRUBやカーネルを検証します。したがって、今回はMOKリストに登録するDB証明書でカーネルとGRUBに署名します。
GRUBへの署名 (もしカスタムGRUBを使用する場合): ディストリビューション提供のShim/GRUBを使用する場合、通常は既にディストリビューションの鍵で署名されているため、この手順は不要です。カスタムのGRUBをビルドした場合は署名が必要です。
Bash# GRUB EFI実行ファイル (例: grubx64.efi) を署名 # ここでは grubx64.efi が `/boot/efi/EFI/GRUB/grubx64.efi` にあると仮定 sudo sbsign --key DB.key --cert DB.crt --output /boot/efi/EFI/GRUB/grubx64.efi.signed /boot/efi/EFI/GRUB/grubx64.efi # 後で署名済みのファイルに置き換えるか、ブートエントリを更新します
Linuxカーネルへの署名:
EFI Stubブートローダーとしてカーネルを直接ブートする場合や、GRUBが署名済みカーネルを要求する場合に署名します。
カーネルイメージは /boot/vmlinuz-$(uname -r) のようなパスにあることが多いです。
Bash# 例: 現在起動中のカーネルイメージをコピーして署名 KERNEL_VERSION=$(uname -r) sudo cp /boot/vmlinuz-${KERNEL_VERSION} ~/secureboot_keys/vmlinuz-${KERNEL_VERSION}.unsigned # DB証明書と鍵を使用してカーネルに署名 # sbsign コマンドが存在しない場合は、efiutils パッケージをインストールしてください。 sudo sbsign --key DB.key --cert DB.crt --output ~/secureboot_keys/vmlinuz-${KERNEL_VERSION}.signed ~/secureboot_keys/vmlinuz-${KERNEL_VERSION}.unsigned # 署名済みカーネルを /boot に配置し、grub.cfg を更新するか、新しいブートエントリを作成します。 # GRUBの場合、initrd も署名する必要がある場合があります。 # (例: dracut コマンドで署名済みの initrd を作成) # sudo dracut --force --kver ${KERNEL_VERSION} --hostonly --install-drivers "trusted" --uefi-secure-boot --uefi-secure-boot-cert ~/secureboot_keys/DB.crt --uefi-secure-boot-key ~/secureboot_keys/DB.key /boot/initramfs-${KERNEL_VERSION}.signed.img ${KERNEL_VERSION}
注意: sbsign は efiutils パッケージに含まれています。sudo apt install efiutils (Debian/Ubuntu) または sudo dnf install efi-utils (Fedora) でインストールしてください。
ステップ4: MOKリストへの登録 (またはUEFI DBへの登録)
作成したDB証明書 (DB.crt) をシステムのMOK (Machine Owner Key) リストに登録します。MOKリストはShimブートローダーが参照する信頼できる鍵のリストです。
-
MOKリストへの登録ファイルの準備:
mokutilコマンドで証明書を登録します。bash # DB.crt をDER形式に変換し、MOK登録用のファイルを作成 openssl x509 -in DB.crt -outform DER -out DB.cer sudo mokutil --import DB.cerこのコマンドを実行すると、システム再起動時にMOK管理ユーティリティが起動し、登録を承認するよう求められます。 -
システム再起動とMOK登録の承認: システムを再起動すると、通常はブートプロセス中に青い画面の「Enroll MOK」ユーティリティが表示されます。
Enroll MOKを選択します。Continueを選択します。Yesを選択して、証明書の登録を確認します。- 登録を完了するために、事前に設定したパスワードの入力を求められる場合があります。
これで、UEFIファームウェアのDBにShimが登録されており、ShimはMOKリストに登録されたあなたのDB証明書を信頼し、その証明書で署名されたGRUBやカーネルを起動できるようになります。
ステップ5: テストと検証
MOKリストへの証明書登録とカーネル署名が完了したら、セキュアブートを有効にしてシステムが正しく起動するか検証します。
-
UEFI設定でセキュアブートを有効にする: システムのUEFI/BIOS設定画面に入り、「Secure Boot」オプションを探して「Enabled」に設定します。設定の保存と再起動を行います。
-
システムの起動: 署名済みカーネルが正しく設定されたブートエントリで起動するか確認します。
-
セキュアブート状態の確認: OS起動後、以下のコマンドでセキュアブートが有効になっているか確認します。 ```bash # セキュアブートの状態を確認 bootctl status | grep SecureBoot # または mokutil --sb-state
MOKリストに登録した証明書を確認 (MOKリストにあなたのDB証明書が表示されるはずです)
mokutil --list-new mokutil --list-enrolled
``SecureBoot: enabled` と表示されれば成功です。
ハマった点やエラー解決
-
「Bad signature」エラー:
- 原因: 起動しようとしているEFI実行ファイル(Shim, GRUB, カーネル)が、UEFIファームウェアのDBやMOKリストに登録されていない鍵で署名されているか、全く署名されていない。
- 解決策:
- 証明書の確認:
DB.crtがMOKリストに正しく登録されているかmokutil --list-enrolledで確認。 - 署名の確認:
sbsign --verifyコマンドでEFI実行ファイルが正しく署名されているか確認。 - Shimの検証: ディストリビューション提供のShimがUEFIファームウェアのDBに登録されているか確認。もしShimからカスタマイズしている場合は、Shim自体もファームウェアのDBに登録された鍵で署名されている必要があります。
- 証明書の確認:
-
MOK管理画面が表示されない/登録が失敗する:
- 原因:
mokutil --importコマンドの実行後に再起動しなかった、またはBIOS設定でMOK管理ユーティリティが無効になっている。パスフレーズの入力ミス。 - 解決策:
mokutil --import実行後はすぐに再起動してください。- UEFI/BIOS設定で「MOK management」や類似のオプションが有効になっているか確認してください。
- MOK登録時のパスフレーズは正確に入力してください。
- 原因:
-
起動しない/UEFIエラー:
- 原因: GRUB設定の誤り、カーネルイメージパスの誤り、セキュアブートが有効な環境で署名されていないEFI実行ファイルを起動しようとした。
- 解決策:
- セキュアブートの一時的な無効化: 問題を切り分けるため、UEFI設定でセキュアブートを一時的に無効にし、通常通り起動できるか確認します。
- GRUB設定の確認:
/etc/grub.d/40_customや/etc/default/grubを確認し、grub-mkconfigで設定を更新してください。 - ログの確認: 起動失敗時のUEFIエラーメッセージや、ログファイル (
dmesg,journalctl) を確認して原因を特定します。
まとめ
本記事では、UEFIセキュアブートに対応したLinuxカーネルイメージを作成し、安全に起動させるための具体的な手順 を解説しました。
- セキュアブートの概念と必要性: 起動時の改ざん防止と信頼性確保の重要性を理解しました。
- デジタル署名のための鍵と証明書の準備: OpenSSLを使用してPK/KEK/DBの各鍵と証明書を作成しました。
- Linuxカーネルイメージへの署名とMOKリストへの登録:
sbsignを用いてカーネルに署名し、mokutilを使ってその証明書をMOKリストに登録するプロセスを実践しました。
この記事を通して、読者の皆様はセキュアなLinux起動環境を構築するための基盤となる知識と実践的なスキルを得られたことと思います。これにより、システム起動時のセキュリティリスクを軽減し、より堅牢な運用が可能になります。
今後は、セキュアブートの自動化(例:CI/CDパイプラインへの組み込み)や、TPM (Trusted Platform Module) と連携したさらなるセキュリティ強化、あるいは異なるUEFIファームウェア環境でのセキュアブート設定に関する記事についても深掘りしていく予定です。
参考資料
- UEFI Forum: UEFI Specification
- Linux Kernel Documentation: Secure Boot
- Arch Wiki: Secure Boot
- Red Hat Enterprise Linux 8: Managing secure boot
- man sbsign (efiutils)
- man mokutil
