blob: 8f7e44538f30aeaee17792b85985e7c3792289e8 [file] [log] [blame]
// 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;
/**
* 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[12];
} 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_