虚拟机Secure Boot安全启动

概述

Secure Boot 作为 UEFI 的一个选项,它可以被设置为开启或关闭。 Secure Boot 所需要的公钥证书被保存在计算机的主板的 FLASH 里面,FLASH 里面保存着 PK , KEK, db, dbx 的证书链。下面我们在虚拟机中使能Secure Boot功能,可以在虚拟机中实验,这样比较安全。

工具

以下工具是必不可少的:

openssl
efitools
sbsigntools

在有些系统上 efitools 和 sbsigntools 无法直接获取,请从源码包编译,其中efitools依赖 sbsigntools。

yum install -y perl-File-Slurp.noarch
git clone https://gitee.com/mirrors_kernel_googlesource/efitools.git
git clone https://git.kernel.org/pub/scm/linux/kernel/git/jejb/sbsigntools.git/

在用源代码编译 efitools 时,需要 Perl 的一个模块,名字为 File Slurp,上面的命令安装该 module。

步骤

这里简要介绍 PK,KEK,db,dbx 和 MOK 的概念。

Platform Key (PK) - PK 是用于在硬件平台层和硬件平台拥有者建立起的信任关系 ,规定一个硬件平台只能被一个拥有者所拥有,即 PK 只能存在一个 ,与拥有者相关的公钥被存储在 FLASH 里面的 PK 变量里面,同时,拥有者的私钥可以来对 PK, KEK, db, dbx 进行签名和管理。

Key Exchange Key (KEK) - KEK 是用于在硬件平台和操作系统之间建立信任关系 ,KEK 的公钥可以在主板的 FLASH 存在多个不同项,即 KEK 可以存在多个 ,每一项对应一种可以被启动的操作系统,同样,KEK 的私钥可以来对 db, dbx 进行签名和管理。

Database (db) - db 是用于对 被许可的 EFI 文件予以加载的数据签名库 ,和 KEK 一样, db 的公钥可以存在很多项 。(在 UEFI 平台里面,操作系统加载文件就是一个 EFI 文件)

Database Excluded (dbx) - dbx 是一个 黑名单数据签名库 ,只要谁的 EFI 签名在这,谁就被屏蔽掉, dbx 的公钥也可以存在很多项 。后面不会使用这个。

下面主要是有两种方式将证书更新到 flash 中,一种通过 efivar 方式,另外一种是通过 BIOS 图形界面,前者需要创建EFI list 文件,之后可以通过命令行自动化操作;而后者需要的证书文件较少,但是需要通过图形界面进行操作。

自动化导入证书

建立 PK,KEK,db 密钥对,同时还需要创建EFI list。

建立密钥对

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Platform Key/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256

上面的 -subj 的参数可以自己设置,参数 -days 是密钥的有效期,这里设置为 10 年,也可以设置为其他,生成私钥 PK.key,公钥 PK.crt。

同理,KEK 和 db 亦是如此:

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Key Exchange Key/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Database/" -keyout db.key -out db.crt -days 3650 -nodes -sha256

建立 EFI List 文件
EFI List 文件其实就是公钥配以平台拥有者的 GUID 的文件,所以这里我们需要有一个GUID,可以通过uuidgen 生成。

guid=$(uuidgen)
cert-to-efi-sig-list -g $(cat guid) PK.crt PK.esl
cert-to-efi-sig-list -g $(cat guid) KEK.crt KEK.esl
cert-to-efi-sig-list -g $(cat guid) db.crt db.esl

这样三个公钥就全变成 List 文件了。

给 List 文件签名

sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.esl.signed
sign-efi-sig-list -k PK.key -c PK.crt KEK realKEK.esl realKEK.esl.signed
sign-efi-sig-list -k KEK.key -c KEK.crt db realDB.esl realDB.esl.signed

上述中,平台的 Key 权限最高,可以对 PK 本身,和 KEK 签名,KEK 是建立操作系统和硬件平台之间的信任关系,它只用于对于 db 进行签名。

完整的脚本:

#!/bin/bash

echo -n "请输入一个通用名,比如公司名称或个人名字: "
read NAME

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME PK/" -keyout PK.key \
        -out PK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME KEK/" -keyout KEK.key \
        -out KEK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME DB/" -keyout DB.key \
        -out DB.crt -days 3650 -nodes -sha256
openssl x509 -in PK.crt -out PK.cer -outform DER
openssl x509 -in KEK.crt -out KEK.cer -outform DER
openssl x509 -in DB.crt -out DB.cer -outform DER

