Ubuntu Weekly Recipe

第446回 QEMU/KVMでセキュアブートを利用する

この記事を読むのに必要な時間:およそ 8 分

第441回ではQEMU/KVMでUEFIファームウェアを利用する方法を,第444回ではUEFIのセキュアブート機能について紹介しました。そこで今回は,QEMU/KVMでセキュアブートを利用する方法を紹介します。

「あなたの鍵はどこから?」

第444回でも解説したように,セキュアブートでは少なくとも次の3つの鍵が必要になります。

  • 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を起動する時は,db変数に入っているMicrosftのUEFI CAでshimブートローダーを検証し,shimブートローダーに入っているCanonicalの鍵(Canonical Ltd. Master Certificate Authority)でGRUBやカーネルを検証します。よって,作る鍵の選択肢にはいくつかのパターンがあります。

  1. PK/KEKを自作し,dbにはUEFI CAを使う
  2. PK/KEKを自作し,dbにはCanonical CAを使う
  3. PK/KEKを自作し,dbにも自作の鍵を使う

いずれもPKとKEKの鍵は自前で作る必要があります※1)。1のメリットはshim-signedパッケージにあるshimバイナリをそのまま使えることです。このためルートファイルシステム側はUbuntuをインストールした状態から変更することなく,仮想マシン内部でセキュアブートを体験できます。2はshimブートローダーを使わない方法です。その代わりUEFIブート時にgrub-efi-ARCH-signedパッケージのGRUBバイナリを直接指定します。何らかの理由でMicrosoftの鍵は使いたくない人向けです。3はすべてを自分でコントロールする方法です。UEFI CAやCanonical CAが使えないので,ブートローダーやカーネルを自作の鍵で署名し直す必要があります。カーネルを自分でビルドする場合は,3を選ぶ必要があるでしょう。

※1
KEKやdbには複数の鍵を保存できるので,自前の鍵以外にもKEC CAやUEFI CAを入れておくという選択肢もあります。

今回は一番簡単な1の方法を紹介します。

「あらこんなところにQEMUが」

今回はテスト用のマシンとして第441回と同じくQEMU/KVMを使います。セキュアブートの設定はファームウェアのNVRAM領域への書き込みによって行われるのですが,QEMU/KVMではこのNVRAM領域をホストマシン上のファイルとして扱います。よって簡単にNVRAM領域のバックアップやリストアを行えるのです。ここではQEMUコマンドを直接叩きますが,QEMU/KVMを使っているのであればvirt-managerやGNOME Boxesでもかまいません。

まずはUbuntu 16.04 LTSをインストールしましょう。

$ 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回とはオプションがいくつか異なるものの,基本的にやっていることは同じです。唯一異なるのはグラフィックデバイスとしてQXL-vga qxlオプション)を指定しているところです※2)。QXLは仮想マシンのリモートデスクトッププロトコルとして開発されたSPICE向けの仮想グラフィックデバイスです。ちなみにQXLを使えば,仮想マシン上でもUnity8を試すことができます。

※2
理由は不明ですがセキュアブートを有効にすると,stdディスプレイだとboot_paramsscreen_infoに正しい値が渡らずefifbが乱れるようです。そこで最初からQXLを使うようにしています。

あとは普通のUbuntuと同じようにインストールしてください。インストールが完了したら再起動して,アップデートをすべて適用しておきましょう※3)。この状態で,NVRAM領域をバックアップしておきます。

※3
インストール時にもブートオーダーの変更を行うためにNVRAM領域への書き込みを行います。よってNVRAM領域のバックアップを行うなら,少なくともインストールが終わったあとになります。
$ cp xenial_OVMF_VARS.fd xenial_OVMF_VARS.fd.bak

今後セキュアブートの設定などでうまく起動しなくなったら,とりあえずバックアップファイルでNVRAM領域を上書きすれば,インストール後の状態に戻せるというわけです。

ここから先の手順は,今回作成したゲストマシン上で行います。

「ピッカピカの証明書」

セキュアブートを有効化したい仮想マシン上でPK/KEK用の鍵を作成します。Platform Keyは2048ビットのRSA鍵が推奨されていますのでそれを使うことにしましょう。簡単のためにKEKはPKと同じ鍵を流用します。証明書のフォーマットの選択肢はUEFI Specification上に何種類か指定されています。今回は一般的に使われているDERエンコードされたX.509証明書を作ることにしましょう。またPK/KEKの証明書は自分自身の鍵で署名します※4)。そのためopensslコマンドだけで鍵を作成できます。

※4
まっとうな認証局で署名してもらってもかまいませんが,UEFIファームウェア上でその署名を検証する術はありません。

作成するものは公開鍵証明書と秘密鍵のセットになります。公開鍵証明書はNVRAM領域に書き込みますが,秘密鍵は別に管理が必要です。今回はゲストマシン上に保存しておくことにしましょう※5)。UEFIバイナリ検証用の(db変数に入れる)鍵はMicrosoftのUEFI CAを使うことにしましたので,作成しなければならないのはPK用とKEK用の鍵です。さらに今回はPKとKEKを共用することにしましょう。つまり作る鍵は1つだけです※6)。

※5
セキュアブートのテスト用だから,本当にセキュアでなくてもかまわないという割りきった運用方法になります。もちろんゲストマシン上で鍵を作る必要性は特にありませんので,別の場所で鍵一式を作成し,公開鍵のみをゲストの外から登録する手順でもかまいません。
※6
PKとKEKを別の鍵にしたい場合は,今回説明する方法を複数回実行するだけです。

まずは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向けの設定において,証明書署名要求ファイルを作成するときに使われます。今回はCAによる署名は不要で,自己署名証明書を作るため-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.crtをダウンロードしておいてください※7)。このファイルもPEM形式ですので,DERに変換しておきます。ここまで作った鍵を/etc/securebootに移動します。このディレクトリは,このあと使うツールであるsbsigntoolでも参照するディレクトリです※8)。

※7
Firefoxの場合は「証明書のインポート」ダイアログが表示されるかもしれません。その場合はまず「証明書を表示」を押します。証明書ビューアが起動しますので「詳細」タブのエクスポートボタンを押してファイルとして保存してください
※8
正確にはsbkeysyncコマンドでのみ参照します。他のコマンドの時は別にどこで実行してもかまいませんし,sbkeysyncもオプションを指定すれば任意の場所の鍵ファイルを読み込めます。本記事では項分けの都合で,このタイミングで/etc/secureboot/に移動しています。
$ 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

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member株式会社 創夢所属。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。

コメント

コメントの記入