lowRISC / opentitan

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

[entropy_src] Power management functionality and tests #22293

Open vsukhoml opened 5 months ago

vsukhoml commented 5 months ago

Description

There should be a way to disable Entropy source completely and/or partially, if not used. Currently https://opentitan.org/book/hw/ip/entropy_src/doc/registers.html#module_enable is used to disable entropy source.

However, it is unclear from planned tests wherever:

Do health checks, conditioner, internal FIFO continue to work when no entropy is requested? Can these blocks be automatically power down when not used?

@vogelpi

vogelpi commented 1 month ago

I can confirm that the MODULE_ENABLE signal is thoroughly tested at the block and at the top level. We also have and open issue to test if ENTROPY_SRC can be disabled without restarting CSRNG and EDN. This way ENTROPY_SRC and the RNG can be disabled to save power, while CSRNG and EDNs continue to serve entropy to consumers until a reseed is initiated.

When CSRNG executes a reseed command, it triggers an interrupt to software. So software will be informed and can re-enable ENTROPY_SRC (and RNG). This interrupt has already been tested before. In addition, we changed the RTL of CSRNG for Earlgrey-PROD to expose the RESEED_COUNTERS of all contexts via CSRs. This means software can periodically read these RESEED_COUNTERS to get an idea of the entropy consumption in the system and to enable ENTROPY_SRC ahead of time (startup health tests take some time).

At the moment, the guidance is to always disable / enable the full entropy complex to avoid any deadlocks (see e.g. https://opentitan.org/book/hw/ip/csrng/doc/programmers_guide.html#module-enable-and-disable) but knowing the RTL of all there blocks I am confident that ENTROPY_SRC can be disabled / enabled without touching the other blocks. This is what we would like to test at the top level, see #22705.

vsukhoml commented 1 month ago

@vogelpi , thank you! I also tested that I can program CSRNG for both EDN and firmware to use generate command returning 2048 words to extend reseed period even more. Planned usage model - during initialization ENTROPY_SRC is enabled with all health checks properly configured, wait to ensure its state shows running health checks. Initialize CSRNG, EDNs. Program EDNs to instantiate with live entropy from ENTROPY_SRC, set max reseed interval, send Generate command with len=2048 and set Reseed command to not use entropy source [can though use some live entropy taken once]. Program CSRNG for firmware use with similar settings. Wait till data from EDN (RV_IBEX_CORE.RND_STATUS) and CSRNG.GENBITS_VLD is available to ensure successful initialization. Disable ENTROPY_SRC.

vogelpi commented 1 month ago

Planned usage model - during initialization ENTROPY_SRC is enabled with all health checks properly configured, wait to ensure its state shows running health checks. Initialize CSRNG, EDNs. Program EDNs to instantiate with live entropy from ENTROPY_SRC, set max reseed interval, send Generate command with len=2048 and set Reseed command to not use entropy source [can though use some live entropy taken once]. Program CSRNG for firmware use with similar settings. Wait till data from EDN (RV_IBEX_CORE.RND_STATUS) and CSRNG.GENBITS_VLD is available to ensure successful initialization. Disable ENTROPY_SRC.

Thanks for sharing this information @vsukhoml . This sounds reasonable and I strongly believe it should be possible to use the entropy complex that way.

I am not 100% sure at the moment if the FIPS bit drops to 0 if you do a reseed command on the EDNs without using the entropy source. I guess you'll find out using the engineering sample. But what I can guarantee you is that on the production silicon you'll be able to enforce a specific FIPS bit value inside CSRNG directly. So this usage model will definitely be fine for the production silicon.

vsukhoml commented 1 month ago

@vogelpi , thanks for checking!

Practically I don't care much of FIPS bit being set by HW - it is not HW's business to decide what is FIPS as whole module with firmware is in scope. And getting entropy manually and then use it for instantiating CSRNG is perfectly valid. The threat of exposing entropy to firmware is not really important and handled by code reviews to ensure proper use of entropy in the first place.

Is it possible to estimate rate of EDN requests to CSRNG for regular operations, assuming no access through RV_IBEX_CODE.RND_DATA? I guess on A1 it would be possible to get this from CSRNG.RESEED_COUNTER.

vogelpi commented 1 month ago

Practically I don't care much of FIPS bit being set by HW - it is not HW's business to decide what is FIPS as whole module with firmware is in scope. And getting entropy manually and then use it for instantiating CSRNG is perfectly valid. The threat of exposing entropy to firmware is not really important and handled by code reviews to ensure proper use of entropy in the first place.

Ack. We came to the same conclusion prior to M2 - just in time to implement the previously mentioned changes. What is also relevant in my view is that back then, it wasn't clear which mode of operation was going to be selected for certification. So the FIPS bit really has to be software configurable.

Is it possible to estimate rate of EDN requests to CSRNG for regular operations, assuming no access through RV_IBEX_CODE.RND_DATA? I guess on A1 it would be possible to get this from CSRNG.RESEED_COUNTER.

It's very hard to estimate that because:

What I would recommend is running representative software on Z1 and then investigate the INT_STATE_VAL CSR of CSRNG. This CSR gives access to the state database (if set up correctly). At offset 0 you can read the RESEED_COUNTER, see also https://opentitan.org/book/hw/ip/csrng/doc/theory_of_operation.html#working-state-values. Using the INT_STATE_NUM CSR, you can control which instance you're reading via INT_STATE_VAL.