第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を実行すれば更新できるというわけです。