blob: 905ae615282b4afe08d1a1ea95327f9e6588637e [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_EDN_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_EDN_H_
/**
* @file
* @brief <a href="/hw/ip/edn/doc/">Entropy Distribution Network</a> Device
* Interface Functions
*
* This API implements the interface for the Entropy Distribution Network (EDN)
* hardware.
*
* There are two main modes of operation:
*
* - boot-time: EDN configures the associated CSRNG instance to fetch pre-FIPS
* entropy immediately at boot-time or after reset.
* - auto refresh: EDN sends reseed and generate commands to the associated
* CSRNG instance. The API allows the user to set the CSRNG instantiate,
* reseed and generate para meters, as well as the reseed frequency.
*/
#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_edn_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
enum {
/**
* Maximum seed material number of uint32_t words supported in CSRNG
* instantiate and seed commands.
*/
kDifEntropySeedMaterialMaxWordLen = 12,
};
enum {
/**
* Csrng commands
*/
kDifEdnCmdInstantiate = 1,
kDifEdnCmdReseed = 2,
kDifEdnCmdGenerate = 3
};
/**
* CSRNG seed material for instantiate, reseed and generate commands.
*/
typedef struct dif_edn_seed_material {
/**
* Number of uint32_t words in `data`. Up to
* `kDifEntropySeedMaterialMaxWordLen` words can be set to initialize or
* reseed the CSRNG. CSRNG will extend the `data` to zeros if the provided
* value is less than kDifEntropySeedMaterialMaxWordLen.
*/
size_t len;
/**
* Seed material used in CSRNG instantiate, reseed or generate call.
*/
uint32_t data[kDifEntropySeedMaterialMaxWordLen];
} dif_edn_seed_material_t;
/**
* CSRNG command parameters for instantiate, reseed and generate commands.
*/
typedef struct dif_edn_cmd {
/**
* The CSRNG application interface command header. For details, refer to the
* CSRNG documentation.
*/
uint32_t cmd;
/**
* Optional seed material.
*/
dif_edn_seed_material_t seed_material;
} dif_edn_cmd_t;
/**
* Auto-generate EDN module configuration parameters.
*/
typedef struct dif_edn_auto_params {
/**
* CSRNG instantiate command material.
*/
dif_edn_cmd_t instantiate_cmd;
/**
* CSRNG reseed command material.
*/
dif_edn_cmd_t reseed_cmd;
/**
* CSRNG generate command material.
*/
dif_edn_cmd_t generate_cmd;
/**
* Number of generate calls that can be made before a reseed request is made.
*/
uint32_t reseed_interval;
} dif_edn_auto_params_t;
/**
* EDN Status flags.
*/
typedef enum dif_edn_status {
/**
* Device is ready to receive a command.
*/
kDifEdnStatusReady,
/**
* Device has recieved an ACK from the CSRNG block.
*/
kDifEdnStatusCsrngAck,
} dif_edn_status_t;
/**
* Enumeration of EDN FIFOs, which indicates which part of the hardware
* produced an error.
*/
typedef enum dif_edn_fifo {
kDifEdnFifoReseedCmd,
kDifEdnFifoGenerateCmd,
} dif_edn_fifo_t;
/**
* Enumeration of EDN FIFO errors.
*/
typedef enum dif_edn_error {
/**
* Indicates an error in the command ack state machine.
*/
kDifEdnErrorAckSm,
/**
* Indicates an error in the main state machine.
*/
kDifEdnErrorMainSm,
/**
* Indicates an error in a hardened counter.
*/
kDifEdnErrorCounterFault,
/**
* Indicates a write to a full FIFO occured.
*/
kDifEdnErrorFifoWrite,
/**
* Indicates a read from an empty FIFO occured.
*/
kDifEdnErrorFifoRead,
/**
* Indicates a FIFO was somehow both full and empty.
*/
kDifEdnErrorFifoFullAndEmpty,
} dif_edn_error_t;
/**
* CSRNG consume seed from entropy source enable.
*/
typedef enum dif_edn_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.
*/
kDifEdnEntropySrcToggleDisable = 1,
/**
* Entropy source XOR'ed with the provided seed material.
*/
kDifEdnEntropySrcToggleEnable = 0,
} dif_edn_entropy_src_toggle_t;
/**
* Recoverable alerts emitted by the EDN.
*/
typedef enum dif_edn_recoverable_alert {
/**
* Indicates a bad value was written to the EDN_ENABLE field of the control
* register.
*/
kDifEdnRecoverableAlertBadEnable,
/**
* Indicates a bad value was written to the BOOT_REQ_MODE field of the control
* register.
*/
kDifEdnRecoverableAlertBadBootReqMode,
/**
* Indicates a bad value was written to the AUTO_REQ_MODE field of the
* control register.
*/
kDifEdnRecoverableAlertBadAutoReqMode,
/**
* Indicates a bad value was written to the CMD_FIFO_RST field of the
* control register.
*/
kDifEdnRecoverableAlertBadFifoClear,
/**
* Indicates the genbits bus saw two identical values, indicating a possible
* attack.
*/
kDifEdnRecoverableAlertRepeatedGenBits,
} dif_edn_recoverable_alert_t;
/**
* Configures EDN with runtime information.
*
* This function should need to be called once for the lifetime of `handle`.
*
* @param edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_configure(const dif_edn_t *edn);
/**
* Locks out EDN functionality.
*
* This function is reentrant: calling it while functionality is locked will
* have no effect and return `kDifEdnOk`.
*
* @param edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_lock(const dif_edn_t *edn);
/**
* Checks whether this EDN is locked.
*
* @param edn An EDN 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_edn_is_locked(const dif_edn_t *edn, bool *is_locked);
/**
* Enables the EDN in boot-time mode.
*
* Each call to this function should be sequenced with a call to
* `dif_edn_stop()`.
*
* @param edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_set_boot_mode(const dif_edn_t *edn);
/**
* Enables the EDN in auto refresh mode.
*
* Each call to this function should be sequenced with a call to
* `dif_edn_stop()`.
*
* @param edn An EDN handle.
* @param config Auto request configuration parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_set_auto_mode(const dif_edn_t *edn,
dif_edn_auto_params_t config);
/**
* Queries the EDN status flags.
*
* @param edn An EDN handle.
* @param flag Status flag to query.
* @param set Flag state (set/unset).
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_get_status(const dif_edn_t *edn, dif_edn_status_t flag,
bool *set);
/**
* Queries the EDN error flags.
*
* @param edn An EDN handle.
* @param[out] unhealthy_fifos Bitset of FIFOs in an unhealthy state; indices
* are `dif_edn_fifo_t`.
* @param[out] errors Bitset of errors relating to the above FIFOs; indices are
* `dif_edn_error_t`.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_get_errors(const dif_edn_t *edn, uint32_t *unhealthy_fifos,
uint32_t *errors);
/**
* Forces the status registers to indicate `fifo` as being in an unhealthy
* state.
*
* @param edn An EDN handle
* @param fifo The FIFO to mark as unhealthy.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_get_cmd_unhealthy_fifo_force(const dif_edn_t *edn,
dif_edn_fifo_t fifo);
/**
* Forces the status registers to indicate a particular error cause.
*
* @param edn An EDN handle
* @param error The error to force.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_get_cmd_error_force(const dif_edn_t *edn,
dif_edn_error_t error);
/**
* Returns an opaque blob indicating the main state machine's current state.
*
* @param csrng An EDN 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_edn_get_main_state_machine(const dif_edn_t *edn,
uint32_t *state);
/**
* 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.
*
* `seed_material` can be NULL, in which case CSRNG will use a zero
* vector instead.
*
* @param edn An EDN 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_edn_instantiate(
const dif_edn_t *edn, dif_edn_entropy_src_toggle_t entropy_src_enable,
const dif_edn_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 edn An EDN handle.
* @param seed_material Reseed parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_reseed(const dif_edn_t *edn,
const dif_edn_seed_material_t *seed_material);
/**
* Updates CSRNG state.
*
* This function is similar to `dif_edn_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 edn An EDN handle.
* @param seed_material Update parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_update(const dif_edn_t *edn,
const dif_edn_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 directly 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 edn An EDN handle.
* @param len Number of uint32_t words to generate.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_generate_start(const dif_edn_t *edn, 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 edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_uninstantiate(const dif_edn_t *edn);
/**
* Stops the current mode of operation and disables the entropy module.
*
* @param edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_stop(const dif_edn_t *edn);
/**
* Gets the recoverable alerts currently recorded in the EDN block.
*
* This function returns the alerts in a bitset whose indices are given by
* `dif_edn_recoverable_alert_t`.
*
* @param edn An EDN handle.
* @param[out] alerts Bitset of alerts currently recorded.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_get_recoverable_alerts(const dif_edn_t *edn,
uint32_t *alerts);
/**
* Clears all recoverable alerts currently recorded in the EDN block.
*
* @param edn An EDN handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_edn_clear_recoverable_alerts(const dif_edn_t *edn);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_EDN_H_