第441回ではQEMU/
「あなたの鍵はどこから?」
第444回でも解説したように、
- Platform Key
(PK):プラットフォーム (マシン) のオーナーの鍵 - Key Exchange Key
(KEK):db変数を変更するための鍵 - db変数に保存する鍵:UEFIバイナリを検証するための鍵
そして一般的に市販されているPCであれば、
- Platform Key
(PK):PCベンダーの公開鍵証明書 - Key Exchange Key
(KEK):PCベンダーとOSベンダー (WindowsならMicrosoft Corporation KEK CA 2011) の公開鍵証明書 - db変数に保存する鍵:PCベンダーとOSベンダー
(WindowsならMicrosoft Windows Production PCA 2011とMicrosoft Corporation UEFI CA 2011) の公開鍵証明書
Ubuntuを起動する時は、
- PK/
KEKを自作し、 dbにはUEFI CAを使う - PK/
KEKを自作し、 dbにはCanonical CAを使う - PK/
KEKを自作し、 dbにも自作の鍵を使う
いずれもPKとKEKの鍵は自前で作る必要があります
今回は一番簡単な1の方法を紹介します。
「あらこんなところにQEMUが」
今回はテスト用のマシンとして第441回と同じくQEMU/
まずはUbuntu 16.
$ sudo apt install qemu-kvm ovmf $ mkdir secureboot && $_ $ wget http://jp.releases.ubuntu.com/xenial/ubuntu-16.04.1-desktop-amd64.iso $ cp /usr/share/OVMF/OVMF_VARS.fd xenial_OVMF_VARS.fd $ qemu-img create -f qcow2 xenial.qcow2 40G $ qemu-system-x86_64 -m 2G -enable-kvm -vga qxl \ -drive if=pflash,format=raw,readonly=on,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd \ -drive if=pflash,format=raw,unit=1,file=xenial_OVMF_VARS.fd \ -drive if=virtio,file=xenial.qcow2 \ -cdrom ubuntu-16.04.1-desktop-amd64.iso
第441回とはオプションがいくつか異なるものの、-vga qxl
オプション)
あとは普通のUbuntuと同じようにインストールしてください。インストールが完了したら再起動して、
$ cp xenial_OVMF_VARS.fd xenial_OVMF_VARS.fd.bak
今後セキュアブートの設定などでうまく起動しなくなったら、
ここから先の手順は、
「ピッカピカの証明書」
セキュアブートを有効化したい仮想マシン上でPK/openssl
コマンドだけで鍵を作成できます。
作成するものは公開鍵証明書と秘密鍵のセットになります。公開鍵証明書はNVRAM領域に書き込みますが、
まずはRSAの秘密鍵を作成します。
$ mkdir master && cd $_ $ openssl genrsa -out test-key.rsa 2048 Generating RSA private key, 2048 bit long modulus ......................................................................+++ ....................................................+++ e is 65537 (0x10001)
次にこの秘密鍵からPEMエンコードの公開鍵証明書を作成します。
$ openssl req -new -x509 -sha256 -subj '/CN=test-key' -days 3650 -key test-key.rsa -out test-cert.pem
openssl req
はHTTPS向けの設定において、-x509
オプションを指定しています。有効期限の-days
は適当な日数を設定してください。
最後にこのPEMファイルをDERエンコードに変更します。DERはNVRAM変数に保存するデータ形式です。また元になったPEMファイルの方も変数保存時の署名に使いますので、
$ openssl x509 -in test-cert.pem -inform PEM -out test-cert.der -outform DER
今回はdb変数に保存する鍵としてMicrosoftのUEFI CAを使いますので、MicrosoftCorporationUEFICA2011.
」/etc/
に移動します。このディレクトリは、
$ openssl x509 -in MicrosoftCorporationUEFICA2011.crt -inform PEM -out MicrosoftCorporationUEFICA2011.der -outform DER $ cd .. $ chmod 600 master/*.rsa $ chmod 644 master/*.pem master/*.crt master/*.der $ sudo mkdir -p /etc/secureboot/keys/{PK,KEK,db,dbx} $ sudo cp -a master /etc/secureboot/ ls -l /etc/secureboot/master/ 合計 20 -rw-r--r-- 1 shibata shibata 2198 11月 12 15:41 MicrosoftCorporationUEFICA2011.crt -rw-r--r-- 1 shibata shibata 1556 11月 12 15:41 MicrosoftCorporationUEFICA2011.der -rw-r--r-- 1 shibata shibata 765 11月 12 15:31 test-cert.der -rw-r--r-- 1 shibata shibata 1090 11月 12 15:31 test-cert.pem -rw------- 1 shibata shibata 1679 11月 12 15:30 test-key.rsa
「残念ながらPKがない方にセキュアブートを提供することはできません」
PK/test-key.
ファイルとdb用のmicrosoft-uefica-public.
の用意ができました。しかしながらただ作るだけではダメで、
この認証方法についてはUEFI SpecificationのEFI_
descriptor (Recommended)」SignedData
を作成し、SetVariable()
を呼び出します。ファームウェアは、
第444回でも説明したように、
- Setup Mode:PlatformKeyが未設定の時のモード。認証が必要な変数の書き出し時に、
認証をスキップする。 - User Mode:PlatformKeyが設定されている時のモード。認証が必要な変数の書き出し時に、
認証を行う。
今回のケースだと、SetVariable()
に渡す署名の作成は必要です。この認証の諸々を行ってくれるのが、sbsiglist
、sbvarsign
、sbkeysync
コマンドです。このsbsigntoolパッケージはUEFI環境にインストールしたUbuntuシステムであれば、
実際の設定手順を説明していきましょう。まず最初に行うことは、EFI_
)sbsiglist
コマンドを使って生成します。
オーナーのGUID作成 $ owner_guid=$(uuidgen) Microsoft鍵用のGUID作成 $ vendor_guid=$(uuidgen) PK/KEK用の署名データベース作成 $ sbsiglist --owner $owner_guid \ --type x509 \ --output /etc/secureboot/master/test-cert.siglist \ /etc/secureboot/master/test-cert.der db用の署名データベース作成 $ sbsiglist --owner $vendor_guid \ --type x509 \ --output /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist \ /etc/secureboot/master/MicrosoftCorporationUEFICA2011.der $ ll /etc/secureboot/master/*.{der,siglist} -rw-r--r-- 1 shibata shibata 1556 11月 12 15:41 /etc/secureboot/master/MicrosoftCorporationUEFICA2011.der -rw-r--r-- 1 shibata shibata 1600 11月 12 15:45 /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist -rw-r--r-- 1 shibata shibata 765 11月 12 15:31 /etc/secureboot/master/test-cert.der -rw-r--r-- 1 shibata shibata 809 11月 12 15:43 /etc/secureboot/master/test-cert.siglist
GUIDはuuid-runtimeパッケージのuuidgen
コマンドで生成しています。ここではわかりやすさのためにオーナー用の鍵を使う場合とベンダー用の鍵を使う場合で異なるGUIDを設定しています。EFI_
と元のデータの違いは、EFI_
になっている)
次にsbvarsign
コマンドとPK/
PK変数用のデータとして署名 $ sbvarsign --key /etc/secureboot/master/test-key.rsa \ --cert /etc/secureboot/master/test-cert.pem \ --output /etc/secureboot/master/test-cert.siglist.PK.signed \ PK /etc/secureboot/master/test-cert.siglist KEK変数用のデータとして署名 $ sbvarsign --key /etc/secureboot/master/test-key.rsa \ --cert /etc/secureboot/master/test-cert.pem \ --output /etc/secureboot/master/test-cert.siglist.KEK.signed \ KEK /etc/secureboot/master/test-cert.siglist db変数用のデータとして署名 $ sbvarsign --key /etc/secureboot/master/test-key.rsa \ --cert /etc/secureboot/master/test-cert.pem \ --output /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist.db.signed \ db /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist $ ll /etc/secureboot/master/*.{siglist,signed} -rw-r--r-- 1 shibata shibata 1600 11月 12 15:45 /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist -rw-r--r-- 1 shibata shibata 2907 11月 12 15:57 /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist.db.signed -rw-r--r-- 1 shibata shibata 809 11月 12 15:43 /etc/secureboot/master/test-cert.siglist -rw-r--r-- 1 shibata shibata 2116 11月 12 15:57 /etc/secureboot/master/test-cert.siglist.KEK.signed -rw-r--r-- 1 shibata shibata 2116 11月 12 15:57 /etc/secureboot/master/test-cert.siglist.PK.signed
これまでにも述べているように、
最後に作成したデータをsbkeysync
コマンド用のディレクトリにコピーして、sbkeysync
コマンドでUEFIファームウェアに書き出します。
$ sudo cp /etc/secureboot/master/test-cert.siglist.PK.signed /etc/secureboot/keys/PK/ $ sudo cp /etc/secureboot/master/test-cert.siglist.KEK.signed /etc/secureboot/keys/KEK/ $ sudo cp /etc/secureboot/master/MicrosoftCorporationUEFICA2011.siglist.db.signed /etc/secureboot/keys/db/ $ sudo sbkeysync --verbose --pk Filesystem keystore: /etc/secureboot/keys/db/MicrosoftCorporationUEFICA2011.siglist.db.signed [2907 bytes] /etc/secureboot/keys/KEK/test-cert.siglist.KEK.signed [2116 bytes] /etc/secureboot/keys/PK/test-cert.siglist.PK.signed [2116 bytes] firmware keys: PK: KEK: db: dbx: filesystem keys: PK: /CN=test-key from /etc/secureboot/keys/PK/test-cert.siglist.PK.signed KEK: /CN=test-key from /etc/secureboot/keys/KEK/test-cert.siglist.KEK.signed db: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011 from /etc/secureboot/keys/db/MicrosoftCorporationUEFICA2011.siglist.db.signed dbx: New keys in filesystem: /etc/secureboot/keys/db/MicrosoftCorporationUEFICA2011.siglist.db.signed /etc/secureboot/keys/KEK/test-cert.siglist.KEK.signed /etc/secureboot/keys/PK/test-cert.siglist.PK.signed Inserting key update /etc/secureboot/keys/db/MicrosoftCorporationUEFICA2011.siglist.db.signed into db Inserting key update /etc/secureboot/keys/KEK/test-cert.siglist.KEK.signed into KEK Inserting key update /etc/secureboot/keys/PK/test-cert.siglist.PK.signed into PK
「--verbose
」--pk
」/sys/
以下に、
$ ls -1 /sys/firmware/efi/efivars/ | grep '^PK\|^KEK\|^db' KEK-8be4df61-93ca-11d2-aa0d-00e098032b8c PK-8be4df61-93ca-11d2-aa0d-00e098032b8c db-d719b2cb-3d3a-4596-a3bc-dad00e67656f
「OVMFが気になるそこのあなた!」
さて実際に再起動してセキュアブートが有効になっているか確認してみましょう。その前に、

「Device Manager」

正しくPKがセットアップされていたら


どうやら正しく変数が保存されているようです。そこで今度はUbuntuを起動してdmesg
コマンドにログが残っているか確認してみます。
$ dmesg | grep Secure [ 0.000000] Secure boot enabled
無事にQEMU/
「なんだかうまくいかない時は、使うデバイスを変えてみる」
ここまでは仮想マシンにインストール済みのUbuntu上で鍵の更新を行っていました。複数の台数の仮想マシンを用意する場合、
OVMFはPK/
$ dd if=/dev/zero of=usb.img bs=1M count=64 64+0 レコード入力 64+0 レコード出力 67108864 bytes (67 MB, 64 MiB) copied, 0.0418903 s, 1.6 GB/s $ mkfs.vfat -F32 -n"UEFI SECURE KEYS" usb.img mkfs.fat 3.0.28 (2015-05-16) $ sudo mount -t vfat -o loop,rw ./usb.img /mnt $ sudo cp master/*.der /mnt/ $ sudo umount /mnt
OVMFにおいて、
$ cp /usr/share/OVMF/OVMF_VARS.fd plane_OVMF_VARS.fd $ qemu-system-x86_64 -m 2G -enable-kvm -vga qxl \ -drive if=pflash,format=raw,readonly=on,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd \ -drive if=pflash,format=raw,unit=1,file=plane_OVMF_VARS.fd \ -drive if=virtio,format=raw,file=usb.img
前節と同様にESCキーでUEFIメニューを起動し、
- 「PK Options」
で 「Enroll PK」 を選択し、 「Enroll PK Using File」 から先ほど作ったUSBディスクイメージを指定した上で、 PK用の鍵 ( test-cert.
)der を選択します。 「Commit Changes and Exit」 を選べば設定が反映され、 「User Mode」 になります。 - 「KEK Options」
で 「Enroll KEK」 を選択し、 PKと同様の手順でKEK用の鍵 ( test-cert.
)der をEnrollします。 - 「DB Options」
で 「Enroll Signature」 を選択肢、 PKと同様の手順でdb用の鍵 ( MicrosoftCorporationUEFICA2011.
)der をEnrollします。
ここまで完了したらESCキーを何回か押して、plane_
にセキュアブート関連の鍵が登録された状態となっているはずです。
あとはこのファイルを仮想マシン作成時に流用すれば、
何らかの理由でdbを更新したい時も、sbsynckey
を実行すれば更新できるというわけです。