当前位置: 首页 > news >正文

EDKII之安全启动详细介绍

文章目录

    • 安全启动简介
    • 安全启动流程介绍
    • 签名过程
    • 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实现

在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 的源码

相关文章:

EDKII之安全启动详细介绍

文章目录 安全启动简介安全启动流程介绍签名过程BIOS实现小结 安全启动简介 安全启动&#xff08;Secure Boot&#xff09;是一种计算机系统的安全功能&#xff0c;旨在确保系统启动过程中只能加载经过数字签名的受信任的操作系统和启动加载程序。通过使用安全启动&#xff0c…...

原生js上传图片

无样式上传图片 创建一个 FormData 对象&#xff1a;这个对象可以用于存储数据。 将文件添加到 FormData 对象&#xff1a;通过 append() 方法&#xff0c;将用户选择的文件添加到 formData 对象中。 使用 fetch 发送请求&#xff1a;使用 fetch API 或者其他方法将 FormDat…...

使用torch==2.5.1版本用的清华源遇到的坑

解决安装torch后,torch.cuda.is_available()结果为false的问题 清华源下载到的torch2.5.1版本的Lib\site-packages\torch\version.py 其中&#xff0c;清华源指的是&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorchhttps://mirrors.tuna.tsinghua.…...

泷羽Sec-星河飞雪-BurpSuite之解码、日志、对比模块基础使用

免责声明 学习视频来自 B 站up主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下代码、网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 泷羽sec官网&#xff1a;http…...

对拍详细使用方法

对拍的作用 对于我们在学校OJ&#xff0c;cf&#xff0c;牛客…各种只提供少量测试数据的题目&#xff0c;常常交上代码常常超时&#xff0c;能写出正确的暴力代码而题目要求的时间复杂度更低。然而这时你写出了能通过样例且时间复杂度更低的代码&#xff0c;但交上去就是错误…...

Python面向对象编程与模块化设计练习

需求&#xff1a; 编写一个BankAccount类&#xff0c;模拟银行账户功能&#xff1a; 属性&#xff1a;账户名、余额 方法&#xff1a;存款、取款、查询余额 使用模块将类和测试代码分离。 模块文件&#xff1a;bank_account.py 该模块包含 BankAccount 类。 class BankAccoun…...

Linux系统硬件老化测试脚本:自动化负载与监控

简介&#xff1a; 这篇文章介绍了一款用于Linux系统的自动化硬件老化测试脚本。该脚本能够通过对CPU、内存、硬盘和GPU进行高强度负载测试&#xff0c;持续运行设定的时长&#xff08;如1小时&#xff09;&#xff0c;以模拟长时间高负荷运行的环境&#xff0c;从而验证硬件的稳…...

搭建一个基于Web的文档管理系统,用于存储、共享和协作编辑文档

搭建一个基于Web的文档管理系统&#xff0c;用于存储、共享和协作编辑文档 本项目采用以下架构&#xff1a; NFS服务器: 负责存储文档资料。Web服务器: 负责提供文档访问和编辑功能。SELinux: 负责权限控制&#xff0c;确保文档安全。Git服务器: 负责存储文档版本历史&#x…...

排序学习整理(1)

1.排序的概念及运用 1.1概念 排序&#xff1a;所谓排序&#xff0c;就是使⼀串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作&#xff0c;以便更容易查找、组织或分析数据。 1.2运用 购物筛选排序 院校排名 1.3常见排序算法 2.实…...

《深入探究 Java 中的 boolean 类型》

在 Java 编程语言的世界里&#xff0c;boolean 类型虽然看似简单&#xff0c;却在程序的逻辑控制和决策中起着至关重要的作用。本文将带你深入了解 Java 中的 boolean 类型&#xff0c;从其基本概念、用法到实际应用场景&#xff0c;以及一些常见的注意事项。 一、boolean 类型…...

智享 AI 自动无人直播系统:打破地域与时间枷锁中小微企业的营销破局利器

中小微企业&#xff0c;在商业浪潮中恰似逐浪扁舟&#xff0c;常面临营销成本高、推广渠道窄、专业人才缺等 “暗礁”&#xff0c;而智享 AI 自动无人直播系统恰如精准导航的灯塔&#xff0c;助其破浪前行、突出重围。 成本维度&#xff0c;传统直播人力成本让中小微企业望而却…...

接口测试工具:reqable

背景 在众多接口测试工具中挑选出一个比较好用的接口测试工具。使用过很多工具&#xff0c;如Postman、Apifox、ApiPost等&#xff0c;基本上是同类产品&#xff0c;一般主要使用到的功能就是API接口和cURL&#xff0c;其他的功能目前还暂未使用到。 对比 性能方面&#xff…...

同时多平台git配置:GitHub和Gitee生成不同的SSH Key

文章目录 GitHub和Gitee生成不同的SSH Key步骤1&#xff1a;生成SSH Key步骤2&#xff1a;配置SSH配置文件步骤3&#xff1a;查看SSH公钥步骤4&#xff1a;将SSH公钥添加到GitHub和Gitee步骤5&#xff1a;测试SSH连接步骤6&#xff1a;添加remote远程库 GitHub和Gitee生成不同的…...

刷题计划day24 回溯(三)【复原 IP 地址】【子集】【子集 II】

⚡刷题计划day24 回溯&#xff08;三&#xff09;继续&#xff0c;回溯一共会有五个专题&#xff0c;敬请期待关注&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 题目一&#xff1a;复原 IP…...

从“找三角形”讲“等腰三角形”

【题目】 周长为11&#xff0c;且各边长均为整数的三角形有哪些&#xff1f; 【答案】 四种&#xff0c;边长分别为&#xff1a; 2 4 5 3 3 5 1 5 5 3 4 4 【解析】 讲解等腰三角形的概念时&#xff0c;传统方法一般向学生展示一个等腰三角形的实物模型&#xff0c;这…...

