| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| #ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_CSRNG_H_ |
| #define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_CSRNG_H_ |
| |
| /** |
| * @file |
| * @brief <a href="/hw/ip/csrng/doc/">CSRNG</a> Device Interface Functions |
| */ |
| |
| #include <stdint.h> |
| |
| #include "sw/device/lib/base/macros.h" |
| #include "sw/device/lib/base/mmio.h" |
| #include "sw/device/lib/dif/dif_base.h" |
| |
| #include "sw/device/lib/dif/autogen/dif_csrng_autogen.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif // __cplusplus |
| |
| /** |
| * This API implements an interface for the CSRNG hardware. |
| * |
| * The API follows the naming conventions used in NIST SP 800-90Ar1: |
| * |
| * - Instantiate. |
| * - Update |
| * - Reseed |
| * - Generate |
| * - Uninstantiate |
| * |
| * The seed used for instantiation can either be provided directly in |
| * hardware by an entropy source module; or directly by software. See |
| * `dif_csrng_instantiate()` and `dif_csrng_entropy_src` for |
| * more details. |
| * |
| * The following sequence of operations are required to initialize |
| * and generate cryptographic entropy from the CSRNG module: |
| * |
| * - `dif_csrng_init()` |
| * - `dif_csrng_configure()` |
| * - `dif_csrng_instantiate()` |
| * - `dif_csrng_generate_start()` |
| * - `dif_csrng_uninstantiate()` |
| * |
| * The following functions can be used for reseed and update operations: |
| * |
| * - `dif_csrng_reseed()` |
| * - `dif_csrng_update()` |
| * |
| * The following utility functions are available to poll the state of |
| * the hardware: |
| * |
| * - `dif_csrng_get_cmd_interface_status()` |
| * - `dif_csrng_get_output_status()` |
| * |
| * Please see the following documentation for more information: |
| * https://docs.opentitan.org/hw/ip/csrng/doc/ |
| * |
| * Remaining work: |
| * |
| * - Add error status interface. |
| * - Add internal state control and debug interface. |
| */ |
| |
| /** |
| * Enumeration of CSRNG command interface states. |
| */ |
| typedef enum dif_csrng_cmd_status_kind { |
| /** |
| * The command interface is ready to accept commands. |
| */ |
| kDifCsrngCmdStatusReady, |
| /** |
| * The command interface is processing a command. |
| */ |
| kDifCsrngCmdStatusBusy, |
| /** |
| * The command interface completed with an error. |
| */ |
| kDifCsrngCmdStatusError, |
| } dif_csrng_cmd_status_kind_t; |
| |
| /** |
| * Enumeration of CSRNG FIFOs, which indicates which part of the hardware |
| * produced an error. |
| */ |
| typedef enum dif_csrng_fifo { |
| kDifCsrngFifoCmd, |
| kDifCsrngFifoGenBits, |
| kDifCsrngFifoCmdReq, |
| kDifCsrngFifoRcStage, |
| kDifCsrngFifoKeyVrc, |
| kDifCsrngFifoUpdateReq, |
| kDifCsrngFifoBencRec, |
| kDifCsrngFifoBencAck, |
| kDifCsrngFifoPData, |
| kDifCsrngFifoFinal, |
| kDifCsrngFifoGBencAck, |
| kDifCsrngFifoGrcStage, |
| kDifCsrngFifoGGenReq, |
| kDifCsrngFifoGadStage, |
| kDifCsrngFifoBlockEnc, |
| } dif_csrng_fifo_t; |
| |
| /** |
| * Enumeration of CSRNG FIFO errors. |
| */ |
| typedef enum dif_csrng_error { |
| /** |
| * Indicates an error in the command stage state machine. |
| */ |
| kDifCsrngErrorCmdStageSm, |
| /** |
| * Indicates an error in the main state machine. |
| */ |
| kDifCsrngErrorMainSm, |
| /** |
| * Indicates an error in the DRBG's generator state machine. |
| */ |
| kDifCsrngErrorDrbgGenSm, |
| /** |
| * Indicates an error in the DRBG's block encoding state machine. |
| */ |
| kDifCsrngErrorDrbgUpdateBlockEncSm, |
| /** |
| * Indicates an error in the DRBG's block output state machine. |
| */ |
| kDifCsrngErrorDrbgUpdateOutBlockSm, |
| /** |
| * Indicates an error in the AES state machine. |
| */ |
| kDifCsrngErrorAesSm, |
| /** |
| * Indicates an error in the generate command's counter. |
| */ |
| kDifCsrngErrorGenerateCmdCounter, |
| /** |
| * Indicates a write to a full FIFO occured. |
| */ |
| kDifCsrngErrorFifoWrite, |
| /** |
| * Indicates a read from an empty FIFO occured. |
| */ |
| kDifCsrngErrorFifoRead, |
| /** |
| * Indicates a FIFO was somehow both full and empty. |
| */ |
| kDifCsrngErrorFifoFullAndEmpty, |
| } dif_csrng_error_t; |
| |
| /** |
| * The status of the CSRNG block at a particular moment in time. |
| */ |
| typedef struct dif_csrng_cmd_status { |
| /** |
| * The kind of status the CSRNG is in. |
| */ |
| dif_csrng_cmd_status_kind_t kind; |
| /** |
| * A bitset of FIFOs in an unhealthy state, with bit indices given by |
| * `dif_csrng_fifo_t`. |
| */ |
| uint32_t unhealthy_fifos; |
| /** |
| * A bitset of errors, with bit indices given by `dif_csrng_error_t`. |
| */ |
| uint32_t errors; |
| } dif_csrng_cmd_status_t; |
| |
| /** |
| * CSRNG consume seed from entropy source enable. |
| */ |
| typedef enum dif_csrng_entropy_src_toggle { |
| /** |
| * Seed material used as the only seed material. |
| * |
| * This configuration option will toggle the hardware state of the |
| * CSRNG to non-FIPS compliant until it is re-instantiated. |
| * |
| * Note: Software may opt to XOR the seed material with a seed to implement |
| * a software assisted FIPS mode of operation. |
| */ |
| kDifCsrngEntropySrcToggleDisable = 1, |
| /** |
| * Entropy source XOR'ed with the provided seed material. |
| */ |
| kDifCsrngEntropySrcToggleEnable = 0, |
| } dif_csrng_entropy_src_toggle_t; |
| |
| enum { |
| /** |
| * Maximum seed material number of uint32_t words supported in CSRNG |
| * instantiate and seed commands. |
| */ |
| kDifCsrngSeedMaterialMaxWordLen = 12, |
| }; |
| |
| /** |
| * CSRNG common transaction parameters. |
| */ |
| typedef struct dif_csrng_seed_material { |
| /** |
| * Number of uint32_t words in `seed_material`. Up to 12 words can be |
| * set to initialize the CSRNG. CSRNG will extend the `seed_material` |
| * to zeros if the provided value is less that 12. |
| */ |
| size_t seed_material_len; |
| /** |
| * Seed material used in CSRNG |
| */ |
| uint32_t seed_material[kDifCsrngSeedMaterialMaxWordLen]; |
| } dif_csrng_seed_material_t; |
| |
| /** |
| * Generated output state. |
| */ |
| typedef struct dif_csrng_output_status { |
| /** |
| * Set to true when there is cryptographic entropy data available to |
| * read using `dif_csrng_generate_read()`. |
| */ |
| bool valid_data; |
| /** |
| * Set to true when the cryptographic entropy data available to read |
| * is FIPS/CC compliant at the hardware level. |
| */ |
| bool fips_mode; |
| } dif_csrng_output_status_t; |
| |
| /** |
| * CSRNG internal state selector ID. |
| */ |
| typedef enum dif_csrng_internal_state_id { |
| /** |
| * CSRNG instance assigned to Entropy Distribution Network (EDN) 0. |
| */ |
| kCsrngInternalStateIdEdn0 = 0, |
| /** |
| * CSRNG instance assigned to Entropy Distribution Network (EDN) 1. |
| */ |
| kCsrngInternalStateIdEdn1 = 1, |
| /** |
| * CSRNG instance assigned to software interface. |
| */ |
| kCsrngInternalStateIdSw = 2, |
| } dif_csrng_internal_state_id_t; |
| |
| /** |
| * CSRNG internal state. |
| */ |
| typedef struct dif_csrng_internal_state { |
| /** |
| * Indicates the number of requests for pseudorandom bits since instantiation |
| * or reseeding. |
| */ |
| uint32_t reseed_counter; |
| /** |
| * Internal V working state with a 128bit block size. |
| */ |
| uint32_t v[4]; |
| /** |
| * Internal key used to configure the internal CSRNG cipher. |
| */ |
| uint32_t key[8]; |
| /** |
| * Set to true when the CSRNG instance has been instantiated. |
| */ |
| bool instantiated; |
| /** |
| * Set to true when FIPS compliant entropy was provided directly by the |
| * entropy source to instantiate or reseed the CSRNG instance. |
| */ |
| bool fips_compliance; |
| } dif_csrng_internal_state_t; |
| |
| /** |
| * Recoverable alerts emitted by the CSRNG. |
| */ |
| typedef enum dif_csrng_recoverable_alert { |
| /** |
| * Indicates a bad value was written to the ENABLE field of the control |
| * register. |
| */ |
| kDifCsrngRecoverableAlertBadEnable, |
| /** |
| * Indicates a bad value was written to the SW_APP_ENABLE field of the control |
| * register. |
| */ |
| kDifCsrngRecoverableAlertBadSwAppEnable, |
| /** |
| * Indicates a bad value was written to the READ_INT_STATE field of the |
| * control register. |
| */ |
| kDifCsrngRecoverableAlertBadIntState, |
| /** |
| * Indicates the genbits bus saw two identical values, indicating a possible |
| * attack. |
| */ |
| kDifCsrngRecoverableAlertRepeatedGenBits, |
| } dif_csrng_recoverable_alert_t; |
| |
| /** |
| * Configures CSRNG. |
| * |
| * This function should need to be called once for the lifetime of `csrng`. |
| * |
| * @param csrng A CSRNG handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_configure(const dif_csrng_t *csrng); |
| |
| /** |
| * Initializes CSRNG instance with a new seed value. |
| * |
| * `seed_material` is used as specified in NIST SP 800-90Ar1 section |
| * 10.2.1.3.1. See `dif_csrng_entropy_src` for details on how this value |
| * is mixed with the CSRNG seed. |
| * |
| * `seed_material` can be NULL, in which case CSRNG will use a zero |
| * vector instead. |
| * |
| * @param csrng A CSRNG handle. |
| * @param entropy_src_enable Entropy source input enable. |
| * @param seed_material Seed initialization parameters. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_instantiate( |
| const dif_csrng_t *csrng, dif_csrng_entropy_src_toggle_t entropy_src_enable, |
| const dif_csrng_seed_material_t *seed_material); |
| |
| /** |
| * Reseeds CSRNG instance. |
| * |
| * When `seed_material.seed_material_len` is set to 0, only the entropy source |
| * seed is used to reseed the instance, otherwise it will be XOR'ed with the |
| * entropy source. |
| * |
| * @param csrng A CSRNG handle. |
| * @param seed_material Reseed parameters. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_reseed(const dif_csrng_t *csrng, |
| const dif_csrng_seed_material_t *seed_material); |
| |
| /** |
| * Updates CSRNG state. |
| * |
| * This function is similar to `dif_csrng_reseed()`, except: |
| * |
| * - Only `seed_material.seed_material` is used in the update operation. |
| * - The update operation does not reset the internal CSRNG reseed |
| * counter. |
| * |
| * @param csrng A CSRNG handle. |
| * @param seed_material Update parameters. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_update(const dif_csrng_t *csrng, |
| const dif_csrng_seed_material_t *seed_material); |
| |
| /** |
| * Requests cryptographic entropy bits from the CSRNG. |
| * |
| * The prediction resistance flag as specified in SP 800-90Ar1 section |
| * 10.2.1.1 is not directily supported by the hardware. It is the |
| * responsibility of the caller to reseed as needed before calling |
| * this function. |
| * |
| * The CSRNG accepts generation requests with 128-bit granularity, with |
| * a minimum 128-bit request size. This function will increase the size |
| * of the request to align it to the nearest 128-bit boundary. |
| * |
| * @param csrng A CSRNG handle. |
| * @param len Number of uint32_t words to generate. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_generate_start(const dif_csrng_t *csrng, size_t len); |
| |
| /** |
| * Reads the output of the last CSRNG generate call. |
| * |
| * This function reads `len` words out of the CSRNG. This function should be |
| * called repeatedly until the number of words requested in |
| * `dif_csrng_generate_start()` is exhausted. This function will block until |
| * `len` words are read. |
| * |
| * `dif_csrng_get_output_status()` can be called before this function to ensure |
| * there is data available in the CSRNG output buffer. |
| * |
| * @param csrng A CSRNG handle. |
| * @param[out] buf A buffer to fill with words from the pipeline. |
| * @param len The number of words to read into `buf`. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_generate_read(const dif_csrng_t *csrng, uint32_t *buf, |
| size_t len); |
| |
| /** |
| * Uninstantiates CSRNG |
| * |
| * Resets the CSRNG instance. Values in the CSRNG are zeroed out. This |
| * command effectively resets the CSRNG, clearing any errors that it |
| * may have encountered due to processing or entropy source errors. |
| * |
| * @param csrng An CSRNG handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_uninstantiate(const dif_csrng_t *csrng); |
| |
| /** |
| * Gets the current command interface status. |
| * |
| * This function can be called before or after any of the following functions: |
| * |
| * - `dif_csrng_instantiate()` |
| * - `dif_csrng_reseed()` |
| * - `dif_csrng_update()` |
| * - `dif_csrng_generate_start()` |
| * - `dif_csrng_uninstantiate()` |
| * |
| * @param csrng An CSRNG handle |
| * @param[out] status Command interface status. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_cmd_interface_status(const dif_csrng_t *csrng, |
| dif_csrng_cmd_status_t *status); |
| |
| /** |
| * Forces the status registers to indicate `fifo` as being in an unhealthy |
| * state. |
| * |
| * @param csrng An CSRNG handle |
| * @param fifo The FIFO to mark as unhealthy. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_cmd_force_unhealthy_fifo(const dif_csrng_t *csrng, |
| dif_csrng_fifo_t fifo); |
| |
| /** |
| * Forces the status registers to indicate a particular error cause. |
| * |
| * @param csrng An CSRNG handle |
| * @param error The error to force. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_cmd_force_error(const dif_csrng_t *csrng, |
| dif_csrng_error_t error); |
| |
| /** |
| * Returns an opaque blob indicating the main state machine's current state. |
| * |
| * @param csrng An CSRNG handle |
| * @param state[out] The state machine state as an opaque blob. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_main_state_machine(const dif_csrng_t *csrng, |
| uint32_t *state); |
| |
| /** |
| * Returns a bitset indicating which hardware CSRNGs have encountered |
| * exceptions. |
| * |
| * @param csrng An CSRNG handle |
| * @param exceptions[out] The bitset of exception states. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_hw_csrng_exceptions(const dif_csrng_t *csrng, |
| uint32_t *exceptions); |
| |
| /** |
| * Clears recorded hardware CSRNG exceptions. |
| * |
| * @param csrng An CSRNG handle |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_clear_hw_csrng_exceptions(const dif_csrng_t *csrng); |
| |
| /** |
| * Gets the current cryptographic entropy output data status. |
| * |
| * This function can be used before calling `dif_csrng_generate_read()` to |
| * check if there is data available to read. |
| * |
| * @param csrng A CSRNG handle. |
| * @param[out] status CSRNG output status. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_output_status(const dif_csrng_t *csrng, |
| dif_csrng_output_status_t *status); |
| |
| /** |
| * Gets the working state of a CSRNG instance. |
| * |
| * @param csrng A CSRNG handle |
| * @param instance_id CSRNG instance ID. |
| * @param[out] state The working state of a CSRNG instance. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_internal_state( |
| const dif_csrng_t *csrng, dif_csrng_internal_state_id_t instance_id, |
| dif_csrng_internal_state_t *state); |
| |
| /** |
| * Locks out CSRNG functionality. |
| * |
| * This function is reentrant: calling it while functionality is locked will |
| * have no effect and return `kDifCsrngOk`. |
| * |
| * @param csrng A CSRNG handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_lock(const dif_csrng_t *csrng); |
| |
| /** |
| * Checks whether this CSRNG is locked. |
| * |
| * @param csrng A CSRNG handle. |
| * @param[out] is_locked Out-param for the locked state. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_is_locked(const dif_csrng_t *csrng, bool *is_locked); |
| |
| /** |
| * Disables the CSRNG module. |
| * |
| * @param csrng A CSRNG handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_stop(const dif_csrng_t *csrng); |
| |
| /** |
| * Gets the recoverable alerts currently recorded in the CSRNG block. |
| * |
| * This function returns the alerts in a bitset whose indices are given by |
| * `dif_csrng_recoverable_alert_t`. |
| * |
| * @param csrng A CSRNG handle. |
| * @param[out] alerts Bitset of alerts currently recorded. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_get_recoverable_alerts(const dif_csrng_t *csrng, |
| uint32_t *alerts); |
| |
| /** |
| * Clears all recoverable alerts currently recorded in the CSRNG block. |
| * |
| * @param csrng A CSRNG handle. |
| * @return The result of the operation. |
| */ |
| OT_WARN_UNUSED_RESULT |
| dif_result_t dif_csrng_clear_recoverable_alerts(const dif_csrng_t *csrng); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif // __cplusplus |
| |
| #endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_CSRNG_H_ |