lowRISC / ibex

Ibex is a small 32 bit RISC-V CPU core, previously known as zero-riscy.
https://www.lowrisc.org
Apache License 2.0
1.37k stars 542 forks source link

Security vulnerability: Ibex leaks data when multiplication is aborted #2144

Closed KatCe closed 5 months ago

KatCe commented 8 months ago

Observed Behavior

A MULH instruction that is aborted by an unsolicited memory error response leaks information about its input values to a subsequent MUL instruction. The subsequent MUL instruction stores a value dependent on MULH's operands into its result register, thus produces a wrong result and leaking information.

I believe that the reason is that the multiplication's module's internal state machine is not reset in case of an abort.

Expected Behavior

Ibex should not leak data in case of external interface errors.

Steps to reproduce the issue

The testbench in https://github.com/KatCe/ibex/tree/bug_mulh_reg_leakage/dv/bug_mulh_reg_leakage demonstrates the problem. This testbench uses the default configuration. We have also observed the bug in secure configuration with the parameters commented in the testbench.

My Environment

EDA tool and version:

Questa Sim-64, Version 2022.3_1 linux_x86_64 Aug 12 2022

Operating system:

Ubuntu 20.04.6 LTS Version of the Ibex source code:

5a8a1a99930afbb9efe107ff2c80d482239d7a5f The exact list of files run by the test bench can be found in https://github.com/KatCe/ibex/blob/bug_mulh_reg_leakage/dv/bug_mulh_reg_leakage/flist.f

GregAC commented 8 months ago

Thank you for the report @KatCe. We are looking at this internally and will report back once we've examined the issue in detail.

GregAC commented 6 months ago

@KatCe thank you for the report we now have a fix in a PR https://github.com/lowRISC/ibex/pull/2166

With regards to the issue itself it should be noted that Ibex assumes correct adherence to bus protocol by whatever it is connected to. This issue only occurs when there is a violation of that bus protocol so I don't view this as a functional bug.

As you point out this is more of a security issue than a functional issue and in particular it requires an attacker to first inject a fault to trigger the spurious error response. That fault could then disrupt a future multiply instruction or if the attacker is enable to execute code they could use a specifically crafted multiply instruction to infer information about a previous multiply instruction.

The default secure Ibex configuration utilizes dual core lockstep so the fault would have to be injected before the response is sent into the core. In a secure integration it's envisioned ECC or other integrity protection is provided on both requests and responses (this is in the case in OpenTitan for instance). So the fault would need to be injected beyond the point the integrity is checked but before the response is separately fanned out to the two lockstep cores so there is a limited window to inject the required fault.

For an Ibex implementation without the fix a software solution exists. As it triggers an exception handler you could simply execute a trivial multiply (e.g 0 0 or 1 1) to clear out the state machine.