如何在 Linux 系统启用 UEFI 的 Secure Boot

概述

Secure Boot 作为 UEFI 的一个选项,它可以被设置为开启或关闭 ( 有少数恶心的计算机里面, Secure Boot 被设置为开启,却不存在关闭它的选项,但系统主板内置有 Windows 系统的公钥证书签名,使其只能加载 Windows ,其他系统一律不以加载,用户没的选,不能关闭,还没法换系统,真的很恶心)。 Secure Boot 所需要的公钥证书被保存在计算机的主板的 FLASH 里面(注意不是磁盘里面哦),在主板的一小块 FLASH 里面保存着 PK , KEK, db, dbx 的证书链,所以, 在操作开始前请确保你的计算机 UEFI-BIOS 的 Secure Boot 能够被关闭,否则,发生操作失误,将导致证书不能匹配任何程序代码文件,而使主板拒绝加载任何程序代码文件,就会导致主板变砖 (虽然它不是 BIOS ,但是许多人都这么称呼它为 UEFI-BIOS ,所以,这里也这么称呼其为 UEFI-BIOS) 。

这里说一下 Fedora 是如何做到在 Secure Boot 开启时加载的,它实际上是 Fedora 开源项目向微软垄断公司购买了私钥来签名达到的, Fedora 被系统的主板识别为和 Windows 一样的东西,这种购买行为在开源社区是不鼓励的,但是 Fedora 几乎可以在任何可以加载 Windows 系统上被加载(我上面写不能换系统,有点苛刻了,实际上,只要微软同意,是可以换系统的,呵呵)

本人只在 ThinkPad 测试成功,其他机器未曾实验过,不过仅从理论来看,应该也会成功。

工具

以下工具是必不可少的:

  • openssl
  • efitools
  • sbsigntools

如果你是第三方编译好的软件包来安装的,可以忽略此步:

在用源代码编译 efitools 时,需要 Perl 的一个模块,名字为 File Slurp,在 cpan 可以找到。

预先准备

开机进入系统的 UEFI-BIOS 页面,在安全页面里找到 Secure Boot 选项,先关掉 Secure Boot (如果没有关的话),再删除或清空所有证书文件,使机器从 User Mode 转到 Setup Mode 即为正常,如果这两步不能做到,可能影响到下面的步骤。

步骤

概念介绍

这里简要介绍 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 的公钥也可以存在很多项

  • Machine Owner Key (MOK) - MOK 的作用是等价于 db 的,但是它不是标准 Secure Boot 的内容,PreLoaderShim 使用了 MOK 。

建立 PK,KEK,db 密钥对

这里需要 Linux 系统中存在 uuidgen

echo $(uuidgen) >guid

如果你不打算启动 Windows 系统,请忽略文中所有提及有关 Windows 系统的内容

如果系统不存在 uuidgen,就随便写个 GUID 到那个 guid 文件里,然后把微软的 Owner GUID 写到另外一个文件里:

echo  77fa9abd-0359-4d32-bd60-28f4e78f784b >ms-guid

建立密钥对:

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

这里没有建立 dbx 的黑名单,因为暂时用不到这个,也没有黑名单签名文件,MOK 不通用,亦不讨论

建立 EFI List 文件

EFI List 文件其实就是公钥配以平台拥有者的 GUID 的文件:

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 文件了。

为了能够也启动磁盘里的 Windows 系统,下载三个微软的公钥,一个 KEK,两个 db:

curl -L http://go.microsoft.com/fwlink/?LinkID=321185 -o MSKEK.der
curl -L http://go.microsoft.com/fwlink/?LinkID=321192 -o MSdbWPCA.der
curl -L http://go.microsoft.com/fwlink/?LinkID=321194 -o MSdbUDSCA.der

微软的这三个公钥与这里使用的公钥格式不同,需要重新转换:

openssl x509 -in MSKEK.der -inform DER -out MSKEK.crt
openssl x509 -in MSdbWPCA.der -inform DER -out MSdbWPCA.crt
openssl x509 -in MSdbUDSCA.der -inform DER -out MSdbUDSCA.crt

同样需要转换成 List 文件,不过这里的 GUID 最好用微软 Owner GUID:

cert-to-efi-sig-list -g $(cat ms-guid) MSKEK.crt MSKEK.esl
cert-to-efi-sig-list -g $(cat ms-guid) MSdbWPCA.crt MSdbWPCA.esl
cert-to-efi-sig-list -g $(cat ms-guid) MSdbUDSCA.crt MSdbUDSCA.esl

在这里需要注意一下,在 ThinkPad 里面,第二次添加 KEK 时(加参数 -a ),会出现失败,我的解决方法是把那些 List 合并成一个 List 文件,即:

cat KEK.esl MSKEK.esl >realKEK.esl
cat db.esl MSdbWPCA.esl MSdbUDSCA.esl >realDB.esl

根据 efitools 的文档,这种 cat 操作是可以完成合并的。

给 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 进行签名。

给二进制的 EFI 文件签名

这是密钥管理和签名的最后一步,我使用的 grub ,其他的比如 elilo 等等,同理。给 grub 的 EFI 文件签名:

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

可以不用给内核 vmlinuz 签名,毕竟 vmlinuz 不是硬件平台的启动 EFI 文件,不过给内核签名也没什么影响,如果想给内核签名类似于给 grub 签名,用 私钥 db.key 及对应的公钥 db.crt 对其签名,这里用的 db 是那个自己创建的 db ,即没有合并微软 db 的那个,合并了微软 db 的是 realDB

写入 efivars

到这里是整个过程的最后一步,首先必须保证系统的 efivarfs 被正确挂载,ls 一下 /sys/firmware/efi/efivars/ 是否存在文件,有的系统默认挂载 efivarfs ,有的则不是(后续步骤需要切换至 root 用户):

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

