secure bootが有効な環境で自前ビルドのカーネルに署名する方法(fedora向け)

fedoraなら多分一番手軽だと思う署名方法です。他のディストリビューションはわかりません😭

テスト環境

ディストリビューションは(もちろん) fedoraです。バージョンは31です。実機ではなくてqemuでテストしました。

準備

まずpesignとnss-toolsパッケージをインストールします。pesignパッケージをインストールするとpesignコマンドなどのバイナリの他に/etc/pki/pesign/と/etc/pki/pesign-rh-testにデータベースがインストールされます。今回は/etc/pki/pesign-rh-testにあるものを使います。

署名前の準備

まずcertificateファイルを取り出します。

$ sudo certutil -d /etc/pki/pesign-rh-test -L -n "Red Hat Test CA" -r > rhca.cer

次に取り出したcertファイルを登録します。このときにパスワードを聞かれるのでお好きなパスワードを入れてください。

$ sudo mokutil --import ./rhca.cer
input password: 
input password again:

インポートに成功すると次のように確認できます。

$ sudo mokutil --list-new | head -n 10
[key 1]
SHA1 Fingerprint: 65:37:ee:ed:f1:ea:fe:d0:a4:cd:d8:91:eb:f2:2b:45:45:41:cd:44
Certificate:
    Data:

そうしたらここで一旦rebootします。

enroll

再起動するとgrubなどは起動せずにuefiのアプリが起動します。

f:id:masami256:20200112150853p:plain

なにか適当にキーを押すとメニューが出るのでEnroll MOKを選択してエンターキーを押します。

f:id:masami256:20200112150941p:plain

View Key 0を選択してエンターキーを押すと鍵の内容が確認できます。

f:id:masami256:20200112151052p:plain

Continueを選ぶと鍵を登録するか聞かれるのでYesを選択してエンターキーを押しましょう。

f:id:masami256:20200112151206p:plain

パスワードを聞かれるので先程入力したパスワードを打ち込みます。

f:id:masami256:20200112151303p:plain

パスワードが正しければメニュー画面に戻ります。Rebootを選択すればシステムが再起動して通常のブートフローになります。

f:id:masami256:20200112151353p:plain

カーネルへの署名

参考文献の手順だとpesignのオプションでエラーになったんですが、fedoraカーネルパッケージをビルドしたときのログを見てたらコマンドラインオプションがわかりました。

↓がログです。

+ '[' -f arch/x86_64/boot/zImage.stub ']'
+ _pesign_nssdir=/etc/pki/pesign
+ '[' 'Red Hat Test Certificate' = 'Red Hat Test Certificate' ']'
+ _pesign_nssdir=/etc/pki/pesign-rh-test
+ '[' -x /usr/bin/pesign ']'
+ '[' x86_64 == x86_64 -o x86_64 == aarch64 ']'
+ '[' 0 -ge 7 -a -f /usr/bin/rpm-sign ']'
++ id -un
++ uname -m
+ '[' '%{vendor}' == 'Fedora Project' -a mockbuild == mockbuild -a x86_64 == x86_64 ']'
+ '[' -S /var/run/pesign/socket ']'
+ /usr/bin/pesign -c 'Red Hat Test Certificate' --certdir /etc/pki/pesign-rh-test -i arch/x86/boot/bzImage -o vmlinuz.signed -s
+ '[' '!' -s -o vmlinuz.signed ']'
+ '[' '!' -s vmlinuz.signed ']'

コマンドはこんな感じになります。-iオプションにbzImageのパスを渡してください。

$ pesign -c 'Red Hat Test Certificate' --certdir /etc/pki/pesign-rh-test -i ./bzImage -o vmlinuz.signed -s

自分の場合はカーネルのmake installまで済ませていて、カーネルはvmlinuz-5.4.8-testとして置いておいたのでvminuz.signedを/boot/vmlinuz-5.4.8-testとしてコピーして完了でした。 あとは再起動してこのカーネルで起動します。

自前のカーネルでブート

起動してカーネルのバージョン、secure bootが有効なことを確認してすべてOKって感じです🎉

$ uname -a
Linux secureboot-test 5.4.8-test #1 SMP Thu Jan 9 00:04:00 JST 2020 x86_64 x86_64 x86_64 GNU/Linux
$ dmesg | grep Secure
[    0.008666] Secure boot enabled

鍵を消したら

deleteオプションで鍵を消せます。再起動すると登録したときと同じようにShimのアプリが起動するのでそこで鍵を削除できます。

$ sudo mokutil --delete ./rhca.cer 
input password: 
input password again:

鍵を消すとその鍵で署名したカーネルでは起動できなくなります。

f:id:masami256:20200112152306p:plain

カーネルモジュール

自作モジュールもロードできます。

$ lsmod | grep test_mod
test_mod               16384  0

dmesgでも

[  104.658715] test_mod: loading out-of-tree module taints kernel.
[  104.658741] test_mod: module verification failed: signature and/or required key missing - tainting kernel
[  104.658958] test_mod: install test_mod : insmod

参考文献

次のブログを参考にしました。

Booting custom kernels in F18 with Secure Boot - pointless pontifications of a back seat driver — LiveJournal