ibex
ibex copied to clipboard
Violation of the Data Independent Timing property for misaligned Load and Store Instructions
Observed Behavior
Ibex handles misaligned load and store Instructions by splitting them into two separate, aligned memory accesses. This creates a data dependent execution time for these Instructions. According to the specification, the data_ind_timing control bit should ensure that execution times and power consumption of all instructions shall be independent of input data. However, this does not hold for load and store instructions and creates a possible timing side channel.
Expected Behavior
I would expect Ibex to do either one of the following things:
- Disable the "misaligned address feature" whenever the data_ind_timing bit is set to ensure all loads and stores require a single memory access. If a misaligned access is scheduled, Ibex should perform an aligned access and return bogus data. Further, the specification should tell the SW developer to ensure no misaligned access occurs.
- In a different fix, Ibex could perform an additional dummy memory access (e.g. to an adjacent address), whenever an aligned load/store is issued while the data_ind_timing bit is set.
Steps to reproduce the issue
Enable the data_ind_timing bit and set up a "secret" register value. Issue a LW or LH with the secret register value as source and measure the time. If value+offset result in an aligned access, the instruction will only trigger a single memory access. If value+offset result in a misaligned access, the instruction will trigger two memory accesses.
In the trace, you can see an example with two processor instances.
The data independent timing bit gets set in both processors (via CSRRW) and the same LH instruction is executed.
However, r20 contains different values in the different instances (0 and 3) which causes a misaligned access only in instance 2.
As a consequence, instance 1 finishes earlier and is ready for the next instruction (id_in_ready_o) whereas instance 2 is requesting a second memory access (data_req_o).
My Environment
I set up a set of formal SVA properties inside OneSpin to prove data independent execution of different instructions, both with and without the data_ind_timing bit. For the proofs, I only consider the ibex_core, i.e., without cache or register file, in a 2-safety approach. If you are interested in the details of the methodology, feel free to message me.
My Results
I was able to prove that branches, division and (slow) multiplication have data dependent timing in the non-secure Ibex setting. As described in the specification, when the data_ind_timing bit set, all of these issues get resolved. However, I also got counterexamples for both load and store instructions, showing that the same instruction can cause different timing behavior based on register values. This behavior does not change with an enabled data_ind_timing bit set.
EDA tool and version: OneSpin 360 DV - Version 2021.1.1
Operating system: Ubuntu Linux 18.04
Version of the Ibex source code: 90ff7ca6c3367da721dba13e91dfc98f782a5745
Thanks for this detailed report @Seek64.
Reading through it, I think we might have a specification issue here, not so much an implementation issue. And the solution could be to simply specify that the timing of memory accesses (load and store) is unspecified and can depend on the address accessed and other factors outside of the CPU's control, even if data independent timing is enabled.
Two reasons for that:
- One of them is the one you're reporting here: misaligned addresses have a different timing behavior.
- Another reason is the unpredictability of the memory access timing once it leaves the Ibex boundary: depending on where the request goes (e.g. to a device vs to main SRAM) and many other factors the timing behavior might be very different.
What do others think?
Agreed - it should be a stipulation on SW to avoid any unaligned accesses in regions of code where this security property is required. We can't arbitrarily perform extra memory accesses for aligned loads/stores since those accesses might have side effects. All data-side memory is treated as "non-idempotent" (in RISCV terminology) in Ibex.
Hello everyone,
Thank you for the responses. I don't see the issue as a major HW security breach, yet, there are some subtleties that should be considered for a system with a high level of security.
Of course, if the memory system is non-oblivious, so will be all load and store operations inside of Ibex. However, if Ibex shall support data-oblivious computing (as the data-independent timing bit suggests), it needs to be integrated with a data-oblivious memory subsystem. Typically, such a memory subsystem hides data, addresses and timing of accesses. An example would be an Oblivious RAM Controller that blocks information leakage by maintaining all memory contents encrypted and memory locations randomly shuffled (see https://ieeexplore.ieee.org/document/7160074). However, even with strong countermeasures like this in place, Ibex could still introduce a security violation by varying the total number of memory accesses.
If you see it as an obligation of the software programmer to ensure that misaligned memory accesses never occur in the data-independent timing mode, then, in that mode, the hardware should not support that feature. Otherwise, it could possibly create an attack surface. If erroneous/malicious code containing a misaligned access is run on the core, it would create a visible timing footprint.
As a possible and relatively simple hardware fix, Ibex could simply perform an aligned access upon a misaligned memory request, and return bogus data. After such a fix, the erroneous/malicious software would, of course, not produce the correct results, but the hardware would still remain resilient to possible timing side channels.
In any event, I agree that these restrictions must be communicated to the software developer as part of the specification.
Thanks again for this report and the input on proposed solutions. For now, I have added #1455 to update the documentation. We don't want to increase the verification space by changing any Ibex behavior at the moment but I'll leave this issue open to track that option for the future.