echo $(uuidgen) > myGUID.txt

cert-to-efi-sig-list -g $GUID PK.crt PK.esl
cert-to-efi-sig-list -g $GUID KEK.crt KEK.esl
cert-to-efi-sig-list -g $GUID DB.crt DB.esl
rm -f noPK.esl
touch noPK.esl

sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
                  -k PK.key -c PK.crt PK PK.esl PK.auth
sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
                  -k PK.key -c PK.crt PK noPK.esl noPK.auth
sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
                  -k PK.key -c PK.crt KEK KEK.esl KEK.auth
sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
                  -k KEK.key -c KEK.crt db DB.esl DB.auth
echo ""
echo "For use with KeyTool, copy the *.auth and *.esl files to a FAT USB"
echo "flash drive or to your EFI System Partition (ESP)."
echo "For use with most UEFIs' built-in key managers, copy the *.cer files."
echo ""

更新到虚拟机的证书列表中
通过写入 efivars 的方式更新到 flash 中,首先必须保证系统的 efivarfs 被正确挂载,ls 一下 /sys/firmware/efi/efivars/ 是否存在文件,否则需要手动挂载:

# mount -t efivarfs efivarfs /sys/firmware/efi/efivars/

再把那三个签过名的 List 文件写入主板:

# efi-updatevar -f PK.esl.signed PK
# efi-updatevar -f realKEK.esl.signed KEK
# efi-updatevar -f realDB.esl.signed db

图形界面导入证书

图形化导入证书只识别后缀名为 .crt, .der , .cer的证书,但是编码方式需要是 DER,所以需要对证书进行一次转换。

openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME PK/" -keyout PK.key \
        -out PK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME KEK/" -keyout KEK.key \
        -out KEK.crt -days 3650 -nodes -sha256
openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$NAME DB/" -keyout DB.key \
        -out DB.crt -days 3650 -nodes -sha256
openssl x509 -in PK.crt -out PK.cer -outform DER
openssl x509 -in KEK.crt -out KEK.cer -outform DER
openssl x509 -in DB.crt -out DB.cer -outform DER

之后将证书拷贝到磁盘中,在虚拟化中可以将宿主机文件镜像以磁盘的形式呈现给虚拟机,我们这里使用单独的一个文件镜像来存储证书。

dd of=data.img if='/dev/zero' bs=1M count=16
mkfs.vfat -I data.img
mkdir mnt
mount data.img mnt
cp -a /path/to/certificates/* mnt
umount mnt/
rm -rf mnt

将文件镜像添加到虚拟机磁盘列表,可以通过virt-manager或者配置文件。

图形化导入证书

  1. 在启动过程中进入启动菜单,选择Security, 这个菜单可能出现的位置稍有不同。
    在这里插入图片描述
  2. 进入Secure Boot Configuration 之后,选择Secure Boot Mode中的Custom Mode, 会多出来一个菜单
    在这里插入图片描述
  3. 进入Custom Secure Boot Options 中进行证书导入
    在这里插入图片描述
  4. 选择导入PK
    在这里插入图片描述
  5. 选择证书文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  6. 导入证书,将证书存储到flash中
    在这里插入图片描述
    其他两个KEK 和 DB 可以导入也可以选择不导入,但是PK 是必须的。
    在之后会提示你需要重启来使刚才的证书和配置生效,此时如果没有对grub 进行签名,需要暂时禁掉 Secure Boot功能。

给二进制的 EFI 文件签名

这是密钥管理和签名的最后一步,给 grub 的 EFI 文件签名:

sbsign --key db.key --cert db.crt --output grubx64.efi.signed /boot/efi/EFI/BOOT/grub64.efi

可以不用给内核 vmlinuz 签名,毕竟 vmlinuz 不是硬件平台的启动 EFI 文件,不过给内核签名也没什么影响,如果想给内核签名类似于给 grub 签名,用 私钥 db.key 及对应的公钥 db.crt 对其签名,这里用的 db 是那个自己创建的 db ,即没有合并微软 db 的那个,合并了微软 db 的是 realDB 。
现在vmlinuz基本都需要支持 EFI 启动,即生成vmlinuz.efi 作为一个EFI应用直接启动,绕过了grub,这种方式下需要使用同样的方式对其进行签名。

sbsign --key db.key --cert db.crt --output vmlinuz.efi.signed vmlinuz.efi

重启系统

重启之后在BIOS中开启Secure Boot 选项,然后一切应该正常了。。。

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值