Abstract
- 问题背景: 现代硬件设计(SoC)日益复杂,重用性设计虽然降低了成本,但也增加了安全漏洞的风险。传统的形式化验证(Formal Verification)受限于可扩展性,而基于模拟的验证(Simulation)往往忽略关键的边缘情况。
- 现有挑战: 现有的硬件模糊测试(Fuzzing)技术面临输入覆盖率有限、难以遍历分支路径、电路参数管理复杂以及难以融入工业界标准工作流(如UVM)等问题。
- 提出方案:SymbFuzz。这是一种创新的混合硬件模糊测试方法,结合了通用验证方法学(UVM)和符号执行(Symbolic Execution)。
Background
- 覆盖率引导的模糊测试: 基于边界值分析,通过变异输入来探索未定义的行为。
- 符号执行: 使用符号值而非具体值来表示输入,通过求解约束条件(Constraints)来确定特定执行路径所需的输入。
- UVM (Universal Verification Methodology): 半导体行业广泛使用的标准化验证框架,包含驱动器(Driver)、监视器(Monitor)、序列器(Sequencer)等组件。(参考)
Design
总体架构 Overall Architecture

三部分:Simulation setup (a-c), coverage measurement (d), seed mutation (e-f)
算法概括:
- 提取 I/O Interface,构建控制流图 CFG。对寄存器进行分类,对关键状态(检查点)进行标记。CFG 的起点是复位状态;每个节点都是一个硬件状态,由寄存器向量决定;每个边都是状态的转移,由输入状态和上下文决定。
- 根据输入和参数创建一个 UVM 环境
- 持续进行模糊测试,直到所有的检查点被覆盖。
- 如果多次间隔(到达参数阈值)没有覆盖率增长,触发符号执行,它会找到最新覆盖的状态(第 14 行),定位最近的检查点(第 15 行),并回溯控制流图(CFG)以找出未探索的路径(第 16-18 行)。系统会重置并使用约束求解器来到达这些路径(第 19-21 行)。
UVM 集成 UVM Integration

