2015年5月14日木曜日

SecureBootとLinux

みなさんUEFIしてますか(挨拶)

UEFIではSecureBootという機能があり,Windows以外が起動できないかもしれない云々という話はみなさんの記憶に新しいかと思います.

将来の話はともかく,現状でもSecureBootが有効だとLinuxが起動できないという誤解も一部蔓延してるようなので本記事を執筆するものであります.

本記事はSecureBootを有効にしてLinuxを起動しようとしてたけどイマイチ方法わからなかったという人にも有効かと思われます.

前提

今回は1st BootLoaderにshim.efi,2nd BootLoaderにrEFIndを用います.
shim.efiは,Fedoraで使われている,Microsoft鍵によって署名されたブートローダーです.
rEFIndはAppleのマシンでよくつかわれるUEFIのブートローダーであるrEFItのforkで,
OS X以外の様々なOSが扱いやすくなっています(ex. hfs(+),ext2/3/4,ntfs,iso9660,btrfs,reiserfsのファイルシステムのUEFIドライバを備えており,読み出す事ができる).

前準備

まずはSecureBootを無効化した状態で,rEFIndでLinuxを起動できるようにする必要があります.
本記事ではrEFIndのインストール,設定方法については触れないので,各自調べたりしてください.
http://orumin.blogspot.jp/2014/07/linuxrefind.html 拙筆の過去記事も参考になるかもやしれません.

それでは,以下よりEFI SYSTEM PARTITION(以下ESP)の\EFI\refind\以下にrEFIndがインストールされており,Linuxは起動可能であるとして話を進めます.

手順

必要なものの準備

まず,署名されたshim.efiおよびrEFIndを使う必要があります.
shim.efi: http://www.codon.org.uk/~mjg59/shim-signed/
rEFInd: http://www.rodsbooks.com/refind/getting.html

もし,前準備としてインストールしたrEFIndがディストリビューションのパッケージマネージャのものであるならば,上記URLよりzipをダウンロードしてインストールしなおしたほうが良いかもしれません.
少なくともArchLinuxではrEFIndがディストリビュータにより作られたバイナリで配布されており,署名鍵でverifyしてもエラーが出ます.

また,shim.efiについては新しいバージョンのものをダウンロードすることをおすすめします.

設定

次に,ダウンロードしたshim.efiの中身について,shimx64.efiとMokManager.efiをどちらも
refindのインストールしたディレクトリに保存します.
そして,refind_x64.efiはgrubx64.efiとrenameしてください.これは,shim.efiがGRUB2をロードするようにハードコードされているためです.

また,UEFIのBootEntryのPathについて,refind_x64.efiではなくshimx64.efiを登録しなおしてください.

MOK

MOK: Machine Owner Keys とはUEFIのBootVarに保存されるセキュアブートのための鍵リストで,自分の鍵を追加する事が可能です.

SecureBootは鍵署名されたブートローダーが読むバイナリについて,ブートローダーが鍵を検証する必要があります.信用されたバイナリによる鍵の検証のチェインを作って,信頼性を担保しています.

OpenSUSEのサイトより引用
よって,まずUEFIバイナリ用の署名ツールをインストールします.
pesign: https://github.com/rhinstaller/pesign
sbsigntool(git tree): git://kernel.ubuntu.com/jk/sbsigntool.git
それぞれ,前者はFedoraで,後者はUbuntuで用いられています.

そして次に自分の鍵を作成します.

$ openssl req -new -x509 -newkey rsa:2048 -keyout MOK.key \
-out MOK.crt -nodes -days 3650 -subj "/CN=Your Name/"
$ openssl x509 -in MOK.crt -out MOK.cer -outform DER
Your Nameは自分の名前で大丈夫です.

こうして作られたオレオレ署名鍵をつかって署名します.
カーネルとカーネルモジュールを署名する必要があります.

ディストリビューションによっては,パッケージマネージャによってインストールされたカーネルは既に署名済みの可能性があります.rEFIndのインストールディレクトリにあるkeysディレクトリの中に,自分のディストリビューションの名前の鍵があれば,署名鍵を作る必要も署名する必要もないです(おそらく).

AltLinux,Fedora,RedHat Enterprise,Ubuntu,OpenSUSE,SUSE Linux Enterpriseでは署名済みだと思われます.(そもそもこの記事の内容の一切をしなくても標準で対応できるはずです)
ただしこれらディストリビューションで自前ビルドカーネルを使ってSecureBootしたいときは以下の内容は役立ちます.

では,署名の方法です.
今回はsbsigntoolで署名する方法について説明します.

$ sbsign --key MOK.key --cert MOK.crt <inputfile>
これだけです.こうすると,入力ファイルに拡張子.signedが付いたファイルが同じディレクトリに出力されます.これが署名済みバイナリです.署名されてるか確認するのは
$ sbverify --cert MOK.crt <inputfile>
と署名済みバイナリをコマンドに与えたとすると
 Signature verification OK
と出るはずです.

仕上げ

先程作ったオレオレ鍵の,拡張子が.cerのファイルをESPに置いておきます.
では,再起動してみましょう.SecureBootを有効化しても大丈夫のはずです.
rEFIndが起動したら,下側に鍵マークのアイコンが増えてるはずなのでそれを選択.

そしたら,その後にEnroll keyを選択します.

次に,ファイルシステムの一覧が出てくるので,ESPのファイルシステムを選択し,
その後refindのインストールディレクトリのkeys以下にあるrefind.cerと,先程ESPに置いたオレオレ鍵の.cerを選択します.

そうするとMokManager.efiによりMOKに鍵が登録されます.

おめでとうございます! これで貴方のカーネルはSecureBoot EnabledなUEFIにより起動できるようになりました!
MokManager.efiはもうESPから削除しても構いません.

四方山話

UEFIのベンダによっては,MokManager.efiを使わずともUEFIの設定画面から鍵登録や鍵のクリアをする事ができる場合があります.オレオレ鍵こんなに簡単に使えて大丈夫なのか?と思われるかもしれませんが,例えば悪意あるユーザに侵入され,ブートローダーをBootkitに置き換えられたとしても,そのオレオレ鍵が盗まれそれで署名された等でなければSecureBootにより弾かれるだけで終わります.Secureですね.

ちなみに,起動後のLinuxで,
$ od /sys/firmware/efi/vars/SecureBoot-<UUID>/data
をして出てきた値の末尾が1になってるのがSecureBootの証です.

ただし,OpenSUSEの先程画像を引用したページによると
セキュアブートモードでブートする場合、以下の制限が適用されます。
  • ハイブリッド化されたISOイメージは、UEFIシステムでブート可能とみなされません。このため、USBデバイスからのUEFIブートは、SP3でサポートされません。
  • セキュアブートを簡単に回避できないようにするため、セキュアブートで実行する場合は一部のカーネル機能が無効になっています。
  • ブートローダ、カーネル、およびカーネルモジュールが署名されている必要があります。
  • kexecおよびkdumpが無効になっています。
  • ハイバネーション(ディスクの休止)は無効になっています。
  • ルートユーザであっても、/dev/kmemおよび/dev/memにアクセスできません。
  • ルートユーザであっても、I/Oポートにアクセスできません。すべてのX11グラフィカルドライバはカーネルドライバを使用する必要があります。
  • sysfs経由でPCI BARにアクセスすることはできません。
  • ACPIのcustom_methodは使用できません。
  • asus-vmiモジュールに対してdebufgsを使用できません。
  • acpi_rsdpパラメータはカーネルに影響を及ぼしません。

との事なのでご注意を