lowRISC / opentitan

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

[ot_certs,rom_ext] optimize on-device certificate generation code-size #24558

Open timothytrippel opened 1 month ago

timothytrippel commented 1 month ago

Description

Currently, there exists opentitantool support (opentitantool certificate codegen ...) for generating device libraries that may be used to generate X.509 certificate binary blobs. The libraries make use of a manually crafted device library that can encode simple ASN.1 structures. While this mechanism is extremely flexible, i.e., new certificate extensions can be easily crafted, it comes at a cost of code-size. Specifically, when analyzing the size-breakdown of various components in the ROM_EXT, we can see that:

image

Moreover, we are currently attempting to add support for other DICE certificate extensions, and encodings (i.e., CBOR). If we continue to use the same approach, where we use host tools to generate device code that generates certificates on-device by calling into an additional CBOR device lib, then we could end up bloating the ROM_EXT (if we aim to provide a flexible ROM_EXT that can support multiple DICE certificate formats).

We should investigate a more efficient way to generate certificates on-device.

One approach could be to use an auto-generated fixed-size array template that various fields can be mem-copied into. The original rationale for not using such an approach was that doing so would require all fields in the TBS region to be fixed size, otherwise it is impossible to generate a fixed-sized template array. The biggest issue was that the serial number field in X.509 certs is encoded as an ASN.1 integer type, that does not allow 0 padding on the MSb side. One way around this is to just automatically set the MSb, since serial numbers are not crytpographic, rather just unique values (currently the serial number for OT certs is just a truncated SHA256 of the pub key). Other ideas/suggestions are also welcome.

Marking this lower priority for the time being, as I think we should investigate the size of the additional CBOR encoding libraries that are being vendored-in/implemented, and what room for code we have in ROM_EXT, and the impact the additional CBOR cert generation feature has on ROM_EXT code size before making a decision to pursue additional optimization work.

CC: @cfrantz

pamaury commented 1 month ago

Just a note here that if we really wanted to reduce the size, one possibility would be to hand-craft a function to produce a CDI certificate. This function could be flexible enough to handle both CDI by adding only the necessary parts at runtime. This would basically factor cdi_0_build_tbs and cdi_1_build_tbs into one function (and same for the cdi_0_build_cert). This might even potentially be done by the ot_certs library by allowing optional fields at runtime and having a single cdi.hsjon template.

The codegen code could also be smarter: there are parts of the certificate which are complexity fixed (ie never change at runtime). In this case, the codegen could simply put this into a constant byte array and memcpy instead of filling it at runtime.

If we further want to shave off a few bytes from the asn library, the integer pushing function is the obvious candidate: if we know that we always produce integer of fixed size (like you said, by setting the MSb) then we could simply memcpy the byte and save some bytes (since the function is quite "complex").

Yet another avenue is to look at the assembly code and see why the cdi_X_build_tbs functions are so large: maybe there are opportunities here to reduce the size by writing the code differently?