资讯详情

资讯详情

coreboot Eltan Security 方案实战:基于 OEM Manifest 的无 ChromeOS 实测启动与验签启动

固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载本篇文章以 Documentation/vendorcode/eltan/security.md 为核心脉络结合 coreboot 仓库中src/vendorcode/eltan/security的完整实现代码讲解如何为不基于 ChromeOS、甚至可以没有 TPM的嵌入式系统搭建 measured boot度量启动与 verified boot验证启动双安全机制。读完本文你将掌握 Eltan 方案的整体架构、mb_log_list/*_verify_list[]的配置方法、RSA2048 密钥对的生成、oemmanifest.bin的哈希/签名制作流程以及通过cbfstool将签名清单写回 coreboot 固件的完整实战链路。一、方案背景为什么需要 Eltan Securitycoreboot 本身已经提供了基于 ChromeOS 的 verified bootsrc/security/vboot下的VBOOT选项但它的设计依赖 ChromeOS 的整套安全基础设施如 vboot 槽位管理、flash 布局、board 级支持等。对于普通嵌入式主板、工控板或非 ChromeOS 消费设备这套机制往往过于复杂且难以适配。Eltan Security 正是为这类场景设计的 vendorcode 安全方案它复用了3rdparty/vboot/firmware的哈希/验签 API对应 src/vendorcode/eltan/security/Makefile.mk 中select VBOOT_LIB的依赖关系因此不需要额外引入整棵 vboot 树Verified boot 可以在完全没有 TPM 的硬件上工作——它通过一张存储在 CBFS 中的 OEM manifestoemmanifest.bin来携带并校验各固件组件的哈希值Measured boot 则要求硬件上存在TPM2 设备用于把固件度量结果扩展到 PCR 并记录事件日志。两条链路既相互独立也可以组合使用mb_log_list[]负责“度量”仅 TPM 场景*_verify_list[]负责“验证”manifest 场景而 verify list 中的条目在 TPM 存在时还可以同时完成度量。在 src/vendorcode/eltan/security/verified_boot/Kconfig 中可以看到VENDORCODE_ELTAN_MBOOT与VENDORCODE_ELTAN_VBOOT都depends on !VBOOT即与 ChromeOS vboot 互斥。二、整体架构与两类启动链Eltan Security 的核心代码位于 src/vendorcode/eltan/security分为两个子目录mboot/——Measured boot 实现mboot.c、mboot.hverified_boot/——Verified boot 实现vboot_check.c、vboot_check.h。主开关是USE_VENDORCODE_ELTAN见 src/vendorcode/eltan/security/Kconfig开启后会暴露 Eltan Security Settings 菜单。构建系统只在这两个选项任一开启时才把mboot/verified_boot头文件目录加入CPPFLAGS_common。2.1 度量链Measured boot需要TPM2mb_log_list[]中的条目以及各*_verify_list[]中带 PCR 索引的条目会被测量并扩展进 PCR入口调用链为verified_boot_early_check()→mb_measure()→mb_entry()TPM 初始化/StartUp→mb_measure_log_start()→mb_crtm() 遍历mb_log_list[]测量失败时会调用invalidate_pcrs()将 PCR 0–7 用固定值扩展使可信状态“失效”避免攻击者利用半完成度量见 mboot.c 中mb_measure()与invalidate_pcrs()。2.2 验证链Verified boot不依赖 TPM依赖oemmanifest.bin中预置的哈希表在 bootblock、early romstage、postcar、ramstage、payload、option rom 各加载节点前按*_verify_list[]逐项比对 CBFS 文件/内存块的哈希与 manifest 中的哈希若VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST开启还会先用内置公钥验证 manifest 自身签名。2.3 挂钩时机验证动作通过 coreboot 的prog_locate_hook()注入到程序加载流程。prog_locate_hook的默认弱实现位于 src/lib/prog_loaders.c在 src/lib/cbfs.c、src/lib/rmodule.c、src/lib/selfboot.c 等加载路径中被调用。Eltan 在 vboot_check.c 中覆写它按阶段分发挂钩阶段触发条件执行的验证BootblockENV_BOOTBLOCKverified_boot_bootblock_check()先验 manifest 签名若开启再处理bootblock_verify_list[]Early romstageENV_RAMINIT且加载 REFCODE 或 POSTCAR 时首次verified_boot_early_check()先执行mb_measure()若开启 MBOOT再处理romstage_verify_list[]Postcar 前CONFIG(POSTCAR_STAGE)且加载 POSTCARprocess_verify_list(postcar_verify_list)Ramstage 前非 POSTCAR 时加载 RAMSTAGE / POSTCAR 阶段加载 RAMSTAGEprocess_verify_list(ramstage_verify_list)Payload 前ENV_RAMSTAGE且加载 PAYLOADprocess_verify_list(payload_verify_list)Option ROM 执行前通过verified_boot_should_run_oprom()钩子由 x86 option rom 加载逻辑调用process_oprom_list(oprom_verify_list, ...)按 vid:devid 匹配后验证option rom 的处理比较特殊它并不是简单地在 CBFS 中查文件而是解析 option ROM 的PCI_ROM_HDR签名与pci_data中的 vendor/device ID只有匹配oprom_verify_list[]中VERIFY_OPROM条目指定的viddev时才对 ROM 内容做哈希验证并允许其执行见 vboot_check.c。三、Measured boot无 ChromeOS 系统的 TPM2 度量方案3.1 开启方式在menuconfig中开启VENDORCODE_ELTAN_MBOOT位于 Eltan Security Settings → Measured Boot (mboot)见 src/vendorcode/eltan/security/mboot/Kconfig该选项默认关闭会select VBOOT_LIB引入 vboot 哈希库。同时还需在主板代码中定义mb_log_list[]度量清单可按需修改VENDORCODE_ELTAN_CRTM_VERSION_STRING默认 default CRTM version它会被拼进 CRTM 版本字符串。3.2 mb_log_list 度量清单mb_log_list[]是mboot_measure_item_t类型的数组结构定义见 mboot.htypedef struct { const char *cbfs_name; /* CBFS 中的文件名称 */ uint32_t cbfs_type; /* CBFS 文件类型如 CBFS_TYPE_RAW */ uint32_t pcr; /* 度量目标 PCR 编号 */ TCG_EVENTTYPE eventType; /* TCG 事件类型如 EV_NO_ACTION */ const char *event_msg; /* 事件描述写入事件日志 */ } mboot_measure_item_t;原文档要求mb_log_list[]中应只放不属于任一 verify list的条目bootblock_verify_list[]除外避免重复度量。允许的条目包括config——编译生成的.config配置快照revision——Git 版本信息文件cmos_layout.bin——CMOS 布局文件当 Verified boot 同时启用时还应加入oemmanifest.bin把 manifest 本身也纳入度量。参考实现见 src/mainboard/facebook/fbg1701/board_mboot.h它将revision、cmos_layout.bin度量到 PCR 0并在VENDORCODE_ELTAN_VBOOT开启时把oemmanifest.bin度量到 PCR 7。3.3 度量执行流程mb_measure()mboot.c的执行逻辑mb_entry(wake_from_s3)——调用tlcl_lib_init()初始化 TPM 驱动再根据是否从 S3 唤醒选择tlcl_startup()或tlcl_resume()mb_measure_log_start()——先通过tpm2_get_active_pcrs()确认 TPM 的 SHA256 PCR bank 已激活否则直接返回错误再执行mb_crtm()度量 CRTM 版本随后遍历mb_log_list[]逐个调用mb_measure_log_worker()任意一步失败即调用invalidate_pcrs()对 PCR 0–7 各扩展一个 Invalidate PCR 事件使启动链失效。mb_crtm()mboot.c度量的是由CONFIG_VENDORCODE_ELTAN_CRTM_VERSION_STRING、COREBOOT_VERSION、COREBOOT_EXTRA_VERSION、COREBOOT_BUILD拼接而成的版本字符串事件类型为EV_S_CRTM_VERSIONPCR 0在 Intel 平台上还会尝试读取 ME 固件哈希并以EV_S_CRTM_CONTENTS事件追加到 PCR 0。mb_crtm、mb_entry、mb_measure_log_start等都是__weak函数允许主板按需覆写fbg1701 就在 romstage.c 中覆写了mb_crtm。事件日志遵循 TCG 规范TCG_PCR_EVENT2_HDR含TPML_DIGEST_VALUES用于 TCG 2.0 格式日志同时保留了 TCG 1.2 的TCG_PCR_EVENT_HDR结构见 mboot.h。四、Verified boot无 TPM 也能做的完整性验证4.1 开启方式在menuconfig中开启VENDORCODE_ELTAN_VBOOT见 src/vendorcode/eltan/security/verified_boot/Kconfig需要满足定义各*_verify_list[]验证清单VENDORCODE_ELTAN_VBOOT_KEY_FILE指向用futility生成的公钥文件在固件镜像的RO 区域放置公钥在RW 区域放置oemmanifest.bin。4.2 verify list 与相关配置项核心数据结构是verify_item_tvboot_check.htypedef struct { verify_type type; /* VERIFY_TERMINATOR / VERIFY_FILE / VERIFY_BLOCK / VERIFY_OPROM */ const char *name; union { struct { const void *related_items; uint32_t cbfs_type; } file; struct { const void *start; uint32_t size; } block; struct { const void *related_items; uint32_t viddev; } oprom; } data; uint32_t hash_index; /* 对应 manifest.h 中的 HASH_IDX_XXX 索引 */ int32_t pcr; /* 度量目标 PCR-1 表示仅验证不度量 */ } verify_item_t;原文档定义了六个验证清单各有明确的执行时机清单验证时机说明bootblock_verify_list[]bootblock 内不会被度量bootblock 阶段 TPM 尚未初始化仅做哈希比对romstage_verify_list[]early romstage在verified_boot_early_check()中处理postcar_verify_list[]postcar 加载前一刻ramstage_verify_list[]ramstage 加载前一刻payload_verify_list[]payload 加载前一刻oprom_verify_list[]option ROM 执行前按 vid:devid 匹配每个条目都有一个related_items成员可以指向另一张子清单形成按运行时选择动态展开的验证集合。原文档的典型例子是payload_verify_list[]中的grub条目 →grub_additional_list[]包含 GRUB payload 运行时依赖的文件payload_verify_list[]中的seabios条目 →seabios_additional_list[]包含 SeaBIOS 依赖的文件。process_verify_list()vboot_check.c在验证完父条目后会递归处理related_items指向的子清单——这样被验证以及被度量的条目集合随运行时实际选中的 payload 而变而不是固定全集。fbg1701 的实现即把config、vbt.bin、logo.bmp、fallback/dsdt.aml放在ram_stage_additional_list[]中由ramstage_verify_list[]中的 RAMSTAGE 条目通过related_items引用见 src/mainboard/facebook/fbg1701/board_verified_boot.c。4.3 哈希索引与 manifest 顺序verify_item_t.hash_index引用的是主板 manifest 头文件中HASH_IDX_XXX宏定义的顺序索引哈希表必须按此顺序排列。参考 src/mainboard/facebook/fbg1701/manifest.h#define HASH_IDX_ROM_STAGE 0 #define HASH_IDX_RAM_STAGE 1 #define HASH_IDX_PAYLOAD 2 #define HASH_IDX_OPROM 3 #define HASH_IDX_FSP 4 #define HASH_IDX_MICROCODE 5 #define HASH_IDX_SPD0 6 #define HASH_IDX_LOGO 7 #define HASH_IDX_DSDT 8 #define HASH_IDX_POSTCAR_STAGE 9 #define HASH_IDX_PUBLICKEY 10 #define HASH_IDX_CONFIG 11 #define HASH_IDX_BOOTBLOCK 12 /* Should always be the last one */注意其中的注释Make sure the index matches the actual order in the manifest generated using the HashCb.cmd file即索引顺序必须与生成哈希表时使用的顺序严格一致。VENDORCODE_ELTAN_VBOOT_MANIFEST配置项默认mainboard/$(MAINBOARD_DIR)/manifest.h指定该头文件的位置。4.4 manifest 自校验与签名验证当VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST开启时bootblock 会先调用verified_boot_check_manifest()vboot_check.c做三层检查从 CBFS 映射vboot_public_key.bin校验其大小等于VENDORCODE_ELTAN_VBOOT_KEY_SIZE默认 552 字节的 RSA2048 vb1 公钥且位于VENDORCODE_ELTAN_VBOOT_KEY_LOCATION指定的固定地址防止公钥被替换校验oemmanifest.bin大小必须等于VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS × DIGEST_SIZE 2048/8即 N 个哈希 RSA2048 签名长度 256 字节构造vb2_kernel_preamble把 manifest 数据作为body_signature交给vb2api_verify_kernel_data()用 vboot 库验证 RSA 签名失败即die()。实测中发现 fbg1701 把公钥固定映射在0xFFFEA000、manifest 放在0xFFFE9000见 src/mainboard/facebook/fbg1701/Kconfig均处于 8MB 闪存的 RO/RW 规划区域内。公钥与 manifest 的固定地址是在构建时由 verified_boot/Makefile.mk 写入 CBFS 布局的oemmanifest.bin-position与vboot_public_key.bin-position分别取CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC和CONFIG_VENDORCODE_ELTAN_VBOOT_KEY_LOCATION类型均为raw。4.5 验证粒度与内存拷贝优化verified_boot_check_cbfsfile()vboot_check.c在验证前会做一次内存搬运优化当文件内容仍位于闪存映射区时start COREBOOT_CBFS_START优先拷贝到调用方传入的缓冲区或bootmem_allocate_buffer()分配的 RAM 中避免后续加载时对慢速闪存反复访问回调还通过出参*buffer/*filesize把文件内容交还给加载器实现验证即加载。VERIFIED_BOOT_COPY_BLOCK0x80000000作为cbfs_type的标志位指示该项需要拷贝fbg1701 的 PAYLOAD 条目就带上了该标志。五、密钥生成RSA2048 私钥与 vboot 公钥按原文档的完整命令流程# 1. 生成 RSA2048 私钥-F4 表示使用指数 65537 openssl genrsa -F4 -out private_key_file 2048 # 2. 用 vboot 的 futility 工具生成 vb1 格式公钥 futility --vb1 create private_key_file public_key_file_without_extensionfutility来自3rdparty/vboot输出公钥文件名不需要扩展名工具会生成name.vbpubk。公钥会被打进 coreboot 镜像仅用于 verified boot 的 manifest 验签。默认公钥文件路径配置为3rdparty/eltan/verified_boot/Keys/key.vbpubk可通过VENDORCODE_ELTAN_VBOOT_KEY_FILE覆盖该文件在构建时以vboot_public_key.bin名称加入 CBFS。六、启用配置速查表以下是 Kconfig 与 mboot/Kconfig 中与 Eltan 安全相关的全部配置项及默认值配置项类型/默认值说明USE_VENDORCODE_ELTANbool总开关进入 Eltan Security Settings 菜单VENDORCODE_ELTAN_MBOOTbool默认 n启用 measured boot依赖 TPM2VENDORCODE_ELTAN_CRTM_VERSION_STRINGstring默认 default CRTM versionCRTM 版本字符串VENDORCODE_ELTAN_VBOOTbool默认 n启用 verified bootVENDORCODE_ELTAN_VBOOT_SIGNED_MANIFESTbool默认 n对 manifest 签名并附签依赖 VBOOTVENDORCODE_ELTAN_VBOOT_USE_SHA512bool默认 n哈希算法切换为 SHA-512同时影响 manifest 摘要与整体 digestVENDORCODE_ELTAN_OEM_MANIFEST_LOChex默认 0xFFFFF840manifest 在镜像中的固定位置VENDORCODE_ELTAN_VBOOT_MANIFESTstring默认mainboard/$(MAINBOARD_DIR)/manifest.h定义HASH_IDX_XXX的头部文件VENDORCODE_ELTAN_OEM_MANIFEST_ITEMSint默认 13含 config 文件/ 12manifest 中哈希条目总数VENDORCODE_ELTAN_OEM_MANIFEST_ITEM_SIZEintSHA512 时 64否则 32每条哈希的字节数VENDORCODE_ELTAN_VBOOT_KEY_LOCATIONhex默认 0xFFFFF500公钥固定位置仅在签名 manifest 时使用VENDORCODE_ELTAN_VBOOT_KEY_FILEstring默认3rdparty/eltan/verified_boot/Keys/key.vbpubkfutility 生成的公钥文件VENDORCODE_ELTAN_VBOOT_KEY_SIZEint默认 552公钥大小用于加载时校验参考主板的完整配置可查看 src/mainboard/facebook/fbg1701/Kconfig它通过select USE_VENDORCODE_ELTAN启用该方案并覆写了 manifest 位置、签名开关与密钥位置。七、构建流程空 manifest 的生成与回填7.1 构建期自动生成空 manifest在 coreboot 构建期间构建系统会自动向镜像中添加一个空的oemmanifest.bin。见 verified_boot/Makefile.mk启用VENDORCODE_ELTAN_VBOOT时oemmanifest.bin作为 CBFS raw 文件加入并固定放置在CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC生成命令为dd if/dev/zero ...即全零填充签名模式VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFESTdd if/dev/zero of$ seek8 bsITEM_SIZE countITEMS——seek8为 RSA2048 签名预留 256 字节尾部空间非签名模式直接生成ITEMS × ITEM_SIZE字节的零文件。这个空文件只是占位符必须在启用 verified boot 时被真实签名清单替换否则哈希比对必然失败。7.2 哈希计算oemmanifest.bin包含 bootblock、romstage、postcar、ramstage、FSP 等各个二进制组件的哈希。总条目数必须等于VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS。对每个组件按原文档的标准流程# 1. 从 coreboot 镜像中提取组件二进制 cbfstool coreboot_file_name extract -n cbfs_name -f item_binary_file_name # 2. 计算 SHA-256 哈希二进制输出 openssl dgst -sha256 -binary -out hash_file_name item_binary_file_name当启用VENDORCODE_ELTAN_VBOOT_USE_SHA512时将-sha256替换为-sha512。所有哈希必须按HASH_IDX_XXX定义的顺序拼接成一个哈希二进制文件hash_binary。7.3 签名与合并当VENDORCODE_ELTAN_VBOOT_SIGNED_MANIFEST开启时manifest 需要签名# 1. 用私钥对哈希二进制签名 openssl dgst -sign private_key_file_name -sha256 -out signature_binary hash_binary # 2. 把签名追加到哈希之后得到最终的 hash_table.bin cat hash_binary signature_binary hash_table.bin最终文件大小应为VENDORCODE_ELTAN_OEM_MANIFEST_ITEMS × ITEM_SIZE 256RSA2048 签名与 4.4 节中verified_boot_check_manifest()的尺寸校验完全对应。7.4 回写固件镜像生成hash_table.bin后用cbfstool替换镜像中的空占位文件# 1. 移除旧的空 manifest cbfstool coreboot_file_name remove -n oemmanifest.bin # 2. 在固定位置加入真实清单raw 类型 cbfstool coreboot.bin add -f hash_table_file_name -n oemmanifest.bin -t raw \ -b CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC-b参数必须与VENDORCODE_ELTAN_OEM_MANIFEST_LOC完全一致——代码中通过cbfs_map(oemmanifest.bin, ...)映射后直接以CONFIG_VENDORCODE_ELTAN_OEM_MANIFEST_LOC作为常量地址访问其内容见 vboot_check.c因此位置错配会直接导致验证失败。7.5 镜像布局要求原文档强调两条硬性约束公钥必须位于 RO 区域——只有 RO 中的公钥才能保证受信根不被攻击者篡改oemmanifest.bin必须位于 RW 区域——这样每次固件更新只需更换 RW 中的清单即可同时更新镜像中的实际组件无需重写 RO。fbg1701 的 fmd 布局与RW_REGION_ONLY/RO_REGION_ONLY设置见 src/mainboard/facebook/fbg1701/Kconfig正是这一要求的工程落地。八、调试与排错原文档给出的调试手段是在 menuconfig 中开启 verbose console 输出。结合源码vboot_check.c与mboot.c中埋有大量可观测点可直接指导排错BIOS_SPEW级别各阶段的处理开始日志如 processing bootblock items、process related items、option rom can be startedBIOS_DEBUG级别每个条目的哈希比对日志——verified_boot_check_buffer()会通过hexdump同时打印实际计算出的 buffer hash与manifest 中记录的 hash二者不一致时一目了然vboot_check.cBIOS_ERR/BIOS_EMERG级别公钥缺失Public key not found!、公钥非法Illegal public key!、manifest 尺寸错误Incorrect manifest size!以及最终的die(HASH verification failed!)mboot 侧mb_measure()返回码、TPM StartUp 失败码、invalidate_pcrs()触发等均会打印mboot.c。一个实用的排查顺序是先确认oemmanifest.bin在镜像中的位置与大小正确cbfstool print查看再检查哈希表顺序与manifest.h中HASH_IDX_XXX一致最后核对公钥文件是否由同一私钥生成。九、参考实现facebook/fbg1701当前仓库中facebook/fbg1701是该方案最完整的参考实现建议对照阅读src/mainboard/facebook/fbg1701/board_mboot.h——mb_log_list[]定义src/mainboard/facebook/fbg1701/board_verified_boot.c——六个*_verify_list[]与related_items的完整写法src/mainboard/facebook/fbg1701/manifest.h——HASH_IDX_XXX索引约定src/mainboard/facebook/fbg1701/Kconfig——USE_VENDORCODE_ELTAN与各项覆盖默认值src/mainboard/facebook/fbg1701/romstage.c——mb_crtm()的主板级覆写示例。该主板的构建配置可见 configs/config.facebook_fbg1701.sbom。从源码结构看Eltan Security 的设计目标是让主板开发者以声明式列表的方式配置信任策略把要保护的文件、目标 PCR、哈希索引写进数组即可复杂的 TPM 交互与 vboot 验签细节全部封装在 vendorcode 内部——这也正是它区别于 ChromeOS vboot 的最大工程价值所在。赞分享固件嵌入式操作系统驱动开发【免费下载链接】corebootRead-only mirror of https://review.coreboot.org/coreboot.git. Synced every hour. We dont handle Pull Requests.项目地址https://gitcode.com/gh_mirrors/co/coreboot点击查看免费下载相关推荐coreboot Eltan 安全启动框架实战指南无 ChromeOS 环境下的 Measured Boot 与 Verified Boot 实现coreboot Eltan 安全启动框架实战指南无 ChromeOS 环境下的 Measured Boot 与 Verified Boot 实现 coreb固件嵌入式操作系统驱动开发coreboot 安全架构实战指南验证启动、度量启动、Intel TXT 与内存清零coreboot 安全架构实战指南验证启动、度量启动、Intel TXT 与内存清零 导读coreboot 的固件安全体系由四大模块构成——Google v固件嵌入式操作系统驱动开发coreboot vboot 验证启动全指南信任根、固件布局、镜像签名与启动流程coreboot vboot 验证启动全指南信任根、固件布局、镜像签名与启动流程 本文以 coreboot 官方文档 Documentation/securi固件嵌入式操作系统驱动开发上一篇Ninjabrain-Bot常见问题解答解决测量偏差与跨hair校准难题下一篇BOOTSTRA.386 Flexbox 工具类全解用 Bootstrap 5.3 的 Flex 工具类快速完成布局、对齐与排序创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →