The main difference between chip security and software security is that once the chip is “printed” it cannot be modified. So if my phone’s CPU has a security issue, it will remain there until I change phones.
This is why it is critical to be able to test the chip before it is “printed” (or taped out). This is one of the tasks that electronic design automation (EDA) tools try to solve.
Why SystemVerilog simulators ?
Hardware can be described using SystemVerilog (check my introduction on it if you are not familiar with it), and as with all programming languages one can write unit tests for it. These will enable to check that all the different components of a chip have the expected behaviour.
As SystemVerilog is a very complex language, simulators can have logic bugs, or mis-translation bugs. These bugs concern the way the simulator simulates the code.
If such a bug is triggered in a design, then when it is printed then the chip will have a different behaviour from the one that was tested. This enables a malicious actor to be write code that will seem innocent in testing and only activate once printed. This enables writing undetectable trojans (during the testing phase), provided one knows of such a bug.
Why fuzzing
If I write a module that performs an addition between two integers, I expect the simulator to simulate it and give me the result of the addition.
But what if the simulator’s addition is broken, and instead of sending $a + b$ back, it would send back $a+b+1$ If I wrote a test that would perform the addition outside of the function and then check if the result match then I would not see any bug. To detect the bug I need to write a test that will take a very specific input -let’s say 2 and 3- and check that the result is 5 and not 6.
This is a very easy example to catch as I know exactly what should be the result.
What if I had a new module which takes two values in input (that need to be summed) and a third value (the quantity of carries that need to be added). What if I could put a negative carry ? If the programmer that writes the testbenches thinks of this test, then he might prevent a bug. If he does not, then maybe a bug is present there.
Determining all these potential bugs is tough and that is why many security researchers have resolved to use fuzzers to try and find bugs in programs.
What is a fuzzer
A fuzzer is a piece of software which will try as many values as possible as inputs to all the functions and try and determine if the result is what we expect or not. Here are two deep examples.


As you can tell it is hard to know when the fuzzer found a bug or not… So most fuzzers rely on the program
- crashing (ending unexpectedly)
- hanging (never ending)
And some use “golden models”, which are other programs/methods which give the expected value, and who we can trust.
If we want to find mis-translation bugs we need a golden model approach. There is none for SV… each simulators hopes to be one…
So we resort to differential fuzzing : it consists in sending the same input to two programs and see if they agree or not on the output.
Yet another fuzzer
To fuzz the SystemVerilog (SV) simulators we need to create valid hardware designs.
If you read my short SystemVerilog introduction then you understand that non determinism is going to be a big problem, I mean a biiiiiiiiiiiig problem. (quick recap: SV enables writing code which can have a different behaviour each time it is run).
In my differential fuzzer I rely on two simulators giving me two different outputs for a same input. When I find one, how can I know that I found a bug in one of the simulators and not a non-deterministic input…
There already exists fuzzers for SV, but the code they generate is poor, because this language has many rules, code must abide by, and as the language is very complex (proof is no simulator fully supports SV), then writing code (the fuzzer) to produce such code (the input to the simulators) that will trigger code (in the simulators) is very complex.
This is why a new fuzzer was needed, a fuzzer specifically targeted for hardware description language, that handles:
- generating deterministic SystemVerilog code
- handling the partial support of all the tools
- generating rich and complex SystemVerilog code
These are the problems VeriFuse tries to address.