EDKII之安全启动详细介绍

devtools/2024/9/20 1:38:56/ 标签: 安全, UEFI, BIOS, 驱动开发

文章目录

安全启动简介

安全启动(Secure Boot)是一种计算机系统的安全功能,旨在确保系统启动过程中只能加载经过数字签名的受信任的操作系统和启动加载程序。通过使用安全启动,系统可以防止恶意软件在启动过程中植入并运行,提高系统的安全性。

安全启动的工作原理通常包括以下几个步骤:

  1. 启动固件验证:在计算机启动时,启动固件(如UEFI固件)会验证操作系统引导加载程序的数字签名,确保其来自受信任的发布者。
  2. 操作系统验证:启动加载程序会验证操作系统内核和驱动程序的数字签名,以确保它们没有被篡改。
  3. 启动链验证:整个启动链中的每个组件都会被验证,包括引导加载程序、内核、驱动程序等。
  4. 安全启动状态:如果所有组件的数字签名验证通过,系统将进入安全启动状态,允许操作系统正常加载和运行。

通过安全启动,系统可以有效防止恶意软件在启动过程中进行植入和篡改,提高系统的整体安全性。安全启动通常与UEFI固件结合使用,是现代计算机系统中的重要安全功能之一。

BIOS启动过程中会执行BootLoader来加载系统,最常用的就是GRUB,它可能是一个名为bootx64.efi的UEFI应用。BIOS启动的最后会将控制权交给这个bootx64.efi,并由后者来启动系统。但是这里存在一个问题,如何保证这个应用真的是我们需要的呢?如果该应用被修改甚至替换了,导致执行一些我们不希望其执行的代码,则是一个非常严重的安全漏洞。

安全启动流程介绍

在这里插入图片描述

在这里插入图片描述
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 的公钥也可以存在很多项 。后面不会使用这个。

测试方法:
建立 PK,KEK,db 密钥对,同时还需要创建EFI list。

在这里插入图片描述
在这里插入图片描述

  1. 加载PK。 ROOTCA.cer

在这里插入图片描述
加载KEK.CER,同样方法加载DB.CER
众所周知,进入EFI SHELL下,当不开启Secure Boot的时候 是可以执行efi 文件的,但是当我们打开Secure Boot 就不是所有efi 文件可以加载
在这里插入图片描述

签名过程

我们怎么签名Efi文件和启动项,怎么导入对应的证书呢?


```bash
#!/bin/bashecho -n "请输入一个通用名,比如公司名称或个人名字: "
read NAMEopenssl 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 DERecho $(uuidgen) > myGUID.txtcert-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.eslsign-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 ""
运行后生成一组密钥

`在这里插入图片描述
``

在这里插入图片描述
使用密钥签名Efi文件,对于SecurityBoot就时需要将Grub.efi Boot.efi 去签名 让BIOS去LoadImage 时通过校验

sbsign --key db.key --cert db.crt --output grubx64sign.efi.signed grub64.efi
apt-get install sbsigntool
在这里插入图片描述

导入证书后, Sign过的efi 才能运行 否则会返回无权限。
当不添加DB 时去加载签名过的EFI 会显示 Image被签名但是不在DB中 。 PK是可以去校验签名 但是DB时我们的签名白名单支持库。
在这里插入图片描述

BIOS_104">BIOS实现

