diff --git "a/sig/Industrialization/media/IPMI\351\200\232\344\277\241\346\240\274\345\274\217.jpg" "b/sig/Industrialization/media/IPMI\351\200\232\344\277\241\346\240\274\345\274\217.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..faeb2cdab4f0cbeda99b0b31f575ec6ceeae00b5 Binary files /dev/null and "b/sig/Industrialization/media/IPMI\351\200\232\344\277\241\346\240\274\345\274\217.jpg" differ diff --git "a/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204.png" "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204.png" new file mode 100644 index 0000000000000000000000000000000000000000..d136c0ad680253ca606eb860172494781724f944 Binary files /dev/null and "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204.png" differ diff --git "a/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\345\220\257\345\212\250\346\227\266.png" "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\345\220\257\345\212\250\346\227\266.png" new file mode 100644 index 0000000000000000000000000000000000000000..c9fc2a0d152d37d98b343684890977fde56dd76c Binary files /dev/null and "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\345\220\257\345\212\250\346\227\266.png" differ diff --git "a/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\350\277\220\350\241\214\346\227\266.png" "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\350\277\220\350\241\214\346\227\266.png" new file mode 100644 index 0000000000000000000000000000000000000000..930d3f0dac1729c28680d6230a6ee462453dafcd Binary files /dev/null and "b/sig/Industrialization/media/\347\263\273\347\273\237\346\236\266\346\236\204\350\277\220\350\241\214\346\227\266.png" differ diff --git "a/sig/Industrialization/media/\350\212\202\347\202\271\351\200\232\344\277\241.png" "b/sig/Industrialization/media/\350\212\202\347\202\271\351\200\232\344\277\241.png" new file mode 100644 index 0000000000000000000000000000000000000000..505d511e0cd4a88fa0274e6e3f31df4231996e7e Binary files /dev/null and "b/sig/Industrialization/media/\350\212\202\347\202\271\351\200\232\344\277\241.png" differ diff --git "a/sig/Industrialization/\345\237\272\344\272\216BMC\346\212\200\346\234\257\347\232\204\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237\345\256\211\345\205\250\345\217\257\344\277\241\346\226\271\346\241\210\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260.md" "b/sig/Industrialization/\345\237\272\344\272\216BMC\346\212\200\346\234\257\347\232\204\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237\345\256\211\345\205\250\345\217\257\344\277\241\346\226\271\346\241\210\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..c82299af55e67485745e5308b29f4ad443f6f5c8 --- /dev/null +++ "b/sig/Industrialization/\345\237\272\344\272\216BMC\346\212\200\346\234\257\347\232\204\350\256\241\347\256\227\346\234\272\347\263\273\347\273\237\345\256\211\345\205\250\345\217\257\344\277\241\346\226\271\346\241\210\350\256\276\350\256\241\344\270\216\345\256\236\347\216\260.md" @@ -0,0 +1,401 @@ +# 基于BMC技术的计算机系统安全可信方案设计与实现(设计文档) + +## 概述 +本作品用 BMC 板卡中的 TPCM 作为信任锚点,构建高效、灵活的计算机系统安全启动方案。 +这一方案与传统的可信计算方案存在关键不同:传统的可信计算技术依赖于主板上内置的 TPM 硬件模块,而本作品的信任根位于 BMC 板卡的可信执行环境中,具有更好的隔离性。 +并且,本作品将可信计算中关键的度量操作转移到 BMC 板卡上来执行,进一步提高度量操作的安全性。 +本作品支持关键组件度量、节点间通信等功能。 +为了验证本作品的设计,团队成员在X86主机、飞腾 D2000 桌面机、飞腾 BMC 载板以及虚拟AST2500 BMC上实现了原型系统。 + +## 软件架构 +![系统架构](./media/系统架构.png "系统架构") + +本作品所设计的安全系统由两类节点组成:一类是左侧承担实际工作负载的计算节点,一类是右侧负责管理工作的 BMC 节点。 +左侧计算节点中运行业务应用程序。同时,为了保证安全,计算节点也运行着 TPCM 度量程序、TPCM 软件栈、TPCM 驱动等关键组件。 +右侧 BMC 节点运行着 BMC 应用、TCM 等管理程序。 +右侧 BMC 节点会先于左侧启动,并负责管理与检测左侧计算节点行为。 +本次比赛所提供的 BMC 板卡搭载了 ARM TrustZone 安全扩展,将 BMC 节点上的系统分为普通世界与安全世界。 +普通世界中运行 OurBMC,为服务器运维提供基本接口。 +安全世界运行安全敏感的程序,如密钥管理、加密操作、身份认证等。 +计算节点和 BMC 节点可以通过专用硬件接口或者网络来实现通信。 + +## 系统安全启动 +![系统架构启动时](./media/系统架构启动时.png "系统架构启动时") + +如上图所示,系统启动过程中,计算节点所运行的软件栈是固件程序。 +在启动计算节点前,BMC 节点会通过 SPI 总线读取 BIOS 镜像来核验安全性。 +BMC 节点将镜像二进制交给 TSB,TSB 请求 TPCM 来验证度量值。 +BIOS 的参考度量值在第一次上传时就已经被 TSB 程序度量,度量值被扩展到 TPCM 中。 +验证通过后,BIOS 被认为是安全可靠的,加载到内存中开始运行。 +UEFI BIOS的生命周期被分为七个阶段:PEI 阶段以及之后的阶段会发送 TPCM 命令来进行配置、度量值存储。 +度量值存储在 TPCM 的 PCR 寄存器中,代表着系统自上电到运行过程的每一步的状态,可以用于确保信任链的完整性。 +当 UEFI BIOS 进入到 TSL 阶段,两个关键的UEFI程序会先后执行:Shim 和 Grub。 +它们三个会相继验证下一组件的完整性与合法性。 +具体而言,UEFI BIOS 加载 Shim.efi 程序,加载过程会逐步调用 DxeImageVerificationHandler 来进行实际的验签操作。 +Shim.efi 验证通过后,它会调用 verify_buffer 函数来验证 Grub.efi。 +Grub 被加载后,它也会调用 Shim 的 verify_buffer 函数来验证将要加载的内核。 + +## 应用动态度量 +![系统架构运行时](./media/系统架构运行时.png "系统架构运行时") + +如上图所示,系统启动过程中,计算节点所运行的软件栈是 TPCM 软件栈。 +对于有动态度量需求的程序,它在启动时会被 TSB Agent 劫持。 +该程序的二进制会被发送至 BMC 侧 TSB,进行度量与验证。 +验证通过后,BMC 会发送信号至计算节点,应用程序可以继续执行。 + +## 节点间通信 + +| 被度量组件 | 度量者 | 验证者 | +| -------- | -------- | -------- | +| BIOS | TSB | TPCM | +| Shim | BIOS | BIOS | +| Grub | Shim | Shim | +| 内核 | Grub | Grub | +| 应用 | TSB | TPCM | + + +![节点通信](./media/节点通信.png "节点通信") + + +根据上表所示,系统可信启动和应用动态度量过程中需要进行一系列的度量和验证工作。 +其中,BIOS是系统最早的运行组件,它需要由 BMC 进行检测。 +而对于内核来说,由于体积过大,不适用于发送至 BMC,需要通过 BIOS-Shim-Grub-Kernel的顺序来逐步建立信任。 +应用可以配合 TSB-Agent 来实现动态度量:BMC 侧度量和验证。 + + +![IPMI通信格式](./media/IPMI通信格式.jpg "IPMI通信格式") + +为了支持前文中 BIOS 的起始度量、系统的安全启动和应用的动态度量,本作品设计了相应的 IPMI 命令来传输 BIOS/应用二进制、TPM 命令。 +如上图所示,TPM命令/TPM响应/二进制包的发送采用朴素的通信算法: +- 当计算节点向 BMC 侧发送命令时,它会对 TPM 命令包进行分块。 +然后,将总包数、包索引、本次包的CRC检验值作为头部,将本次发送的包填充至Payload中,从而构建一个数据包。 +包需要按序依次发送,序列顺序不对会导致发送失败。 +当包索引与总包数相差为 1 时,表示发送任务已经结束。 +- 当计算节点向 BMC 侧发送二进制程序时,整体逻辑和 TPM 命令相似。 +但是,在发送任务完成后,需要额外追加一个数据包。 +此时,包索引等于总包数,BMC 侧的响应信息表示 BIOS 或应用程序是否通过验证。 +- 当计算节点向 BMC 侧发送 TPM 命令后,还需要从 BMC 侧取回响应。 +它的头部成员只有一个,指明向 BMC 侧请求的字节数。 +但是,计算节点不能提前预知本次 TPM 命令的执行情况,无法确定 TPM 响应的程序。 +因此,它需要先发送一个探测包用于获取 TPM 响应头部,来确认本次响应的总长度。 +BMC 侧会将本次传回计算节点的信息按照探测包中请求字节数分块,响应中包含总包数、包索引、本次包的CRC检验值作为头部,将本次发送的包填充至Payload中,从而构建一个响应信息。 +计算节点请求过程中不能随意改变请求字节长度,不然会导致响应失败。 + + +# 基于BMC技术的计算机系统安全可信方案设计与实现(使用文档) + +源码请参考:https://atomgit.com/bmc2024/000004-bmc_users (待开放) + +## 硬件设置 + +请使用飞腾BMC载板作为BMC硬件设备,X86作为计算节点设备,硬件信息参考如下: +BMC硬件设备CPU型号:Phytium E2000 +计算节点设备CPU型号:支持虚拟化的X86主机,且在BIOS中设置了虚拟化选项 +计算节点设置:开启硬件辅助虚拟化,安装KVM驱动 +烧录器:硕飞SP20B +烧录底座:硕飞SF-QFN8-8X6A + +## 1. 安装Ubuntu操作系统 +请于计算节点安装Ubuntu 20.04 系统。 +## 2. 检查KVM使能状态 +```sh +$ sudo kvm-ok +INFO: /dev/kvm exists +KVM acceleration can be used +``` + +# 背景信息 +本作品所设计的安全系统由两类节点组成:一类是左侧承担实际工作负载的计算节点,一类是右侧负责管理工作的 BMC 节点。 +左侧计算节点中运行业务应用程序。同时,为了保证安全,计算节点也运行着 TPCM 度量程序、TPCM 软件栈、TPCM 驱动等关键组件。 +右侧 BMC 节点运行着 BMC 应用、TCM 等管理程序。 +右侧 BMC 节点会先于左侧启动,并负责管理与检测左侧计算节点行为。 +注意:虽然,我们在计算节点使用了swtpm,但是它的作用只是保证系统安全运行,同时建立信道方便转发。 +**可信根依旧存储在BMC的swtpm模拟器中** + +# 步骤一:计算节点安装 Software TPM +## 1.安装编译所需软件 +```sh +apt update -y && \ + apt install -y dh-autoreconf libssl-dev libtasn1-6-dev pkg-config \ + net-tools iproute2 libjson-glib-dev libgnutls28-dev expect \ + gawk socat make +``` +## 2.安装libtpms +```sh +git clone https://github.com/stefanberger/libtpmsq'e'mu +cd libtpms +./autogen.sh --with-openssl --prefix=/usr --with-tpm2 +make -j +make install +``` +## 3.安装swtpm +```sh +git clone https://github.com/stefanberger/swtpm +cd swtpm +./autogen.sh --with-openssl --prefix=/usr --without-seccomp --with-tpm2 +make -j +make install +``` + +# 步骤二:计算节点启动虚拟机 +## 1.下载并安装QEMU +```sh +wget https://download.qemu.org/qemu-8.0.3.tar.xz +tar xvJf qemu-8.0.3.tar.xz +cd qemu-8.0.3 +./configure --prefix=/usr --enable-debug --target-list=x86_64-softmmu --enable-kvm || handle_error "submoudle qemu not benn downloaded" +make -j +make install +``` + +## 2.下载并安装edk2 +```sh +git clone https://github.com/tianocore/edk2.git +cd edk2 +git submodule update --init +make -C BaseTools +source edksetup.sh +build -a X64 -p OvmfPkg/OvmfPkgX64.dsc -t GCC5 -D TPM2_ENABLE=TRUE -D SECURE_BOOT_ENABLE +``` + +## 3.下载虚拟机镜像 +```sh +# xxx表示具体日期 +wget https://cloud-images.ubuntu.com/focal/xxx/focal-server-cloudimg-amd64.img +``` + +## 4.启动虚拟机 +```sh +mkdir /tmp/mytpm +swtpm socket --tpmstate dir=/tmp/mytpm \ + --ctrl type=unixio,path=/tmp/mytpm/swtpm-sock \ + --log level=20 --tpm2 +qemu-system-x86_64 -enable-kvm -m 2048 -nographic \ + -netdev user,id=vmnic -net user,hostfwd=tcp::10021-:22 \ + -net nic,model=e1000 \ + -device e1000,netdev=vmnic,romfile= \ + -hda focal-server-cloudimg-amd64.img \ + -bios OVMF.fd \ + -chardev socket,id=chrtpm,path=/tmp/mytpm/swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-crb,tpmdev=tpm0 +``` + +# 步骤三:虚拟机内安装tpm软件栈 +## 0.按照前文步骤启动虚拟机 +## 1.安装依赖软件 +```sh +apt update && apt install autoconf-archive libcmocka0 libcmocka-dev procps iproute2 build-essential git pkg-config gcc libtool automake libssl-dev uthash-dev autoconf doxygen libjson-c-dev libini-config-dev libcurl4-openssl-dev libltdl-dev expect python-yaml libglib2.0-dev dbus +``` +## 2.安装tpm2-tss +``` sh +git clone https://github.com/tpm2-software/tpm2-tss.git +cd tpm2-tss +./bootstrap +./configure --enable-tcti-device --disable-tcti-mssim --disable-tcti-swtpm +make -j +make install +``` + +## 3. 安装tpm2-abrmd +``` sh +git clone https://github.com/tpm2-software/tpm2-abrmd.git +cd tpm2-abrmd +useradd --system --user-group tss +./bootstrap +./configure --datarootdir=/usr/share +make -j +make install +``` + +## 4.安装tpm2-tools + +``` sh +git clone https://github.com/tpm2-software/tpm2-tools.git +cd tpm2-tools +./bootstrap +./configure +make -j +make install +``` + +# 步骤四:虚拟机配置安全启动 + +先在虚拟机中重新编译 shim,然后将shim、grub、vmlinux 都拷贝出来。 + +## 1.生成密钥 +```sh +openssl genrsa -out rsa.key 4096 +openssl req -new -key rsa.key -out rsa.csr -subj '/C=CN/CN=OpenKylinOS' +openssl x509 -req -days 3650 -in rsa.csr -signkey rsa.key -out rsa.crt +openssl x509 -in rsa.crt -out rsa.der -outform DER +``` + +## 2.将生成的密钥和证书导入NSS数据库 +```sh +mkdir certdb +certutil -N -d certdb +certutil -A -n rsa -d certdb -t CT,CT,CT -i rsa.crt +openssl pkcs12 -export -out rsa.p12 -inkey rsa.key -in rsa.crt +pk12util -d certdb -i rsa.p12 +``` + +## 3.修改并编译shim +```sh +apt source shim +cd shim-15+1533136590.3beb971/debian +# 更改rules文件 +# cert= +make -j +make install # 自动安装 shimx64.efi.signed +``` + +## 4.签名grub +```sh +pesign -n certdb -c rsa -s -i /boot/efi/EFI/ubuntu/grubx64.efi -o grubx64.efi.signed --pinfile=pinfile +cp grubx64.efi.signed /boot/efi/EFI/ubuntu/grubx64.efi +``` + +## 5.签名内核 +```sh +pesign -n certdb -c rsa -s -i /boot/vmlinuz-$(uname -r) -o vmlinuz-$(uname -r).signed --pinfile=pinfile +cp vmlinuz-$(uname -r).signed /boot/vmlinuz-$(uname -r) +``` + +## 6.BIOS 配置 +```sh +qemu-img create -f qcow2 rsa.qcow2 10M +# 将rsa.crt证书文件从虚机中拷贝出来,放置在新创建的虚拟卷中 +# 之后的虚机启动命令变成下文所示: +qemu-system-x86_64 -enable-kvm -m 2048 -nographic \ + -netdev user,id=vmnic -net user,hostfwd=tcp::10021-:22 \ + -net nic,model=e1000 \ + -device e1000,netdev=vmnic,romfile= \ + -hda focal-server-cloudimg-amd64.img \ + -hdb rsa.qcow2 \ + -bios OVMF.fd \ + -chardev socket,id=chrtpm,path=/tmp/mytpm/swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-crb,tpmdev=tpm0 + +# 虚拟机启动过程进入BIOS设置界面进行如下设置: +# Setup->Device Manager->Secure Boot Configuration,Standard Mode改成Custom Mode +# Setup->Device Manager->Secure Boot Configuration->Custom Secure Boot Options-> +# PK和DB相关选项->导入签名->进入rsa.qcow2目录->选择rsa.der->保存并退出 +``` + +# 步骤五:虚拟机更新内核 +注意:以下步骤在虚拟机内部运行! +## 1.下载内核 +```sh +sudo apt-get source linux-image-unsigned-$(uname -r) +``` +## 2.应用patch +```sh +cd linux +git apply linux/001-tpm-driver-ipmi-support.patch # 或者参照 patch 拷贝对应文件,283 a 75 d +``` + +## 3.编译内核 +```sh +make -j +make bindeb-pkg -j +``` +## 4.更新内核 +```sh +dpkg -i linux-image-xxx.deb +dpkg -i linux-headers-xxx.deb +``` + +# 步骤六:虚拟机固件更新 + +## 1.应用patch +```sh +# 注:该步骤发生在Host环境中 +cd edk2 +git apply edk2/001-tpm-driver-ipmi-support.patch # 或者参照 patch 拷贝对应文件,342 a 101 d +``` +## 2.重新编译 + + +# 步骤七:更新 BMC +参考资料:OurBMC仓库之玩转 OurBMC 第3期:OpenBMC的构建与开发流程.md +## 1.下载OurBMC仓库 +```sh +git clone https://gitee.com/ourbmc/openbmc.git +``` + +## 2.应用patch +```sh +cd openbmc +# 基于phytium-ipmi-oem进行二次开发 +# 请自行将对应文件拷贝至文件夹 +``` + +## 3.编译 +```sh +. setup evb-pe2201 +bitbake obmc-phosphor-image +# 所生成的BMC镜像位于:openbmc/build/evb-pe2201/tmp/deploy/images/evb-pe2201/obmc-phosphor-image-evb-pe2201.static.mtd +``` +## 4. 烧录/拷贝 +在载板使用过程中,出现多次镜像失效问题,建议采用直接拷贝的方式,更加稳定。 +烧录过程可以参考赛题参考资料(11-BMC调测载板指导文档)将BMC固件烧录至BMC载板。 + +# 步骤八:连接 BMC +## 1.将D2000机器的0号网口与BMC载板的0号网口连接 +## 2.设置IP +```sh +ip addr add 10.31.34.201/24 dev enp4s0 +``` +## 3.ipmi通信测试 +```sh +ipmitool -C 17 -I lanplus -H 10.31.34.200 -U root -P 0penBmc mc info +``` + +# 步骤九:实验之更新 BIOS +## 1.QEMU模拟启动信号的传递 +```sh +# 由于BMC载板没有flash可以读取,flash相关功能被注释,增加了度量与调用tpm的功能。 +/usr/local/bios_flash.sh +``` + +## 2. 结果 +bios文件被度量,度量结果扩展至 PCR0 中。 + +# 步骤十:实验之可信启动 +## 1.QEMU模拟启动信号的传递 +```sh +# 由于BMC载板没有SPI总线可以直接获取镜像,本方案假设QEMU侧接收到了BMC读取BIOS的动作,由它来主动传输BIOS。 +qemu-system-x86_64 -enable-kvm -m 2048 -nographic \ + -netdev user,id=vmnic -net user,hostfwd=tcp::10021-:22 \ + -net nic,model=e1000 \ + -device e1000,netdev=vmnic,romfile= \ + -hda focal-server-cloudimg-amd64.img \ + -bios OVMF.fd \ + -chardev socket,id=chrtpm,path=/tmp/mytpm/swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-crb,tpmdev=tpm0 +``` + +## 2. 结果 +bios被传输到BMC完成度量与验证。 +验证通过后,BMC向QEMU发送一个允许启动信号,指示QEMU继续执行虚拟机 +执行过程中,TPM命令发送至BMC侧的swtpm中,swtpm将结果返回给虚拟机 + +# 步骤十一:实验之动态度量 +## 1.应用提前度量 +```sh +# 在BMC侧对将要执行的程序进行度量,度量结果存储在 PCR 中 +/usr/local/mesure-application.sh +``` + +## 2.应用动态度量 +```sh +# 写了一个随机数生成程序作为示例程序 +LD_PRELOAD=./tsb_agent.so ./example +``` + +## 3. 结果 +启动程序后,程序二进制会再次发送给BMC侧进行度量和验证。 +验证通过后,BMC向虚拟机发送一个允许启动信号,虚拟机可以继续执行程序。