图 2 阐述了 SymbFuzz 的架构及其与 UVM 的集成。模块(1)至(7)描述了标准的 UVM 设置,而 SymbFuzz 通过模块(8)至(11)对该框架进行了扩展。SymbFuzz 首先利用 UVM 模板配置仿真平台,从而实现验证框架的自动化。接着,它使用 PyVerilog 提取待验证设计(DUV)的输入输出(I/O)接口,使其能够与 UVM 驱动器和 UVM 监视器相连。这就构建起了基于 UVM 的验证环境。
为了启动模糊测试机制,SymbFuzz 使用 PyVerilog 生成 DUV 的控制流图(CFG)(8)。然后,它从该控制流图中推导出依赖方程,这些方程将控制寄存器表示为输入接口的函数(9)。之后,这些方程由 SMT 求解器(z3-solver)进行求解,生成约束条件,这些约束条件能让 UVM 定序器生成专门用于改变控制寄存器值的输入序列 [22]。这种调整可引导 DUV 遍历控制流图中未探索的路径,尤其是在覆盖率提升达到瓶颈时(10)。生成的约束条件随后会被集成到 UVM 定序器中,从而启动下一批仿真。
依赖分析:状态转换取决于状态寄存器,而状态寄存器会受到输入模式序列、输入组合或两者的影响。要实现这一点,需要理解状态寄存器如何依赖于输入端口,这可以通过使用依赖图和从控制流图(CFG)推导的方程来分析。
检查点设定 Checkpoing Setup
完全重置会导致测试效率低下,因此使用基于控制流图(CFG)的结构特征自动确定的检查点。
检查点确定:对于 CFG 的每一个节点(硬件状态),计算其直接后继状态的数量,只要大于阈值即认定该节点是一个检查点。
检查点路径记录:如果确定一个节点检查点,那么它会记录从复位状态(Reset)到达该检查点节点所需的一系列输入向量(Input Sequence),并且该路径被标记为当前检查点的专属路径。
总的来说,生成 CFG -> 找岔路口(出口 >= T) -> 标记为检查点 -> 记下“怎么走到这的路”
覆盖率衡量 Coverage Measurement
SymbFuzz 将硬件的每一个“状态”(Node)定义为当前控制寄存器值的唯一组合。
从两个维度去追踪覆盖率:
- 节点覆盖率(Node Coverage),是否访问了 CFG 中的每一个状态节点。如果一个节点“已覆盖”,那么意味着仿真时达到了该节点所对应的特定的控制寄存器值的组合。
- 边覆盖率(Edge Coverage),是否遍历了状态之间的转换。重点关注的是那些检查点,只有当一个检查点所有的分支都至少被执行了一次,该节点的边覆盖才算完成。
SymbFuzz 将覆盖率目标定义为控制语句条件结果的笛卡尔积(Cartesian Product)。如果一个跳转决定依赖于两个条件(例如 r1 == 0 和 r2 == 1),那么覆盖率目标就是这两个条件所有可能结果的组合(即 2×2=4 种情况)。完全覆盖(Full Coverage) 意味着 CFG 中的每一条边(Edge)都至少被执行了一次。
SymbFuzz 进行运行时追踪,在每次仿真结束后,SymbFuzz 会扫描 Dump 文件。 如果在一定时间间隔内(Interval)没有发现新的节点或边,系统就会判定覆盖率增长停滞,从而激活符号执行引擎来计算新的输入约束,以打破停滞。
路径推进策略 Path Progressing Strategy
这个策略只有在覆盖率增长停滞时启动,旨在通过一套策略选择最优的路径进行突破。
最大化收益原则:利用 SMT 求解依赖方程,优先选择能解锁最多未访问节点(New Nodes)的路径。
回溯机制:如果当前检查点下达到了完全覆盖,SymbFuzz 将退回的父节点。
平局决胜:如果多个路径收益(相同数量的新节点)相同,选择汉明距离最小的路径,即选择那个需要改变最少比特位就能到达的目标状态,这样往往最容易实现,计算代价最小。
种子生成和变异 Seed Generation and Mutation
初始种子:利用 UVM 本身提供的随机位串生成功能,快速覆盖容易到达的状态。
种子变异:利用覆盖率日志分析停滞点,确定下一个目标状态,利用 SMT 求解依赖方程,得到输入端口必须满足什么条件才能进入到下一个状态。SMT 的输出是一组约束条件,使得 UVM 后续生成的随机位串符合约束条件的规则。
漏洞识别 Bug Identification
SymbFuzz 针对的是硬件逻辑,其核心机制是基于属性的验证(Property-based Verification)。
SymbFuzz 不仅仅比较输出结果是否正确(因为很多安全漏洞并不影响功能输出),而是在 RTL 代码中插入监控器(Monitors),实时检查硬件行为是否违反了预定义的安全属性。
这些安全属性是基于 CVE (Common Vulnerabilities and Exposures) 和 CWE (Common Weakness Enumeration) 数据库中的常见硬件漏洞模式推导出来的。
使用 SystemVerilog 断言 (SVA)。例如,定义 property 块来描述“由于某种条件触发,信号 A 绝对不能等于信号 B”。
Evaluation and Results
文中列出了 14 个漏洞,大概可以分为四类。

