Arch Linuxに Secure Bootを設定する

本記事は以前はてなブログに投稿していた記事の内容を加筆修正して移行したものです。

セキュアブートとは?

簡単に説明すると、カーネルとブートローダーに署名をして、起動時にその署名を検証してパスする場合のみブートを許可する機構です。 署名の検証を行うことで、カーネルとブートローダーが改竄されていないことを担保できるためセキュリティーが向上します。

自分のマシン(ThinkPad E14 Gen5)では、Windows11とArch Linuxでデュアルブートしています。 Windows11側でディスク暗号化を運用したいと思ったのですが、 セキュアブートの有効化が必要だったため、今回セキュアブートを設定行いました。

セキュアブートの設定

Linuxでセキュアブートを設定する方法には、大きく分けると二通りの方法があります。

一つの方法は、多くのx86-64なマシンには既にMicrosoftによって発行された鍵が封入されているため、 その鍵で署名されたブートローダーからチェインロードすることでブートするように設定する方法です。 この方法では、鍵を封入する操作が不要なため既存の鍵を飛してしまうようなリスクがないことがメリットですが、操作が少し煩雑です。 この方法は実際にProxmox VEでセキュアブートを実現するために使用されています。

もう一つの方法は、自分で署名用の鍵を作成&封入してカーネル、ブートローダーに署名を行う方法です。 この方法では、鍵を封入する作業があるため、操作を間違えるとマシンを文鎮化してしまうリスクがありますが、作業がシンプルです。

今回は後者の方法を、Arch Wikiのガイドを参考に行いました。

sbctlで鍵を生成して封入する

作業をする行う前にUEFI BIOSに入りsecure bootをsetup modeに設定します。

その後、起動してから、必要なツールをinstallします。

1
$ sudo pacman -S efitools sbctl

ここで、efitools,sbctlはそれぞれEFI領域に対する操作、鍵関係の操作に必要なツールです。

まず、すでに存在するefi鍵の確認を行います。

1
$ for var in PK KEK db dbx ; do efi-readvar -v $var -o old_${var}.esl ; done

何もしていない場合では、恐らくMicrosoftの鍵が見つかるはずです。

続いて、sbctl create-keysで鍵を生成して,enroll-keysで鍵を追加します。 ここで、-mオプションはマイクロソフトの鍵を消さずに自分で生成した鍵を追加するようすることを意味します。

これを忘れると、マイクロソフトの鍵で署名された一部のデバイスドライバが読めなくなって最悪の場合ではマシンが文鎮化する恐れがあります。

1
2
$ sudo sbctl create-keys
$ sudo sbctl enroll-keys -m # -mオプションを忘れないようにすること

今回鍵を登録しようとしたところ以下のようなエーラーが出ました。

1
2
3
‼ File is immutable: /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c
‼ File is immutable: /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f
You need to chattr -i files in efivarfs

どうやら書き込みしたいファイルがイミューダブルなのでミューダブルになるようにしろとのことなので警告の通りにコマンドを実行してミューダブルにしました。

1
2
$ sudo chattr -i /sys/firmware/efi/efivars/KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c
$ sudo chattr -i /sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f

この後で再び鍵の追加を行うと操作に成功しました。

1
2
3
4
$ sudo sbctl enroll-keys -m
Enrolling keys to EFI variables...
With vendor keys from microsoft...✓
Enrolled keys to the EFI variables!

カーネルとブートローダーに署名を行う

まず、sbctl verifyで署名が必要なファイルを調べます。

チェック

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ sudo sbctl verify
Verifying file database and EFI images in /boot...
✗ /boot/EFI/BOOT/BOOTX64.EFI is not signed
✗ /boot/EFI/systemd/systemd-bootx64.efi is not signed
failed to verify file /boot/initramfs-linux-fallback.img: /boot/initramfs-linux-fallback.img: invalid pe header
failed to verify file /boot/initramfs-linux.img: /boot/initramfs-linux.img: invalid pe header
failed to verify file /boot/intel-ucode.img: /boot/intel-ucode.img: invalid pe header
failed to verify file /boot/loader/entries/arch.conf: /boot/loader/entries/arch.conf: invalid pe header
failed to verify file /boot/loader/entries.srel: /boot/loader/entries.srel: invalid pe header
failed to verify file /boot/loader/loader.conf: /boot/loader/loader.conf: invalid pe header
failed to verify file /boot/loader/random-seed: /boot/loader/random-seed: invalid pe header
✗ /boot/vmlinuz-linux is not signed

結果としては以下の3個のファイルに対しての署名が必要なことが分りました。

  • /boot/EFI/BOOT/BOOTX64.EFI is not signed
  • /boot/EFI/systemd/systemd-bootx64.efi is not signed
  • /boot/vmlinuz-linux is not signed

なので、以下のように署名を行います。

1
2
3
$ sudo sbctl sign -s /boot/vmlinuz-linux
$ sudo sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI
$ sudo sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi

今回をこの作業を行なったマシンはブートローダーとして、systemd-bootを採用しており、 かつその更新をsystemd-boot-update.serviceで行なっているので以下のコマンドで/usr/lib内のブートローダーも直接署名しました。

1
2
# for systemd-boot
$ sudo sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi

最後にマシンをシャットダウンしてから、UEFI BIOSに入りsecure boot 有効化してから再度起動して、無事起動できれば成功です。

感想

途中の鍵の登録では-mオプションを忘れると最悪マシンを文鎮化する可能性があるということでビビリながら作業していました。 しかしsbctlで鍵の作成&登録&署名は思っていたよりも簡単にできました。

CC BY
Hugo で構築されています。
テーマ StackJimmy によって設計されています。