Here we, KattangalSec, document the 17 bugs we managed to find for the challenge. We used a combination of methods for finding bugs. Initially, we relied on a fuzzing approach, trying to apply existing RISC-V based fuzzers and techniques, researching online via arXiv, and Connected Papers. Most of those attempts went in vain. However, we were able to find 3 bugs later on through fuzzing. We also modified Mjolnir and created Lightsaber and were able to be gather the majority of the bugs we have listed below.
Almost all of our work was done agentically, with us, the human, acting usually as a supervisor, and guiding the agent. Our preferred choice of harness was Hermes which acted as the principal orchestrator, documenting and writing exploits and testbenches. OpenCode was also used. We estimate our total AI related API costs to be less than $10 dollars, which was possible due to the generous limits of OpenCode’s Go subscription as well as AgentRouter’s promotional free offer granting $200 credits for GPT 5.6 Sol.
Bugs
- PMP error output always zero
- CTN access-range check overridden
- Key Manager source-key validity gate
- AES DPA masking forceable off
- Debug module auth hardwired to 1
- Lifecycle token compared on 32 bits
- LC transition check OR instead of AND
- LcStProd in two unique case branches
- AES output register reset bypass
- AES S-Box DOM counter fault, DFA key recovery
- KeyMgr EDN error path unconnected
- KeyMgr FSM illegal state silent recovery
- CSRNG unmasked AES (state leak)
- ROM controller single-bit digest compare
- Entropy Markov health test dead
- CSRNG key not zeroized after op
- OTBN URND reseed ignores EDN error
Note on testbenches
The module-level testbenches use the synthesizable stimulus-FSM + main_manual.cpp pattern
(Verilator 4.210’s --main harness does not advance time, so the C++ harness toggles
top-clk explicitly; reset is held 2 cycles, then the FSM runs to completion and prints
the result):
verilator -Wno-fatal -Wno-WIDTH -Wno-UNUSED -Wno-IMPLICIT -Wno-CASEINCOMPLETE \
-Wno-DECLFILENAME -Wno-PINMISSING -Wno-MODDUP -Wno-UNOPTFLAT -Wno-MULTIDRIVEN \
--cc --exe --top-module tb +incdir+<ip>/rtl +incdir+... \
<pkg/prim files in dependency order> <module>.sv <module>_tb.sv main_manual.cpp
make -C obj_dir -f Vtb.mk
./obj_dir/Vtb
Dependency notes: packages must precede modules (e.g. prim_util_pkg before prim_*);
generated/abstract prims come from the fuseSoC/primgen build at
hw/build.verilator_real/src/lowrisc_prim_abstract_*. All referenced RTL is the
competition OpenTitan RTL at the given paths.