背景
同样的,在进行了全盘加密后每次boot都需要输入密钥对根目录进行解密,久而久之就会觉得挺麻烦的。在Windows下使用的BitLocker对系统盘进行加密,密钥正是存储在TPM芯片中的,看到Linux内核对TPM2是支持,于是就想将手动输入密钥这一步省略去,从TPM芯片读取进行解密。
开始
准备
在之前的文章中应当是实现了LUKS的全盘加密,顺着走。
首先需要基本管理tpm的软件,在Arch中,安装即可
$ yay -Syu tpm2-abrmd tpm2-tools tpm2-tss
测试TPM是否工作良好,读取存储在TPM中的PCR值
$ tpm2_pcrread
sha1:
0 : 0xA32203D76D2FD203DD76D2FD203D76D21D2C99A8
1 : 0x55CB0B4841FECB0B44841FECB0B4841F9CB64433
2 : 0xB2AFC31EA95BDFC311EA95BDFC31EA955DFD7236
3 : 0xB2AFC31EA95BDFC311EA95BDFC31EA955DFD7236
4 : 0x123B07B3F93E6B07BB3F93E6B07B3F93E6B9C5B7
5 : 0x5F294992FB8CB949992FB8CB94992FB8CB9561B1
6 : 0xB2AFC31EA95BDFC311EA95BDFC31EA955DFD7236
7 : 0xE6CEDBCFC7381EDBCCFC7381EDBCFC7331ED2059
8 : 0x0000000000000000000000000000000000000000
9 : 0x0000000000000000000000000000000000000000
10: 0x0000000000000000000000000000000000000000
11: 0x0000000000000000000000000000000000000000
12: 0x0000000000000000000000000000000000000000
13: 0x0000000000000000000000000000000000000000
14: 0x0000000000000000000000000000000000000000
15: 0x0000000000000000000000000000000000000000
16: 0x0000000000000000000000000000000000000000
17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
23: 0x0000000000000000000000000000000000000000
sha256:
0 : 0x46D108639A20A20B0E15A495B3329C85639A20A20B0E15A495B3329C85BF81DA
1 : 0xE40B13F59B29B2999514F8C32835BEEBF59B29B2999514F8C32835BEEB784292
2 : 0x3D458CFE55CC5CC03EA1F443F114A9FCFE55CC5CC03EA1F443F114A9FC8E7969
3 : 0x3D458CFE55CC5CC03EA1F443F114A9FCFE55CC5CC03EA1F443F114A9FC8E7969
4 : 0x2008CC50255C55C3F518AF21A8D0751D50255C55C3F518AF21A8D0751DD3499A
5 : 0x74572C5B1D49D49B433314DBEFE938FF5B1D49D49B433314DBEFE938FF637DC0
6 : 0x3D458CFE55CC5CC03EA1F443F114A9FCFE55CC5CC03EA1F443F114A9FC8E7969
7 : 0xBCC172045B8CB8C4C81F621F40C486D7045B8CB8C4C81F621F40C486D796E02D
8 : 0x0000000000000000000000000000000000000000000000000000000000000000
9 : 0x0000000000000000000000000000000000000000000000000000000000000000
10: 0x0000000000000000000000000000000000000000000000000000000000000000
11: 0x0000000000000000000000000000000000000000000000000000000000000000
12: 0x0000000000000000000000000000000000000000000000000000000000000000
13: 0x0000000000000000000000000000000000000000000000000000000000000000
14: 0x0000000000000000000000000000000000000000000000000000000000000000
15: 0x0000000000000000000000000000000000000000000000000000000000000000
16: 0x0000000000000000000000000000000000000000000000000000000000000000
17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
23: 0x0000000000000000000000000000000000000000000000000000000000000000
至于其中每个值的含义,这里有一张图,可以看看
含义尚未弄清楚但是偶只知道说存储在一个位置即可,没有其他东西来更改的这个值的,如果你不是Windows的话,从含义可以看出应当是不会影响的。
写入TPM
将密钥写入到TPM2芯片,假设你解密密钥存储的位置是/usr/_crypto_keyfile
一个小问题是密钥的长度,太长了不得行,这个issue指出,长度应该是128淦。
# 清除TPM芯片
tpm2_evictcontrol -C o -c 0x81000000
# 写入密钥
# 这里只用了PCR0和7,PCR4听说是系统生成的,每次内核的更改都需要重新写入一遍密钥
tpm2_createpolicy --policy-pcr -l sha1:0,7 -L policy.digest
tpm2_createprimary -C e -g sha1 -G rsa -c primary.context
tpm2_create -g sha256 -u obj.pub -r obj.priv -C primary.context -L policy.digest -a "noda|adminwithpolicy|fixedparent|fixedtpm" -i /usr/_crypto_keyfile
tpm2_load -C primary.context -u obj.pub -r obj.priv -c load.context
tpm2_evictcontrol -C o -c load.context 0x81000000
rm load.context obj.priv obj.pub policy.digest primary.context
完成过后,你可以使用如下命令将TPM中的密钥取出,和原来的密钥进行比较
tpm2_unseal -c 0x81000000 -p pcr:sha1:0,7 -o /crypto_keyfile.bin
# 记住这个输出路径
更改内核
首先呢参照大佬的脚本再更改一下下,原因为不知道大佬的mkinitcpio.conf是怎么写的,这里摸索了下。
# /etc/initcpio/hooks/encrypt-tpm
#!/usr/bin/bash
run_hook() {
modprobe -a -q tpm >/dev/null 2>&1
modprobe -a -q tpm_crb >/dev/null 2>&1
modprobe -a -q tpm_tis >/dev/null 2>&1
modprobe -a -q tpm_tis_core >/dev/null 2>&1
modprobe -a -q trusted >/dev/null 2>&1
tpm2_unseal -c 0x81000000 -p pcr:sha1:0,7 -o /crypto_keyfile.bin
}
# /etc/initcpio/install/encrypt-tpm
#!/bin/bash
build() {
local mod
add_module "tpm"
add_module "tpm_crb"
add_module "tpm_tis"
add_module "tpm_tis_core"
add_module "trusted"
add_binary "tpm2_unseal"
add_binary "/usr/lib/libtss2-tcti-device.so"
add_runscript
}
help() {
cat <<HELPEOF
This hook allows for reading the encryption key from TPM.
HELPEOF
}
重点来了,上述两个script添加了HOOK动作,在生成内核的时候会被写入进去。下述是节选的关键配置,MODULES中已知的一定要有tpm_tis这个模块,否则在BOOT阶段内核中是没有TPM驱动的,偶把他们都加上了。
另外,BINARIES是上述script中需要使用的,FILES是后面解密LUKS驱动器所需要的 密钥的文件路径,这里的这个路径是默认的密钥的位置,当然也是可以指定的,但是这个根下面的东西在解密后就看不见了,因为解密后的会挂载到根目录,详见Wiki
# /etc/mkinitcpio.conf
MODULES=(vfat ext4 tpm tpm_crb tpm_tis tpm_tis_core trusted)
BINARIES=(tpm2_unseal /usr/lib/libtss2-tcti-device.so)
FILES=(/crypto_keyfile.bin)
HOOKS=(base udev autodetect modconf block filesystems keyboard fsck keymap encrypt-tpm encrypt )
随后重新生成内核,更新grub
#!/bin/bash
mkinitcpio -P
# 根据自己的路径哈
objcopy \
--add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=0x20000 \
--add-section .cmdline="/proc/cmdline" --change-section-vma .cmdline=0x30000 \
--add-section .linux="/boot/vmlinuz-linux" --change-section-vma .linux=0x40000 \
--add-section .initrd="/boot/initramfs-linux.img" --change-section-vma .initrd=0x3000000 \
"/usr/lib/systemd/boot/efi/linuxx64.efi.stub" "/boot/EFI/Archman/grubx64.efi"
grub-mkconfig -o /boot/grub/grub.cfg
可以先试一下,不得行重新写入密钥到TPM。
致谢
感谢大佬们,另外grub好像支持luks2的加密了,不用boot不加密啦。
噢对了,我没有对SecureBoot进行操作,这样还不错。