dif_edn.h

To use this DIF, include the following C header:

#include "/workspace/sw/device/lib/dif/dif_edn.h"

This header provides the following device interface functions:

Generated from dif_edn.h
// Copyright lowRISC contributors (OpenTitan project).
// 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 {
  /**
   * Maximum generate length supported in CSRNG generate commands.
   */
  kDifEntropySeedMaterialMaxGlen = 4095,
};

enum {
  /**
   * Maximum number of generate commands between reseed commands in
   * the EDN auto mode.
   */
  kDifMaxNumReqsBetweenReseeds = 0xffffffff,
};

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 {
  /**
   * SW command register is ready to receive the next word of a command.
   */
  kDifEdnStatusRegReady,
  /**
   * Device is ready to receive a command.
   */
  kDifEdnStatusReady,
  /**
   * Device has received an error from the CSRNG block.
   */
  kDifEdnStatusCsrngStatus,
  /**
   * Device has recieved an ACK from the CSRNG block.
   */
  kDifEdnStatusCsrngAck,
} dif_edn_status_t;

/**
 * EDN SM states as defined in the EDN state machine RTL.
 */
typedef enum dif_edn_sm_state {
  /**
   * Device is idle.
   */
  kDifEdnSmStateIdle = 193,
  /**
   * Boot mode: load the instantiate command.
   */
  kDifEdnSmStateBootLoadIns = 455,
  /**
   * Boot mode: wait for instantiate command ack.
   */
  kDifEdnSmStateBootInsAckWait = 121,
  /**
   * Boot mode: load the generate command.
   */
  kDifEdnSmStateBootLoadGen = 3,
  /**
   * Boot mode: wait for generate command ack.
   */
  kDifEdnSmStateBootGenAckWait = 119,
  /**
   * Boot mode: signal a done pulse.
   */
  kDifEdnSmStateBootPulse = 169,
  /**
   * Boot mode: stay in done state until reset.
   */
  kDifEdnSmStateBootDone = 240,
  /**
   * Boot mode: load the uninstantiate command.
   */
  kDifEdnSmStateBootLoadUni = 309,
  /**
   * Boot mode: wait for uninstantiate command ack.
   */
  kDifEdnSmStateBootUniAckWait = 44,
  /**
   * Auto mode: load the instantiate command.
   */
  kDifEdnSmStateAutoLoadIns = 444,
  /**
   * Auto mode: wait for first instantiate command ack.
   */
  kDifEdnSmStateAutoFirstAckWait = 419,
  /**
   * Auto mode: wait for instantiate command ack.
   */
  kDifEdnSmStateAutoAckWait = 146,
  /**
   * Auto mode: determine next command to be sent.
   */
  kDifEdnSmStateAutoDispatch = 353,
  /**
   * Auto mode: capture the gen fifo count.
   */
  kDifEdnSmStateAutoCaptGenCnt = 270,
  /**
   * Auto mode: send the generate command.
   */
  kDifEdnSmStateAutoSendGenCmd = 477,
  /**
   * Auto mode: capture the reseed fifo count.
   */
  kDifEdnSmStateAutoCaptReseedCnt = 191,
  /**
   * Auto mode: send the reseed command.
   */
  kDifEdnSmStateAutoSendReseedCmd = 106,
  /**
   * Sw port: no hw request mode.
   */
  kDifEdnSmStateSWPortMode = 149,
  /**
   * Stop accepting entropy from CSRNG.
   */
  kDifEdnSmStateRejectCsrngEntropy = 24,
  /**
   * Illegal state reached and hang.
   */
  kDifEdnSmStateError = 382,
} dif_edn_sm_state_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.
 * @return The result of the operation. KDifOutOfRange if the `len` parameter
 * results in a 128bit block level size greater than 0x800.
 */
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_