lowRISC / opentitan

OpenTitan: Open source silicon root of trust
https://www.opentitan.org
Apache License 2.0
2.54k stars 757 forks source link

[boot_flow] Self-authenticate boot images for faster boot flow #20414

Open ballifatih opened 10 months ago

ballifatih commented 10 months ago

Description

Summary

We can reduce signature verification during boot time to single KMAC operation by self-authenticating boot firmware. Depending on the number of boot stages, this cost might be multipled by 2 or more.

Details

To simply describe the idea, let me represent (msg, sig) to denote an image of a boot stage. Normally, each stage would run SigVerify(pub_key, msg, sig) to check authenticity of the next boot stage image, where SigVerify is the verification algorithm of the underlying signature scheme. Running SigVerify might be costly. For instance, a verification takes about 3ms and 13ms for RSA and SPHINCS+ respectively.

We can speed up this verification considerably by adding authentication tags next to boot images and verifying these symmetric tags instead of actual public-key signatures. The tags would be generated by KMAC with a symmetric key derived by Keymgr and these keys would be unique to each device.

Following the same notation, when the boot image is of the form (msg, sig), we can add a third field to this tuple to get (msg, sig, tag). During boot, we can quickly verify KMAC(keymgr_generated_key, msg || sig) = tag and if that check holds, we can skip SigVerify(msg, sig). The tag would be generated after the fresh update and computed directly by the OT device itself.

Benefits

  1. Slower full RSA/SPHINCS+ signature verification would be replaced with faster KMAC operations. The idea is agnostic to signature scheme (which also means one could even go with slower PQ signature schemes in the future).
  2. This could be repeated for each boot stage.
  3. Existing HW already supports this flow. Keymgr can handle the generation of the symmetric key and use the sideload interface to pass the key to KMAC. This flow handles key in two shares. I think no RTL change is needed.
  4. The symmetric key does not need to be static, and it can be regularly rotated (either through update, or by providing further salt values as part of the boot image). Each rotation only costs 1 more SigVerify.

Downside

  1. Keymgr would need to come online earlier during boot flow, in order to generate a symmetric key for KMAC. Furthermore, ROM code needs to be updated in a way that this verification is orchestrated between KMAC and Keymgr. (Or alternatively, one might skip this idea for ROMExt verification and use it for other boot stages).
  2. From security perspective, one also needs to be concerned about potential side-channel leakage of the key used to verify SW images. If this key is recovered by the adversary, it allows loading malicious boot images.

There would be some further aspects to discuss about this idea, such as how to update manifests and where to add such tag field, or whether there should be an OTP bit to enable/disable this feature, but I think it might come down to whether 1) we need a speed-up in the boot flow, 2) whether we can secure the symmetric key against SCA.

ccing for futher discussion: @johannheyszl @jadephilipoom @gdessouky @moidx @timothytrippel @sameo

jadephilipoom commented 5 months ago

It's appealing to have the faster boot time, but wouldn't this require starting up key manager in ROM if we implemented it for the first sigverify? I have a vague recollection that for the current generation we originally wanted to leave all key manager handling to ROM_EXT so that it's possible to update the code in case of issues. Then there was some back and forth over DICE UDS and I'm not sure where we ended up (@moidx @timothytrippel ?). I'm also a little worried that using it for the first sigverify adds the KMAC block and keymgr to the attack surface, since an attacker could compromise only those to break secure boot in a way we can't patch.

One option is that we could implement something like this for later sigverifies in the boot chain, but not the first one -- then we'd get most of the performance benefits but not need to start up keymgr in ROM and would only take on additional attack surface in code that we can patch.

johannheyszl commented 5 months ago

I also think this is probably not something for ROM at this point in time, but can be considered for later stages of boot.

ballifatih commented 5 months ago

I have a vague recollection that for the current generation we originally wanted to leave all key manager handling to ROM_EXT so that it's possible to update the code in case of issues. Then there was some back and forth over DICE UDS and I'm not sure where we ended up (@moidx @timothytrippel ?).

I think the current plan is to do keymgr advancements in ROM_EXT for top_earlgrey.

Whether or not to implement a similar plan suggested in this issue depends on whether we are meeting the boot time requirements for use cases (which I believe will differ from each other). At the moment, we are not advancing keymgr during ROM and that would be the biggest blocker to implement this idea at ROM stage. Later stages could use the idea if needed.

I am not familiar with the timing requirements of the boot stages. Is that information something we can link in this issue?

vsukhoml commented 5 months ago

Another implementation besides caching can be to sign/verify same digest of next stage as verified by P256 signature verification, this way can reuse digest computation for both.