Java中的泛型方法和泛型类

在Java编程语言中&#xff0c;泛型&#xff08;Generics&#xff09;是一个强大的特性&#xff0c;它使得类、接口和方法能够灵活地操作各种数据类型&#xff0c;同时保持类型安全。泛型主要通过类型参数&#xff08;Type Parameters&#xff09;来实现&#xff0c;这些类型参数…...

springboot学习-spring-boot-data-jdbc分页/排序/多表查询的例子

上次使用的是JdbcTemplate实现的&#xff0c;是比较老的方式&#xff0c;重新用spring boot data jdbc和jdbc client 实现一遍。也比较一下这几种的编码差异。数据库方面JAVA给了太多选择&#xff0c;反而不好选了。 上次就试图直接用&#xff1a; public interface UserRepo…...

通信与网络基础

1.网络通信基本概念 通信&#xff1a;人、物通过某种介质和行为进行信息传递与交流 网络通信&#xff1a;终端设备之间通过计算机网络进行通信 两个终端通过网线传递文件 多个终端通过路由器传递文件 终端通过Internet下载文件 2.信息传递过程 图1-1 假定A计算机访问B的web…...

【3.存储系统】综合大题

【考点】存储系统综合大题 【2011年408真题】某计算机存储器按字节编址&#xff0c;虚拟(逻辑)地址空间大小为16 MB&#xff0c;主存(物理)地址空间大小为1 MB&#xff0c;页面大小为4 KB&#xff1b;Cache采用直接映射方式&#xff0c;共8行&#xff1b;主存与Cache之间交换的…...

【Linux】【字符设备驱动】深入解析

Linux字符设备驱动程序用于控制不支持随机访问的硬件设备&#xff0c;如串行端口、打印机、调制解调器等。这类设备通常以字符流的形式与用户空间程序进行交互。本节将深入探讨字符设备驱动的设计原理、实现细节及其与内核其他组件的交互。 1. 引言 字符设备驱动程序是Linux内…...

【JavaEE】多线程(2)

一、线程安全 1.1 线程安全的概念 线程是随机调度执行的&#xff0c;如果多线程环境下的程序运行的结果符合我们预期则说明线程安全&#xff0c;反之&#xff0c;如果遇到其他结果甚至引起了bug则说明线程不安全 1.2 经典例子与解释 下面举一个经典的线程不安全的例子&…...

mac下Gpt Chrome升级成GptBrowser书签和保存的密码恢复

cd /Users/自己的用户名/Library/Application\ Support/ 目录下有 GPT\ Chrome/ Google/ GptBrowser/ GPT\ Chrome 为原来的chrome浏览器的文件存储目录. GptBrowser 为升级后chrome浏览器存储目录 书签所在的文件 Bookmarks 登录账号Login 相关的文件 拷贝到GptBrow…...

使用Grafana K6来测测你的系统负载能力

背景 近期我们有个号称会有很高很高并发的系统要上线&#xff0c;为了测试一下自己开发的系统的负载能力&#xff0c;准备了点海克斯科技&#xff0c;来看看抗不抗的住。 之前笔者写过用Apache JMeter进行压力测试的文章&#xff08;传送门&#x1f449;&#xff1a;https://…...

【论文复现】基于BERT的语义分析实现

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ WRN: 宽度残差网络 概述语义分类文本分类情感分类 实现原理 核心逻辑pre_deal.pytrain.pytest_demo.py 实现方式&演示效果训练阶段测试阶…...

CTF-RE: STL逆向 [NewStarCTF 2023 公开赛道 STL] WP

多看看STL题就会了,很简单 int __fastcall main(int argc, const char **argv, const char **envp) {__int64 v3; // rbx__int64 v4; // raxchar v5; // bl_BYTE *v6; // rax_QWORD *v7; // rax__int64 v8; // rax__int64 v9; // raxint i; // [rsp0h] [rbp-250h]int j; // [r…...

实习冲刺第三十六天

46.全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#…...

【Zemax光学设计实训三】---激光缩束镜的设计优化

前言与目录 技术设计要求&#xff1a; 设计一个激光扩束镜&#xff0c;使用的波长为1064nm&#xff0c;输入光束直径为10mm&#xff0c;输出光束的直径为2mm&#xff0c;且输入光束和输出光束平行&#xff08;即平行光入射&#xff0c;平行光出射&#xff09;。要求只使用两片…...

TCP/IP协议簇自学笔记

摘抄于大学期间记录在QQ空间的一篇自学笔记&#xff0c;当前清理空间&#xff0c;本来想直接删除掉的&#xff0c;但是感觉有些舍不得&#xff0c;因此先搬移过来。 曾经&#xff0c;我只知道socket函数能进行网络间数据的通信&#xff0c;知道tcp/ip协议也是用来进行网络数据…...

Spring Boot教程之十一:获取Request 请求 和 Put请求

如何在 Spring Boot 中获取Request Body&#xff1f; Java 语言是所有编程语言中最流行的语言之一。使用 Java 编程语言有几个优点&#xff0c;无论是出于安全目的还是构建大型分发项目。使用 Java 的优点之一是 Java 试图借助类、继承、多态等概念将语言中的每个概念与现实世…...

计算机网络(二)

ip地址&#xff1a;11010010&#xff1a;01011110:00100100:00010100 子网掩码:11111111:11111111:11111111:11000000 and &#xff1a;11010010&#xff1a;01011110&#xff1a;00100100&#xff1a;00000000 210.94.36.0的下一站为R1 因为255为11111111 192为&#xff…...