参考 LinuxQuestions 上的解决方案,使用了在 efi-updatevar 添加 -a 参数来表示添加,但是在 ThinkPad 上多次实验第二次皆以 Operation not permitted 的错误而中断,所以,合并 EFI List 文件即只需添加一次,就全部都被加上,无需再用 -a 来添加。上述的问题很难判断是密钥链的逻辑问题,还是硬件的保护机制,不过用合并这种方法,在 Secure Boot 下,Windows 和 Linux 都可以正常启动,看来没问题。

所有操作都完成后,可以运行 efi-readvar 来查看添加结果。只要 efivarfs 仍然被挂载,即使在非 root 用户也可以查看。

相关链接

docs.slackware.com

linuxquesions.org

howtogeek.com

archlinux.org

pcworld.com

如何在 Linux 系统启用 UEFI 的 Secure Boot相关推荐

  1. Redis进阶实践之二如何在Linux系统上安装安装Redis

    2019独角兽企业重金招聘Python工程师标准>>> Redis进阶实践之二如何在Linux系统上安装安装Redis 一.引言 上一篇文章写了"如何安装VMware Pr ...

  2. 在linux中 如何创建磁盘配额,如何在Linux系统中配置磁盘配额?

    今天我们看看如何在Linux系统中配置磁盘配额,限制用户滥用空间.使用磁盘配额是相当简单的,对于限制那些过多占用磁盘空间的家伙很有用.而且,你还可以设置软配额和硬配额,软配额可以在某个用户接近其容量空 ...

  3. 我的linux系统怎么输入pv,如何在Linux系统中使用pv命令

    本文介绍了如何在Linux系统中使用pv命令.内容很详细.有兴趣的朋友可以参考一下,希望对大家有帮助. PV 命令 PV由Andrew Wood开发,是Pipe Viewer的简称,意思是通过管道显示 ...

  4. 如何在Linux系统上监测系统温度?(亲测可用)

    转载自:http://os.51cto.com/art/201311/417208.htm 按理说,在大多数情况下,你用不着为电脑的运行温度而操心.除了制造瑕疵外,电脑硬件在设计时确保温度不会超过最高 ...

  5. 如何在Linux系统下安装英特尔® Arc™系列独立显卡驱动以及进行AI推理性能测试...

    点击蓝字 关注我们,让开发变得更有趣 作者 | 周兆靖 排版 | 李擎 如何在Linux系统下安装英特尔® Arc™系列 独立显卡驱动以及进行AI推理性能测试 目录 1.本文目的 2.Linux 系统 ...

  6. linux检测软件温度,如何在Linux系统上监测系统温度?(亲测可用)

    转载自:http://os.51cto.com/art/201311/417208.htm 按理说,在大多数情况下,你用不着为电脑的运行温度而操心.除了制造瑕疵外,电脑硬件在设计时确保温度不会超过最高 ...

  7. 如何在Linux系统上部署接口测试环境

    作为一名软件测试人员,部署测试环境是我们日常工作的一部分,今天就简单整理下接口测试环境部署的步骤,希望能够帮助到大家. 今天为大家整理的接口测试环境部署涉及到Tomcat,JDK和数据库.目前能够提供 ...

  8. linux 新用户 界面登录,如何在Linux系统登录界面加入个性化提示信息

    如何在Linux系统登录界面加入个性化提示信息 Linux字符界面看久了容易乏味,如果在登录时加点个性化显示看着也比较舒服,下面小编就给大家介绍下如何在Linux系统登录界面加入个性化提示信息,一起来 ...

  9. 如何在Linux系统上自动执行任务

    How to automate tasks on a Linux system 如何在Linux系统上自动执行任务 https://www.linux.org/threads/how-to-autom ...

最新文章

  1. 在使用模板时遇到的错误,TypeError at /index/ context must be a dict rather than RequestContext(亲测)
  2. 从原理到方法,一文讲清如何应对C语言内存泄露!
  3. lxcfs容器隔离技术实现原理分析之loadavg、cpuonline
  4. c语言生产者与消费者实验报告,生产者和消费者实验报告.doc
  5. numpy合并两个ndarry或多个
  6. c++ mysql 写库 乱码 ??_mysql c++ 乱码 解决方法
  7. linux 运行菜刀,Linux部署常用命令
  8. 计算机程序配置不正确 请联系我们,电脑应用程序配置不正确怎么办
  9. vodplayer.exe
  10. 贝叶斯公式理解与应用
  11. 多路测温系统C51语言,基于单片机的多路温度检测系统的.docx
  12. LVGL——lv_gauge 仪表盘
  13. 扫描隧道显微镜STM功能介绍及用途
  14. 关于提问的一些书籍及文章
  15. 用C语言编程取出八个球,带你解决C语言编程问题~之口袋放球取法
  16. C/C++ getcwd 获取项目的运行路径
  17. 中国移动云mas短信对接(http)
  18. 电脑D盘格式化了怎么恢复
  19. 谷歌浏览器 无法翻译此网页问题(已解决,亲测有效
  20. 可以玩所有游戏的计算机配置,笔者教你玩大型游戏的电脑配置

热门文章

  1. Redmibook 14 EE 电脑 Hackintosh 黑苹果efi引导文件
  2. html tabl自动生成序列号,如何为el-table组件添加序号
  3. 图像金字塔,原理、实现及应用
  4. Crontab配置及使用总结
  5. java rsautil_JAVA 通过RSA获取公钥私钥工具类
  6. 1989年个人简历_像1989年一样进行计算
  7. 超时空的爱情--胡彦斌
  8. LWN:用户空间的中断!
  9. 基于Labview的计算机声卡声音信号的采集系统设计
  10. C++中vector使用方法