Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[crypto] Add a counter to the main loop of ECDSA-P256 verify. #23921

Merged
merged 3 commits into from
Jul 6, 2024

Conversation

jadephilipoom
Copy link
Contributor

This is a simple, lightweight hardening measure against fault-injection attacks on the loop control flow in OTBN, just in case the hardware hardening measures don't hold up as well as we'd like.

The OTBN ECDSA-P256 verification program returns two results: an "OK" value that's either kHardenedBoolTrue or kHardenedBoolFalse, and the recovered "r" value that should be equal to "r" from the signature if the signature was valid. Ibex needs to check both values.

The new counter basically just piggybacks on the existing "OK" value; instead of directly writing kHardenedBoolTrue into the "OK" buffer, we load the constant kHardenedBoolTrue ^ 256 and then XOR it with a counter that gets incremented on every loop iteration. If the counter says 256 iterations, we get the right value, but if not we'll get something else and Ibex will detect that something is wrong in the code here:

// Check if the signature passed basic checks.
uint32_t ok;
HARDENED_RETURN_IF_ERROR(sc_otbn_dmem_read(1, kOtbnVarBootOk, &ok));
if (launder32(ok) != kHardenedBoolTrue) {
return kErrorSigverifyBadEcdsaSignature;
}
// Read the status value again as an extra hardening measure.
HARDENED_RETURN_IF_ERROR(sc_otbn_dmem_read(1, kOtbnVarBootOk, &ok));
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);

If we wanted to be even more strict, we could cause a more catastrophic error if ok != kHardenedBoolFalse. We could also consider starting the counter at 2^32-1 instead of 0, so that the expected value is 255, which would just give us more bits that the counter flips. Open to opinions on more advanced strategies, but for now I just went with the simplest version.

Copy link
Contributor

@johannheyszl johannheyszl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jadephilipoom this is great. I have reviewed the code - it looks effective and correct!

Copy link
Contributor

@vogelpi vogelpi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jadephilipoom and @johannheyszl ! The change looks good to me.

IMO, we don't need to further harden the newly added counter: if an adversary managed to glitch the counter, they would still need to glitch other stuff to actually exploit this. But if there is a very easy way to further improve things I also wouldn't say no :-)

@jadephilipoom
Copy link
Contributor Author

But if there is a very easy way to further improve things I also wouldn't say no :-)

Challenge accepted 🙂 After a little thought and taking a look at the code again, I added a new commit that expands on the idea just a little bit. Instead of using addi and a constant 1, it sets register x11 to 1 at the start of the loop and uses that to increment the counter. At various points in the control flow that directly follow branches on boolean values, I used and/srl with the x11 register so that it stays 1 if the control flow is followed correctly and gets flipped to 0 otherwise. That way, faults that cause the branches to get skipped would also cause the counter to not increment. I can remove this second commit if folks think the complexity isn't worth it. (The effect on performance is negligible.)

@johannheyszl
Copy link
Contributor

Thank @jadephilipoom you this is very nice. I support keeping it.

Copy link
Contributor

@timothytrippel timothytrippel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jadephilipoom , this is great! Let's get this in once CI passes, and hopefully tonight's or tomorrow's nightly regression can run with the change.

@timothytrippel
Copy link
Contributor

One thing: you will probably have to update the rom self hash test since it will fail on the fpga if the rom changes at all now that it is running in CI. See the instructions here: https://cs.opensource.google/opentitan/opentitan/+/master:sw/device/silicon_creator/rom/e2e/release/rom_e2e_self_hash_test.c;drc=9d2140b0ad00c7337454f85edb7772d611a5615b;l=31

@jadephilipoom jadephilipoom requested a review from a team as a code owner July 5, 2024 13:34
@jadephilipoom jadephilipoom requested review from jon-flatley and removed request for a team July 5, 2024 13:34
@jadephilipoom
Copy link
Contributor Author

One thing: you will probably have to update the rom self hash test since it will fail on the fpga if the rom changes at all now that it is running in CI. See the instructions here: https://cs.opensource.google/opentitan/opentitan/+/master:sw/device/silicon_creator/rom/e2e/release/rom_e2e_self_hash_test.c;drc=9d2140b0ad00c7337454f85edb7772d611a5615b;l=31

Thanks for the tip, should be updated now!

This is a lightweight hardening measure against fault-injection attacks on the
loop control flow in OTBN.

Signed-off-by: Jade Philipoom <jadep@zerorisc.com>
Make the counter increments dependent on some should-be-noop instructions
throughout the control flowof the main loop.

Signed-off-by: Jade Philipoom <jadep@zerorisc.com>
Updates the golden hashes to incorporate the new counter in P256 verify.

Signed-off-by: Jade Philipoom <jadep@zerorisc.com>
@jadephilipoom jadephilipoom merged commit c42c47e into lowRISC:master Jul 6, 2024
32 checks passed
@jadephilipoom jadephilipoom deleted the p256-verify-counter branch July 6, 2024 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants