如何使用已安装的自定义密钥对启动 EFI 映像进行安全签名?

如何使用已安装的自定义密钥对启动 EFI 映像进行安全签名?

我一直在尝试配置 U​​EFI 安全启动以使用我自己的密钥实现双启动(Windows 10 + Linux)系统。

该系统是戴尔 XPS 8700(大约 2015 年),带有 American Megatrends 固件/BIOS,以及一些标准硬件升级。

我一直在遵循以下指南:

https://linuskarlsson.se/blog/secure-boot-when-dual-booting-arch-linux-and-windows/

...和:

https://wiki.gentoo.org/wiki/User:Sakaki/Sakaki%27s_EFI_Install_Guide/Configuring_Secure_Boot_under_OpenRC

...而且当然:

http://www.rodsbooks.com/efi-bootloaders/controlling-sb.html

前两个更适合我的情况,因为我希望保留安装的 Microsoft 签名,但 Rod Smith 的网站上有大量信息。

简而言之,我的问题是安装密钥后,我签名的映像无法启动。结果是一个红色的诅咒样式框,其中包含以下文本:

违反安全启动

检测到无效签名。在设置中检查安全启动策略

我尝试过多次,使用了上述站点的各种命令和参数。以及安装密钥的不同工具,例如KeyToolefi-updatevar和我的 BIOS 密钥管理界面。结果总是一样,无法启动用我的密钥签名的映像。

以下是(我认为)成功安装后的安全启动变量的示例:

# efi-readvar
Variable PK, length 831
PK: List 0, type X509
    Signature 0, size 803, owner 7c782a70-901d-454c-a708-4cfb0f432718
        Subject:
            CN=My Secure PK
        Issuer:
            CN=My Secure PK
Variable KEK, length 2393
KEK: List 0, type X509
    Signature 0, size 1532, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation KEK CA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation Third Party Marketplace Root
KEK: List 1, type X509
    Signature 0, size 805, owner 7c782a70-901d-454c-a708-4cfb0f432718
        Subject:
            CN=My Secure KEK
        Issuer:
            CN=My Secure KEK
Variable db, length 3974
db: List 0, type X509
    Signature 0, size 1515, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Windows Production PCA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Root Certificate Authority 2010
db: List 1, type X509
    Signature 0, size 1572, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Subject:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation UEFI CA 2011
        Issuer:
            C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation Third Party Marketplace Root
db: List 2, type X509
    Signature 0, size 803, owner 7c782a70-901d-454c-a708-4cfb0f432718
        Subject:
            CN=My Secure db
        Issuer:
            CN=My Secure db
Variable dbx, length 652
dbx: List 0, type SHA256
    Signature 0, size 48, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Hash:80b4d96931bf0d02fd91a61e19d14f1da452e66db2408ca8604d411f92659f0a
    [...]
    Signature 12, size 48, owner 77fa9abd-0359-4d32-bd60-28f4e78f784b
        Hash:90fbe70e69d633408d3e170c6832dbb2d209e0272527dfb63d49d29572a6f44c
Variable MokList has no entries

我已经验证此配置仍然存在,并且可以成功启动启用了安全启动的 Windows。

我还做了其他一些测试和验证……例如,如果我不安装 Microsoft 的密钥,我就无法在启用安全启动的情况下启动 Windows。有趣的是,Windows 启动管理器将不出现在启动菜单中,但我的“无效”选项(KeyTool、Grub)仍然存在。如果我禁用安全启动,Windows 启动管理器将再次可用。

因此,基于此行为、efi-readvars成功安全启动 Windows 的当前配置(上面的输出)以及我注意到但记不起来的其他事情,我思考我的安全启动变量应该被正确设置。

我所有的尝试和错误都是我之前关于删除附加签名的问题,因为我不想每次创建新密钥或(重新)签署图像时都在图像上堆叠签名。......我已经尝试了几种不同的方法。

对图像进行签名如下:

# sbverify --list /boot/efi/EFI/Grub/grubx64.efi 
No signature table present

...然后:

# sbsign --key db.key --cert db.crt              \
         --output /boot/efi/EFI/Grub/grubx64.efi \
         /boot/efi/EFI/Grub/grubx64.efi  
Signing Unsigned original image

...和:

# sbverify --list /boot/efi/EFI/Grub/grubx64.efi  
signature 1
image signature issuers:
 - /CN=My Secure db
image signature certificates:
 - subject: /CN=My Secure db
   issuer:  /CN=My Secure db

...最后:

# sbverify --cert db.crt /boot/efi/EFI/Grub/grubx64.efi 
Signature verification OK

然而,安全启动却没有起到什么作用。

答案1

可能的原因:旧版本的 sbsign 未正确重新计算 PE/COFF 标头校验和,这导致某些固件拒绝生成的文件。(这仅仅是固定的在 v0.9.3 中。)

请注意,安全启动使用与 Windows 签署 .exe 文件完全相同的“Authenticode”格式来签署 .efi 文件,因此您不需要专门使用 sbsign - 您可以使用其他工具,例如osslsigncode甚至 Windows signtool.exe

osslsigncode sign -cert db.crt -key db.key \
                   -in /boot/efi/EFI/Grub/grubx64.efi \
                   -out /boot/efi/EFI/Grub/grubx64_signed.efi ;

如上所示,注意不要在原地签名改为osslsigncode。这样做会失败,并且图像将被破坏:

# osslsigncode -certs db.crt -key db.key -h sha256 \
      -in /boot/efi/EFI/Grub/grubx64.efi \
      -out /boot/efi/EFI/Grub/grubx64.efi
Bus error

# ls -l /boot/efi/EFI/Grub/grubx64.efi
-rw-r--r-- 1 root root 0 Jun 13 14:55 /boot/efi/EFI/Grub/grubx64.efi

使用以下方式签名的图像osslsigncode仍将得到验证sbverify

# sbverify --list /boot/efi/EFI/Grub/grubx64_signed.efi 
signature 1
image signature issuers:
 - /CN=My Secure db
image signature certificates:
 - subject: /CN=My Secure db
   issuer:  /CN=My Secure db

# sbverify --cert db.crt /boot/efi/EFI/Grub/grubx64_signed.efi 
Signature verification OK

最初的osslsigncode项目是在 1.7.1 版本之后,复活2.0版本于2018年发布。

相关内容