clevis が ubuntu で対応してた。
clevis ツールでdrucat を使わなくても initramfs で、起動時にLUKSのアンロックができるようになってたらしい。
これは便利ですね。
参考資料にしたブログがよく書いてくれてるので、とても簡単だった。
準備
clevis が動作しないときに備えて、シリアル・ポートとSSHアンロックを最初に準備しておく。
実験環境を作る
いきなり、PCでやるとミスったときに initramfsを書き戻すのが手間なので、実験用に、Nested VMで、ホスト側でswtpm 有効化して、ゲスト側でtpm2 を使った仮想マシンを作成して実験をすることにする。
ttyS0 をgrub 起動でやる
以前やって試しておいた、grub でシリアル・コンソールを有効にする方法で、grub を有効にする。これでシリアルケーブルを繋いだraspiを挿しておけば、万が一のときリモートからアンロックができる。
boot
のバックアップ
やかしたら面倒なので、バックアップをとっておく。
sudo tar cvzf boot.tgz /boot
luksのssh のアンロック
これも以前やって試しておいた。起動時にdm-cryptをSSHでリモートアンロックする方法で、clevis が動作しないときに、リモートから何とかできる経路を用意しておく。
clevis のインストール
clevis を使った initramfs と clevis のtpm2対応パッケージを入れておく
sudo apt install clevis clevis-tpm2 clevis-initramfs
アンロック対象の暗号ブロックデバイスの確認
アンロックの対象になる、ブロックデバイスの名前を確認しておく。
takuya@u0201:~$ lsblk vda 252:0 0 40G 0 disk ├─vda1 252:1 0 512M 0 part /boot/efi ├─vda2 252:2 0 1G 0 part /boot └─vda3 252:3 0 38.5G 0 part └─dm_crypt-0 253:0 0 38.5G 0 crypt └─ubuntu--vg-ubuntu--lv 253:1 0 20G 0 lvm /
今回は、仮想マシンで行っているので /dev/vda
が対象で、EFIブートなので対象パーティションは /dev/vda3
になる。
PCR (Platform Configuration Registers) の確認
PCR を使って、TPMに登録してハッシュ値を計算した結果から、データ改竄をチェックするのに必要。ここではTPMデバイスで使える暗号学的ハッシュ関数を確認しておく
takuya@u0201:~$ sudo tpm2_getcap pcrs [sudo] password for takuya: selected-pcrs: - sha1: [ ] - sha256: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 ] - sha384: [ ] - sha512: [ ]
sha256が使えるとわかる。
clevis に鍵設定する
clevis に鍵を設定する。ここではパスフレーズを使う。
takuya@u0201:~$ sudo clevis luks bind -d /dev/vda3 tpm2 '{"pcr_bank":"sha256","pcr_ids":"7"}' Enter existing LUKS password: ## ちょっと時間かかる
登録されたかチェック
takuya@u0201:~$ sudo clevis luks list -d /dev/vda3 1: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}'
ここ出てくる 1
という番号は cryptsetup luksDump /dev/vda3
で 確認できるキースロットの番号に対応している。
initramfs を更新する
sudo update-initramfs -u -k 'all'
再起動してチェック
takuya@u0201:~$ sudo reboot
initramfs に clevis が登録されたかチェック
lsinitramfs で initramfs の中身を見れる。
takuya@u0201:~$ sudo lsinitramfs /boot/initrd.img-$(uname -r) | grep clevis scripts/local-bottom/clevis scripts/local-top/clevis usr/bin/clevis usr/bin/clevis-decrypt usr/bin/clevis-decrypt-sss usr/bin/clevis-decrypt-tang usr/bin/clevis-decrypt-tpm2 usr/bin/clevis-luks-common-functions usr/bin/clevis-luks-list
削除
clevis 側の設定を削除する
sudo clevis luks unbind -d /dev/vda3 -s 1 The unbind operation will wipe a slot. This operation is unrecoverable. Do you wish to erase LUKS slot 1 on /dev/vda3? [ynYN] y
スロットにいくつか残ってる場合は、一覧(List)をみながら順番に消す。
たとえば、下記の例では、4つのLUKSスロットを使っている。
sudo clevis luks list -d /dev/vda3 0: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}' 1: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}' 4: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}' 5: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha256","pcr_ids":"7"}'
順番に消す。(LUKSのヘッダからキースロットを削除している)
sudo clevis luks unbind -d /dev/vda3 -s 0 sudo clevis luks unbind -d /dev/vda3 -s 1 sudo clevis luks unbind -d /dev/vda3 -s 4 sudo clevis luks unbind -d /dev/vda3 -s 5
tpm 側で削除する.tpmをまっさらにしたら全部消える。tpm側で削除しても clevis 側に残るので注意
sudo tpm2_clear
やってみた結果
めっちゃ手軽になってて感動した。
2022-01-07 追記
Debian/11 でも問題なく同じ手順で動くことを確認した。
luks の自動unlock が動いてたときのcryttab は本当に何もしてないシンプルな構成。これでdm-cryptとtpm2さえあれば安心ができますね。
takuya@d0201:~$ cat /etc/crypttab vda3_crypt UUID=276f641e-c6cd-489b-8b5b-33e65c6405e6 none luks,discard
2022/01/07 追加
initramfs がだいぶサイズが大きくなるので、/boot
が200MBでは容量不足になった。注意が必要。
takuya@:~$ sudo update-initramfs -u -k 'all' update-initramfs: Generating /boot/initrd.img-5.10.0-10-amd64 setupcon: The keyboard model is unknown, assuming 'pc105'. Keyboard may be configured incorrectly. pigz: abort: write error on <stdout> (No space left on device) E: mkinitramfs failure pigz 28 update-initramfs: failed for /boot/initrd.img-5.10.0-10-amd64 with 1.
2022-01-09 追記
最終的に出来上がった initrd は 75Mになった。ブート時に使うには、相当でかいパッケージです。
takuya@:~$ ll -lh /boot/initrd.img-5.10.0-10-amd64 -rw------- 1 root root 75M 1月 9 01:47 /boot/initrd.img-5.10.0-10-amd64
/boot に最低2つのinitradのブートイメージが用意される。万が一のためにカレントと1世代前のinitrdが2つ用意される。これで、75MB✕2=150MBが消費される。
更新時は、新しくinitrdを作って、mvで旧来のファイルを置き換えるので、 +75MBが追加で必要。
さらに、update-initramfs -c -k all したときには、1世代前のinitradも再構成されるので、+75Mが必要
つまり、clevis化した/boot
には、最低でも4つにカーネルが入るだけの容量が必要で、最低でも 300Mが必要になる。
古いカーネルなど複数バージョンのカーネルを持ってる場合はもっと必要になるかもしれません。
なので、 /bootには1GBくらい割り当てないと詰むと思います。
今回、私は見事に、ここで容量不足で詰んでしまいました。luks化された領域ディスク内で開始セクタを簡単に動かせないので、バックアップをとってSSDをまっさらにして/boot を1GB確保する羽目になり、時間が思い切り溶けました。
でも、これでTPM化されて安心です。