> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 启用 UEFI 安全启动

UEFI 安全启动通过确保在启动期间仅加载经过验证且受信任的软件，来增强系统的安全性和可靠性。

[安全启动](./security-features#secure-boot)和 [UEFI 安全启动](./security-features#uefi-secure-boot)是不同的安全功能，涵盖用于认证的不同镜像。

UEFI 安全启动可以在安全启动设备上启用，也可以出于测试目的在非安全启动设备上启用。

## **前提条件**

### **主机要求**

1. 在 Linux 主机上安装 [OpenSSL 0.9.80 June 2010（或更高版本）](https://openssl-library.org/source/)。
2. 安装以下 [efitools](https://pkgs.org/download/efitools)：
   > * cert-to-efi-sig-list：将 OpenSSL 证书转换为 EFI 签名列表
   > * sign-efi-sig-list：对 EFI 签名列表进行签名
   > * hash-efi-sig-list：从二进制文件创建哈希签名列表条目

### **在设备上配置重放保护内存块**

重放保护内存块（RPMB）配置是启用 UEFI 安全启动的必要条件。有关更多信息，请参阅 [RPMB](./security-features#rpmb)。

## **配置 UEFI 安全启动以生成密钥和证书**

你可以设置初始 UEFI 安全启动配置，并将密钥和证书转换为 UEFI 可以理解的格式。请参阅工作流程以了解设备外准备和设备上执行的过程。

**图：UEFI 安全启动工作流程**

<img src="https://mintcdn.com/qualcomm-prod/y8h-WRUMxdbs_SSD/System/Security/media-security/k2c-qli-security/uefi-secure-boot-prep-updated.png?fit=max&auto=format&n=y8h-WRUMxdbs_SSD&q=85&s=5921274f50a8b256f59cba1deb7be663" alt="UEFI 安全启动工作流程" width="957" height="467" data-path="System/Security/media-security/k2c-qli-security/uefi-secure-boot-prep-updated.png" />

**注意**

安全通信和加密由 OpenSSL 工具包提供支持，而 UEFI 安全启动的密钥和签名由 efitool 管理。

## **生成密钥和证书**

要启用 UEFI 安全启动，请生成一对用于签名和认证的密钥和证书。

密钥生成支持以下算法：

* 使用 SHA-256/SHA384 哈希算法的 RSA 2048/4096
* ECDSA secp256r1/secp384r1

以下过程以 RSA 2048 和 SHA-256 为例，提供生成密钥和证书的说明。

**注意**

* 在 Linux 机器上执行这些步骤时，请创建一个目录并在同一位置运行命令。
* 对于 ECC，请将 `rsa:2048` 替换为 `ec:secp384r1` 或 `ec:secp256r1`。对于 SHA384，请在以下命令中将 `-sha256` 替换为 `-sha384`。

### **生成 UID**

你可以生成 GUID 并创建三个新密钥，其中自签名证书为 CRT/PEM 格式，密钥为 `.key` 格式：

GUID 使用 `uuidgen` 生成签名所有者 GUID：

```text theme={null}
uuidgen --random > GUID.txt
```

### **创建 PK 密钥**

1. 创建 PK 密钥对（RSA-2048）和证书：
   ```text theme={null}
   openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom PK/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256
   ```
2. 将 `.crt` 文件转换为 `.cer` 文件：
   ```text theme={null}
   openssl x509 -outform der -in PK.crt -out PK.cer
   ```
3. 将 `.crt` 文件转换为 `.esl` 文件：
   ```text theme={null}
   cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
   ```
4. 使用 `.crt`、`.esl` 和 `.key` 文件签名并生成 `.auth` 文件：
   ```text theme={null}
   sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth
   ```

### **创建 KEK 密钥**

1. 创建 KEK 密钥对（RSA-2048）和证书：
   ```text theme={null}
   openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom KEK/" -keyout KEK.key -out KEK.crt -days 3650 -nodes -sha256
   ```
2. 将 `.crt` 文件转换为 `.cer` 文件：
   ```text theme={null}
   openssl x509 -outform der -in KEK.crt -out KEK.cer
   ```
3. 将 `.crt` 文件转换为 `.esl` 文件：
   ```text theme={null}
   cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
   ```
4. 使用 `.crt`、`.esl` 和 `.key` 文件签名并生成 `.auth` 文件：
   ```text theme={null}
   sign-efi-sig-list -k PK.key -c PK.crt KEK KEK.esl KEK.auth
   ```

### **创建 dB 密钥**

1. 创建 dB 密钥对（RSA-2048）和证书：
   ```text theme={null}
   openssl req -new -x509 -newkey rsa:2048 -subj "/CN=Custom DB Signing Key 1/" -keyout db.key -out db.crt -days 3650 -nodes -sha256
   ```
2. 将 `.crt` 文件转换为 `.cer` 文件：
   ```text theme={null}
   openssl x509 -outform der -in db.crt -out db.cer
   ```
3. 将 `.crt` 文件转换为 `.esl` 文件：
   ```text theme={null}
   cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
   ```
4. 使用 `.crt`、`.esl` 和 `.key` 文件签名并生成 `.auth` 文件：
   ```text theme={null}
   sign-efi-sig-list -k KEK.key -c KEK.crt db db.esl db.auth
   ```

## **签名镜像并将（.auth）密钥/已签名文件复制到 EFI 分区**

在使用 systemd-boot 时，EFI 系统分区由 EFI、loader 和 ostree 组成，其中包含与 EFI 相关的信息。DTB 分区由 dtb 目录组成。

EFI 系统分区保存用于系统启动和更新管理的基本文件，而 DTB 分区包含硬件配置信息。本节提供以下操作说明：

> * 对各种镜像进行签名。
> * 将 `(.auth)` 密钥和已签名文件复制到 EFI 分区和 DTB 分区目录。
> * 已签名的可执行镜像（如 `bootaa64.efi` 文件（systemd-boot））放置在 `efimountedbin/EFI/BOOT/` 目录中，`linux-<target-name>.efi` 文件（Linux）镜像放置在 `efimountedbin/EFI/Linux` 目录中。

systemd-boot 会验证已签名的镜像，并且还用于注册以下内容：

> * UEFI 安全启动密钥放置在 `/keys` 中的特定目录中以进行密钥注册。systemd-boot 使用这些密钥，并在 UEFI 启动时服务期间将它们存储在 RPMB 中。
> * 你可以在 systemd-boot 加载器配置中配置等待时间（以秒为单位）。在等待时间内内核加载会被延迟，让你可以在 systemd-boot 菜单中查看和选择可用选项。
> * 设备树文件存储在 `dtbmountedbin/dtb` 目录中。这些文件在运行时由 UEFI 使用，并对设备树文件进行初始化。由于这些文件是非 PE 镜像，签名时会创建 `.sig` 文件并放置在同一目录中。
>   |                                         | **表：EFI 系统分区（efi.bin）**                                                     |
>   | --------------------------------------- | --------------------------------------------------------------------------- |
>   | `/EFI`                                  | `/Loader`                                                                   |
>   | `/Boot/bootaa64.efi`                    | `loader.conf`                                                               |
>   | `/Linux/linux-<target-name>.efi`        | `/keys/authkeys/db.auth` `/keys/authkeys/KEK.auth` `/keys/authkeys/PK.auth` |
>   |                                         | **表：DTB 分区（dtb.bin）**                                                       |
>   | ---                                     | ---                                                                         |
>   | `qclinux_fit.img (or combined-dtb.dtb)` | `qclinux_fit.sig (or combined-dtb.sig)`                                     |

### **将已签名镜像和密钥放入 EFI 分区**

按照以下步骤在 Linux 主机上将已签名的镜像和密钥放入 EFI 分区。

1. 在 `contents.xml` 文件中找到 `efi.bin` 和 `dtb.bin` 的文件路径，以便从 meta 中获取 `efi.bin` 和 dtb.bin\` 文件。
2. 将 `efi.bin` 文件挂载到 `<workspace>` 目录，并在 `<workspace>` 目录中创建 `efimountedbin` 目录。
3. 将 `dtb.bin` 文件挂载到 \<workspace> 目录，并在 \<workspace> 目录中创建 `dtbmountedbin` 目录。
4. 挂载 `efi.bin` 文件：
   ```text theme={null}
   sudo mount efi.bin efimountedbin
   ```
   ```text theme={null}
   cd efimountedbin
   ```
5. 挂载 `dtb.bin` 文件：
   ```text theme={null}
   sudo mount dtb.bin dtbmountedbin
   ```
   ```text theme={null}
   cd dtbmountedbin
   ```
6. 在 `<workspace>/efimountedbin/` 中创建 `loader/keys/authkeys` 目录链以注册密钥。
7. 选择并将 `.auth` 文件（PK.auth、KEK.auth 和 db.auth）复制到 `efimountedbin` 中的 authkeys 目录。
   ```text theme={null}
   sudo cp <selected algo PK/KEK/DB auth files from the files location> <workspace>/efimountedbin/loader/keys/authkeys/
   ```
8. 使用密钥对 `bootaa64.efi`、`linux-<target-name>.efi` 和 `qclinux_fit.img`（或 `combined-dtb.dtb`）二进制文件进行签名，并复制到 `efimountedbin` 和 `dtbmountedbin` 目录中的相应目录。
   1. 签名 `efi` 镜像：
      > sbsign 工具专用于对符合 EFI 规范的 EFI 启动镜像（如 `bootaa64.efi`）进行签名。该工具用于 UEFI 安全启动签名，可在 Linux 系统上下载和使用。需要注意的是，sbsign 只能对扩展名为 `.efi` 的 PE 镜像进行签名。
      >
      > 1. 将 `bootaa64.efi` 文件从 `/efimountedbin/EFI/BOOT` 目录、`linux-<target-name>.efi` 文件从 `efimountedbin/Linux/` 目录复制到 Linux 机器上的 `<workspace>/images` 目录。
      >
      > 2. 签名镜像：
      >
      > > ```text theme={null}
      > > cd <workspace>/images
      > > ```
      > >
      > > > ```text theme={null}
      > > > sudo sbsign --key <workspace>/keys/db.key --cert <workspace>/keys/db.crt bootaa64.efi --output <workspace>/bootaa64.efi
      > > > ```
      > >
      > > ```text theme={null}
      > > sudo sbsign -key <workspace>/keys/db.key --cert <workspace>/keys/db.crt linux<target-name>.efi -output <workspace>/linux<target-name>.efi
      > > ```
   > 2) 签名 dtb 镜像：
   >    由 UEFI 安全启动认证的所有镜像都是常规 API，通常为 PE 格式。签名头和大小被追加到现有的 PE 头中，签名被追加到已签名文件的末尾。
   >    但是，当非 PE 格式的镜像需要 UEFI 安全启动认证时，由于缺少 PE 头及其用于识别镜像格式的魔数，认证会失败。因此，无法使用标准工具和路径进行镜像验证。
   >    目前，在 UEFI 安全启动验证的镜像列表中，只有 dtb 文件是非 PE 格式镜像。作为 sbsign 工具的替代方案，你可以使用 `OpenSSL cms` 命令为非 PE 格式的镜像签名生成签名文件。
   >    按照以下步骤对非 EFI 镜像进行签名：
   >    1. 要对 dtb 文件和签名文件进行签名，请运行以下命令：
   >    > ```text theme={null}
   >    > openssl cms -sign -inkey <.key file> -signer <.crt file> -binary -in <input dtb file>-out <output .dtb.sig file> -outform DER
   >    > ```
   >    2. 要签名镜像，请运行以下命令：
   >    > ```text theme={null}
   >    > cd <workspace>/images
   >    > ```
   >    >
   >    > ```text theme={null}
   >    > sudo openssl cms -sign -inkey <workspace>/keys/db.key -signer <workspace>/keys/db.crt -binary -in qclinux_fit.img <or combined-dtb.dtb> --out qclinux_fit.sig <or combined-dtb.sig> -outform DER
   >    > ```
9. 将已签名的 `qclinux_fit.img`、`linux-<target-name>.efi` 和 `bootaa64.efi` 镜像复制回各自的目录 `(dtbmountedbin/, efimountedbin/Linux/, and efimountedbin/EFI/BOOT/)`。
10. 配置 systemd-boot 管理器显示菜单的超时时间：
    1. 使用 sudo 权限打开并编辑 `/loader/loader.conf` 中的 `loader.conf` 文件：
    > ```text theme={null}
    > sudo vi loader.conf
    > ```
    2. 添加 `timeout 10` 行以设置启动菜单超时时间并保存文件。
11. 要卸载 EFI 二进制文件以获取最新的 `efi.bin` 文件，请运行以下命令：

> ```text theme={null}
> sudo umount efimountedbin
> ```

12. 要卸载 DTB 二进制文件以获取最新的 `dtb.bin` 文件，请运行以下命令：

> ```text theme={null}
> sudo umount dtbmountedbin
> ```

13. 要在目标设备上烧写已签名的镜像和密钥，请将设备置于 Fastboot 模式，并使用以下命令烧写更新后的 `efi.bin` 和 `dtb.bin` 镜像：

> ```text theme={null}
> fastboot flash efi <efi binary location>
>
> fastboot flash dtb_a <dtb binary location>
>
> fastboot reboot
> ```

## **从 systemd-boot 菜单启用 UEFI 安全启动**

确保首先生成 EFI 已签名镜像和安全启动密钥，然后将它们与 systemd-boot 管理器超时配置一起烧写到目标设备上。有关详细信息，请参阅[签名镜像并将（.auth）密钥/已签名文件复制到 EFI 分区](./enable-uefi-secure-boot#sign-images-and-copy-auth-keysigned-files-to-efi-partition)。

**注意**

使用 systemd-boot 管理器将密钥存储到 RPMB 的密钥注册是一次性操作。密钥注册成功后，无法重新配置和更新 UEFI 安全启动密钥。

以下步骤在设备上启用 UEFI 安全启动。

1. 在下次启动期间加载并运行 UEFI 后，systemd-boot 管理器会在串行日志上显示以下交互式菜单。
   ```text theme={null}
   Qualcomm Linux 1.5-ver.1.1 (ostree:0) Enroll Secure Boot keys: authkeys
   Boot in 10 s. ?????????????????????????????????????????????????
   Boot in 9 s. ?????????????????????????????????????????????????
   Boot in 8 s.
   ```
2. 使用 **vol-** 键停止倒计时，此时会显示 **Enroll Secure Boot keys: authkeys**。
3. 使用 **power** 键开始注册。随后会出现一个可中止此注册操作的倒计时，在此倒计时期间请勿按任何键。倒计时结束后，将执行密钥注册操作。以下日志显示了成功的密钥注册。
   ```text theme={null}
   Qualcomm Linux 1.5-ver.1.1 (ostree:0) Enroll Secure Boot keys: authkeys Enrolling secure boot keys from directory: \loader\keys\authkeys
   Warning: Enrolling custom Secure Boot keys might soft-brick your machine!
   Enrolling in 15 s, press any key to abort.
   ...
   Enrolling in  0 s, press any key to abort.
   Custom Secure Boot keys successfully enrolled, rebooting the system now!
   ```
4. 密钥注册成功后，UEFI 会自动从 SetupMode 切换到 UserMode。然后 systemd-boot 会触发设备重启。
5. 在设备下次启动时，UEFI 以 UserMode 启动，UEFI 安全启动即被启用。以下串行日志显示了 UEFI 安全启动成功启用的情况。
   ```text theme={null}
   OS DTB Authentication Success status = 0
   Authenticate OS DTB Success! Status = Success
   And if EFI Stub level logging is enabled through kernel config then,
   EFI stub: Booting Linux Kernel...
   EFI stub: Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path
   EFI stub: UEFI Secure Boot is enabled.
   EFI stub: Using DTB from configuration table
   EFI stub: Exiting boot services...
   ```
6. UEFI 安全启动成功启用后，请恢复 systemd-boot 管理器的超时配置。

## **对未签名镜像进行哈希并更新 DB 以进行镜像认证**

UEFI 安全启动允许进行镜像认证。这种认证是通过存储在签名数据库（dB）中的镜像哈希来实现的，即使镜像未签名或镜像中的证书不在 dB 中。

此过程专用于无法签名或无法更改其供应商提供状态的内容。如果镜像哈希在数据库拒绝（dBX）列表中，则可以在无需吊销相应证书或密钥的情况下移除对已签名二进制文件的信任。例如，在处理容易受到近期漏洞攻击的早期已签名引导加载程序时，这非常有用。

对同一二进制文件同时应用签名和创建 dB 哈希是多余的。如果镜像组成不需要任何更改（即镜像中没有添加或修改新的密钥和证书，且现有镜像不需要 UEFI 安全启动认证），请按照以下步骤操作。

你可以计算镜像的哈希并生成允许的签名 dB 文件。

### **为未签名镜像生成 db.auth 文件**

1. 为所有需要验证的镜像生成哈希，并将哈希转换为 `.esl` 文件：
   ```text theme={null}
   hash-to-efi-sig-list <list of efis to be hashed>  <output file name with .esl extension>
   ```
2. 使用 dB 密钥对 `.esl` 哈希文件进行签名：
   ```text theme={null}
   sign-efi-sig-list -k < .key file location > -c < .crt file location > <secure variable name> <Above generated .esl file> <o/p .auth file>
   ```
3. 将生成的 `db.auth` 文件复制到 EFI 二进制文件中，并将密钥配置到设备中。

例如，在 Linux 主机上：

1. 将 `efi.bin` 文件挂载到 `<workspace>` 目录，并在 `<workspace>` 目录中创建 `efimountedbin` 文件夹。
2. 在 Linux 机器的 `<workspace>` 目录中创建 `testkeys` 文件夹，并将已有的密钥复制到其中。
3. 签名镜像：
   ```text theme={null}
   hash-to-efi-sig-list <workspace>/efimountedbin/EFI/BOOT/bootaa64.efi mergedhash.esl
   ```
   ```text theme={null}
   sign-efi-sig-list -k keys db.key -c db.crt db mergedhash.esl db.auth
   ```
4. 将 `db.auth` 文件复制到 `<workspace>/efimountedbin/loader/keys/qckeys` 中的 `qckeys` 文件夹。
5. 按照 dtb 签名步骤对 dtb 镜像进行签名，以生成新的 `efi.bin` 文件。有关更多信息，请参阅[签名镜像并将（.auth）密钥/已签名文件复制到 EFI 分区](./enable-uefi-secure-boot#sign-images-and-copy-auth-keysigned-files-to-efi-partition)。
6. 对于目标设备上的 Linux 主机操作：
   1. 擦除任何现有的 UEFI 安全启动密钥，并使用 fastboot 烧写 EFI 二进制文件。
   2. 使用 systemd-boot 配置密钥。有关更多信息，请参阅[从 systemd-boot 菜单启用 UEFI 安全启动](./enable-uefi-secure-boot#enable-uefi-secure-boot-from-systemd-boot-menu)。
      **注意**
      使用此方法，所有未签名的文件都会使用其他密钥进行签名，并通过 UEFI 进行认证。

## **后续步骤**

* 有关芯片组功能管理以及升级芯片组功能包，请参阅[安装或升级 SoftSKU 功能包](./install-or-upgrade-the-soft-sku-feature-packs)。
* 要定制内存和 SEPolicy，请参阅[定制安全服务](./customize-security-services)。
* 有关常见的日志记录和调试技术，请参阅[调试 Qualcomm TEE 和安全设备](./debug-qualcomm-tee-and-secure-devices)。