类型 1. 信息泄露与侧信道风险 (Information Leakage & Side-Channel Risks)
这类漏洞涉及敏感数据(如密钥、伪随机数)被意外暴露,或者防侧信道攻击的机制失效。
- 密钥泄露 (Bug #04): AES 模块在总线上泄露了密钥分片(Key Shares)。这是一个典型的安全漏洞,虽然功能上加密结果是正确的(符合黄金模型),但总线暴露了秘密。
- 掩码失效 (Bug #06): AES 的掩码操作(Masking)本应使用伪随机数(PRNG)来防御侧信道攻击,但被错误地关闭(始终为 0)。
- 盲化失效 (Bug #07): 大数计算单元(OTBN)的盲化操作(Blanking)被禁用,导致操作数透明,容易遭受功率分析攻击。
- 相关 CWE: CWE-1342, CWE-1300, CWE-325。
类型 2. 状态机逻辑漏洞 (FSM Logic & State Transition Vulnerabilities)
这类漏洞涉及有限状态机(FSM)的转换逻辑错误,导致安全检查被绕过或进入未定义状态。
- 绕过检查状态 (Bug #08): ROM 控制器的状态机跳过了“检查(Check)”状态,直接跳到了“完成(Done)”状态,导致完整性验证被绕过。
- 未定义的默认状态 (Bug #02): 状态机存在未定义的默认状态(Undefined default state),可能导致硬件进入不可预测的行为。
- 过早解锁功能 (Bug #03): 在未锁定状态(Unlocked state)完成测试之前,就错误地启用了生产功能(Production function)。
- 相关 CWE: CWE-1245, CWE-1269, CWE-1199。
类型 3. 数据清理与残留 (Incomplete Cleanup / Data Residue)
这类漏洞涉及在重置或操作完成后,敏感数据未被彻底清除,攻击者可能通过残留数据恢复机密信息。
- 寄存器未清除 (Bug #05): 伪随机数据寄存器在使用后未被清除。
- 清理流程不完整 (Bug #09): 电源管理模块中的清理(Clear)信号置位过早,导致清理过程未完成就停止了。
- 数据刷新失败 (Bug #14): 在接收到使能信号时,数据未按预期进行刷新(Flush)。
- 相关 CWE: CWE-459, CWE-1304, CWE-1266。
类型 4. 错误处理与反馈抑制 (Error Handling & Feedback Suppression)
这类漏洞会导致系统在遭受攻击或发生错误时无法报警,使攻击者可以“静默”地进行尝试。
- 静默失败 (Bug #01) [CWE 2025 新条目]: 这是一个在 OpenTitan Mailbox 模块中发现的新漏洞。当尝试向保留地址写入数据时,系统虽然丢弃了数据,但没有反馈任何错误或警告。这允许攻击者无限次尝试写入而不被发现。
- 错误标志位错误 (Bug #13): 系统复位控制器(SysRst Ctrl)产生的错误标志位数值错误,导致无法正确指示错误类型。
- 相关 CWE:New Entry, CWE-1320, CWE-1257。
性能分析
SymbFuzz 在资源消耗和性能之间取得了平衡(详见 Section 5.2):
- 内存开销 (Memory):
- 比 DifuzzRTL 多用约 4%。
- 比 RFuzz 多用约 7%。
- 比 HWFP 少用 7%。
- 分析: 虽然内存略有增加(用于维护 CFG 和检查点),但考虑到其检测能力的巨大提升,这是可接受的权衡。
- CPU 效率:
- 计算效率与 RFuzz 相当。
- 综合效率(资源/检出率)比 DifuzzRTL 高 33%,比 HWFP 高 54%。
- 加速机制: 虽然符号执行(SMT求解)本身很慢,但 SymbFuzz 通过 “检查点重放(Checkpoint Replay)” 技术(仅需微秒级恢复)抵消了这部分开销,避免了昂贵的全系统重启。
覆盖率与收敛速度
SymbFuzz 不仅找得准,而且找得快,能探索更深的状态空间(详见论文 Figure 4 和 Section 5.3):
- 收敛速度: 相比于传统的 UVM 随机测试,SymbFuzz 达到相同功能覆盖率的速度快了 6.8倍。
- 覆盖率深度:
- 相比 DifuzzRTL 提升了约 6%。
- 相比 HWFP 提升了约 10%。
- 相比 RFuzz 提升了约 15%。
- 突破瓶颈: 传统的随机测试在达到一定程度后会进入“饱和平台期”(Plateau),无法再发现新状态。SymbFuzz 利用符号执行成功突破了这一瓶颈,持续发现新的覆盖点(Edge-State Pairs)。

Discussion
设计原理
- 超越黄金模型的安全性:功能正确性并不能确保安全性。
- 基于覆盖的混合模糊测试:模糊测试侧重速度,符号执行侧重深度。
- 选择性符号分析:将符号推理限制在关键控制寄存器上,并使用检查点来管理状态。
可扩展性
SymbFuzz 通过将 SMT 引导的状态剪枝与基于检查点的重放相结合,实现了高效的扩展。
扩展适用性以检测制造缺陷
SymbFuzz 最初是为检测安全漏洞而开发的,但它也能够识别由制造缺陷导致的故障。这需要使用黄金参考模型而非断言,并在模糊测试过程中对输出进行比较。其核心功能 —— 检查点机制和依赖引导的控制流图遍历 —— 仍然有效,这体现了它在安全验证和可靠性验证方面的适应性。
假阳性和假阴性
在测试的设计和时间限制内,SymbFuzz 实现了与同类工具相当或更优的覆盖率。然而,RTL 设计存在大量的边缘情况,因此尽管在我们当前的实验中没有出现,但需要专门分析的缺陷可能仍然存在。
架构对缺陷特征的影响
我们在第 5 节中的评估表明,顺序执行的 Ibex 和 Rocket 基准测试中的所有缺陷都与指令排序或 CSR 处理有关。这些内核严格按顺序执行指令,并且缺乏诸如重排序缓冲区或分支恢复逻辑等推测性特征。
Conclusion
SymbFuzz 成功证明了将符号执行与 UVM 结合的有效性。它通过智能的路径规划和高效的状态恢复机制,解决了硬件验证中“进不去(覆盖率低)”和“测不准(漏报安全隐患)”的难题,为硬件安全验证提供了一个自动化、高效且可扩展的解决方案。