BIOS中加载EFI File会使用gbs->LoadImage去加载镜像,调用的的函数原型是 CoreLoadImageCommon
该函数就包含了安全校验`
Security2StubAuthenticate -->Defer3rdPartyImageLoad
在这里插入图片描述
在这里插入图片描述
使用证书签名文件后,可以看到会在EFI文件后面加一段密钥相关的二进制内容 里面就包含了使用的证书公钥等一些信息

在这里插入图片描述
BIOS中校验File中是否由DB/DBX的Signature,主要使用IsSignatureFoundInDatabase 去检查。

///
/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
/// for the authorized signature database.
///
#define EFI_IMAGE_SECURITY_DATABASE  L"db"
///
/// Varialbe name with guid EFI_IMAGE_SECURITY_DATABASE_GUID
/// for the forbidden signature database.
///
#define EFI_IMAGE_SECURITY_DATABASE1  L"dbx"EFI_STATUS
IsSignatureFoundInDatabase (IN  CHAR16    *VariableName,IN  UINT8     *Signature,IN  EFI_GUID  *CertType,IN  UINTN     SignatureSize,OUT BOOLEAN   *IsFound)
{EFI_STATUS          Status;EFI_SIGNATURE_LIST  *CertList;EFI_SIGNATURE_DATA  *Cert;UINTN               DataSize;UINT8               *Data;UINTN               Index;UINTN               CertCount;//// Read signature database variable.//*IsFound = FALSE;Data     = NULL;DataSize = 0;Status   = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);if (Status != EFI_BUFFER_TOO_SMALL) {if (Status == EFI_NOT_FOUND) {//// No database, no need to search.//Status = EFI_SUCCESS;}return Status;}Data = (UINT8 *)AllocateZeroPool (DataSize);if (Data == NULL) {return EFI_OUT_OF_RESOURCES;}Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data);if (EFI_ERROR (Status)) {goto Done;}//// Enumerate all signature data in SigDB to check if signature exists for executable.//CertList = (EFI_SIGNATURE_LIST *)Data;while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;Cert      = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);if ((CertList->SignatureSize == sizeof (EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid (&CertList->SignatureType, CertType))) {for (Index = 0; Index < CertCount; Index++) {if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) {//// Find the signature in database.//*IsFound = TRUE;//// Entries in UEFI_IMAGE_SECURITY_DATABASE that are used to validate image should be measured//if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) {SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);}break;}Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);}if (*IsFound) {break;}}DataSize -= CertList->SignatureListSize;CertList  = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);}
Done:if (Data != NULL) {FreePool (Data);}return Status;
}
  1. 首先,函数会尝试从变量中读取签名数据库的数据。
  2. 如果成功读取到数据,函数会遍历签名列表,逐个比较签名数据,查找是否存在与给定签名匹配的条目。
  3. 如果找到匹配的签名,函数会将 IsFound 设置为 TRUE,表示找到了该签名。
  4. 如果在 EFI_IMAGE_SECURITY_DATABASE 中找到了签名,还会调用 SecureBootHook 函数来处理安全启动相关的操作。
    主要是将变量度量信息存入到TPM PCR中
SECUREBOOT_CONFIG_PRIVATE_DATA         mSecureBootConfigPrivateDateTemplate = {SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE,{SecureBootExtractConfig,SecureBootRouteConfig,SecureBootCallback}
};HiiHandle = HiiAddPackages (&gSecureBootConfigFormSetGuid,DriverHandle,SecureBootConfigDxeStrings,SecureBootConfigBin,NULL);

Vfr中都使用Label 在C中动态更新页面:
多个Lable 都在C中去动态更新
label FORMID_ENROLL_PK_FORM;
label LABEL_END;

label FORMID_ENROLL_KEK_FORM;
label LABEL_END;

label SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
label LABEL_END;

label SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
label LABEL_END;
label FORMID_ENROLL_PK_FORM;
label LABEL_END;

小结

Security Boot 就是一层对于LoadImage file 去进行签名验签的过程,来保证加载的系统是安全
详细信息都可以参考EDKII 的源码


http://www.ppmy.cn/devtools/100364.html

相关文章

Prometheus Alertmanager告警之邮件、钉钉群、企业微信群机器人报警

文章目录 一、部署alertmanager相关组件1.alertmanager-config2.alertmanager-message-tmpl3.alertmanager 二、调试邮件告警三、钉钉群/企业微信群 报警3.1添加钉钉群机器人3.2添加企业微信群机器人3.3部署alertmanager-webhook-adaptermessage-tmplalertmanager-webhook-adap…

viewBinding的使用(android studio)

引入 在开发安卓软件的时候&#xff0c;我们会大量的使用点击事件。通常情况下&#xff0c;我们是这样做的&#xff1a;将在xml文件里把目标组件添加id属性&#xff0c;如下&#xff1a; 然后在activity里面通过findViewById(R.id.back) 得到一个对象&#xff0c;通过对象调用…

【FPGA】HDMI参数信息汇总

文章列举已知大部分个人电脑屏幕尺寸信息&#xff0c;主要包括720p 1080p 2k 1440p 4k 5k以及8k屏幕。屏幕水平一行包括同步脉冲、后沿间隔、活跃像素、前沿间隔&#xff1b;屏幕垂直包括同步脉冲、后沿间隔、活跃行数、前沿间隔。 1. 720p (1280x720) 水平总像素 (HSYNC): 16…

MongoDB 创建数据库

MongoDB 创建数据库 MongoDB 是一种流行的 NoSQL 数据库&#xff0c;以其灵活的数据模型和强大的查询语言而闻名。在 MongoDB 中&#xff0c;创建数据库是一个简单的过程&#xff0c;可以通过 MongoDB 的命令行工具 mongo 或各种编程语言的 MongoDB 驱动程序来完成。本文将详细…

python 爬虫,东方网 上海新闻, 简单数据分析

起因: 本来想去市区玩玩&#xff0c;结果搜到一些相关的新闻&#xff0c;所以就想爬取新闻网站… 1. 爬虫部分 import os import csv import time import requests""" # home: https://sh.eastday.com/ # 1. 标题, url&#xff0c; 来源&#xff0c;时间 &qu…

输入与输出(12)

在 C 语言中&#xff0c;标准输入输出库&#xff08;stdio.h&#xff09;是用来处理输入和输出操作的主要工具。这个库提供了一系列功能强大的函数来读写各种数据类型&#xff0c;这对任何C程序都是至关重要的。下面是对 C 中输入和输出功能的更详细解释。 1.stdio.h 库 通过包…

CST软件仿真案例:圆极化平板天线仿真01

在接下来的几期中我们介绍一款圆极化Patch天线的仿真实例。读者可以完整的了解到怎么用CST微波工作室&#xff0c;完成对一款天线建模、设置到仿真分析的完整过程。 本案例最终完成的圆极化平板天线 本案例分为几期介绍&#xff0c;第一期先完成一个简单的平板天线的仿真工作流…

MySQL中的事务

一、事务是什么??? 事务&#xff08;Transaction&#xff09;&#xff0c;就是将一组SQL语句放在同一批次内去执行&#xff0c;如果一个SQL语句出错&#xff0c;则该批次内 的所有SQL都将被取消执行。 二、事务的特性 原子性&#xff1a;意味着数据库中的事务执行是作为原…

摄像头实时检查程序,插入设备,自动显示画面,支持多个摄像头,支持拍照,照片放大缩小

支持的特性 插入摄像头设备后&#xff0c;无需手动选择&#xff0c;自动显示摄像头画面&#xff0c;需要预先授权支持多个摄像头切换显示多个摄像头时支持 默认显示特定名称的摄像头支持拍照支持照片放大&#xff0c;缩小 显示效果 完整代码 <!DOCTYPE html> <html…

高效运维网络设备(有线与无线)和安全设备:推荐监控易

随着企业网络环境的日益复杂&#xff0c;运维团队面临着前所未有的挑战。为了确保网络的稳定运行和数据的安全&#xff0c;制定一套高效、可行的运维管理解决方案显得尤为重要。本文将重点探讨网络设备&#xff08;有线与无线&#xff09;和安全设备的运维策略&#xff0c;并推…

jvm监控工具一览

下面是对 BTrace、JAD、JMAP、JSTAT、JSTACK、JINFO 以及 MARK 工具的比较表&#xff1a; 工具/属性功能适用场景使用难度是否侵入式是否需要重启 JVMBTrace动态跟踪和监控 Java 应用程序性能分析、故障排查、日志收集、安全监控中等无侵入式否JAD反编译 Java 字节码文件&…

uni-app 如何开发多平台小程序

Uni-app 是一个使用 Vue.js 语法开发跨平台应用的前端框架&#xff0c;可以一次性编写代码并发布到多个平台&#xff0c;包括小程序&#xff08;如微信小程序、支付宝小程序、百度小程序等&#xff09;、H5、App&#xff08;iOS 和 Android&#xff09;等。以下是使用 uni-app …

C3-80螺栓介绍及其特性

C3-80 螺栓作为马氏体不锈钢高强度紧固件的一员&#xff0c;在工程应用中扮演着重要角色。它不仅具有较高的强度&#xff0c;还拥有良好的耐腐蚀性能&#xff0c;适用于多种恶劣环境下的工业应用。 C3-80螺栓概述 C3-80螺栓是一种马氏体不锈钢材质的高强度紧固件&#xff0c;其…

接口如何定义

接口设计完成之后&#xff0c;需要出接口文档。根据要求可以出word类型、excel类型都可以&#xff1b;如果没有特殊要求&#xff0c;使用swagger生成接口文档较为方便。 根据接口设计的内容编写controller方法&#xff0c;最后通过swagger生成接口文档。 1. 编写controller方…

动态规划-删除并获取点数

题目描述 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1 和 nums[i] 1 的元素。 开始你拥有 0 个点数。返回你能通…

组合逻辑环(Combinational Logic Loop)错误学习

组合逻辑电路 组合逻辑电路是数字电子学中一类基本的电路类型&#xff0c;它由一系列逻辑门组成&#xff0c;用于实现特定的逻辑功能。与时序逻辑电路不同&#xff0c;组合逻辑电路的输出完全取决于当前的输入信号&#xff0c;而不受之前输入的影响。换句话说&#xff0c;组合…

【Nature】在科研中应用ChatGPT:如何与数据对话

随着人工智能技术的迅猛发展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;正逐渐成为科研领域的一种创新工具。这些模型通过自然语言处理技术&#xff0c;使得研究人员能够以直观的方式与数据进行交互&#xff0c;从而简化了数据分析和解释的过程。在《自然》杂志2024…

开发团队如何应对突发的技术故障和危机?

开发团队如何应对突发的技术故障和危机&#xff1f; 在数字化时代&#xff0c;软件服务的稳定性至关重要。然而&#xff0c;即便是像网易云音乐这样的大型平台&#xff0c;也难免遇到突发的技术故障。8月19日下午&#xff0c;网易云音乐疑似出现服务器故障&#xff0c;网页端出…

数据结构之LRUCache

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 LRU Cache的概念 LRU Cache的实现 模拟实现LRU Cache 相关练习 LRU Cache的概念 LRU是…

如何把huggingface格式的whisper模型转为openai格式

1. 摘要 openai目前提供的模型有tiny&#xff0c;tiny.en&#xff0c;base&#xff0c;base.en&#xff0c;small&#xff0c;small.en&#xff0c;medium&#xff0c;medium.en&#xff0c;large-v1&#xff0c;large-v2&#xff0c;large-v3共11种&#xff0c;其中en结尾的是…