blob: 44fc894aed935070f13eac7aa78dd4f5d89a327c [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_ENTROPY_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ENTROPY_H_
/**
* @file
* @brief <a href="/hw/ip/entropy_src/doc/">Entropy Source</a> Device Interface
* Functions
*/
#include <stdint.h>
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_warn_unused_result.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
enum {
/**
* Maximum pre-conditioning FIFO capacity.
*/
// TODO: Synchronize value with hardware.
kDifEntropyFifoMaxCapacity = 64,
};
/**
* A toggle state: enabled, or disabled.
*
* This enum may be used instead of a `bool` when describing an enabled/disabled
* state.
*/
typedef enum dif_entropy_toggle {
/*
* The "enabled" state.
*/
kDifEntropyToggleEnabled,
/**
* The "disabled" state.
*/
kDifEntropyToggleDisabled,
} dif_entropy_toggle_t;
/**
* A statistical test on the bits emitted by an entropy source.
*/
typedef enum dif_entropy_test {
/**
* An SP 800-90B repetition count test.
*
* This test screens for stuck bits, or a total failure of the noise source.
* This test fails if any sequence of bits repeats too many times in a row
* for too many samples.
*/
kDifEntropyTestRepCount,
/**
* An SP 800-90B adaptive proportion test.
*
* This test screens for statistical bias in the number of ones or zeros
* output by the noise source.
*/
kDifEntropyTestAdaptiveProportion,
/**
* A bucket test.
*
* This test looks for correlations between individual noise channels.
*/
kDifEntropyTestBucket,
/**
* A "Markov" test.
*
* This test looks for unexpected first-order temporal correlations
* between individual noise channels.
*/
kDifEntropyTestMarkov,
/**
* A firmware-driven "mailbox" test.
*
* This test allows firmware to inspect 2kbit blocks of entropy, and signal
* potential concerns to the hardware.
*/
kDifEntropyTestMailbox,
/**
* A vendor-specific test implemented externally to the IP.
*/
kDifEntropyTestVendorSpecific,
/** \internal */
kDifEntropyTestNumVariants,
} dif_entropy_test_t;
/**
* A mode of operation for the entropy source.
*/
typedef enum dif_entropy_mode {
/**
* Indicates that the source is disabled.
*/
kDifEntropyModeDisabled = 0,
/**
* The physical true random number generator mode.
*
* This mode uses a physical random noise generator for operation, and is
* truly random. This noise generator is compatible with SP 800-90B.
*/
kDifEntropyModePtrng = 1,
/**
* The Linear Feedback Shift Register (LFSR) mode.
*
* This mode is digital, and as such is only pseudo-random and intended
* for test purposes only.
*
* In this mode, the `dif_entropy_config.lfsr_seed` value is used to
* initialize the internal state of the LFSR.
*/
kDifEntropyModeLfsr = 2,
} dif_entropy_mode_t;
/**
* A single-bit RNG mode, where only one bit is sampled.
*/
typedef enum dif_entropy_single_bit_mode {
/**
* Single-bit-mode, sampling the zeroth bit.
*/
kDifEntropySingleBitMode0 = 0,
/**
* Single-bit-mode, sampling the first bit.
*/
kDifEntropySingleBitMode1 = 1,
/**
* Single-bit-mode, sampling the second bit.
*/
kDifEntropySingleBitMode2 = 2,
/**
* Single-bit-mode, sampling the third bit.
*/
kDifEntropySingleBitMode3 = 3,
/**
* Indicates that single-bit-mode is disabled.
*/
kDifEntropySingleBitModeDisabled = 4,
} dif_entropy_single_bit_mode_t;
/**
* Criteria used by various entropy source health tests to decide whether the
* test has failed.
*/
typedef struct dif_entropy_test_config {
/**
* The size of the window to use for health tests, in bits.
*/
uint16_t health_test_window;
/**
* The threshold for the repetition count test.
*/
uint16_t rep_count_threshold;
/**
* The value range for the adaptive proportion test.
*
* The first value is the lower threshold; the second is the higher
* threshold.
*/
uint16_t adaptive_range[2];
/**
* The threshold for the bucket test.
*/
uint16_t bucket_threshold;
/**
* The range for the "Markov" test.
*
* The first value is the lower threshold; the second is the higher
* threshold.
*/
uint16_t markov_range[2];
/**
* The value range for the vendor-specific test.
*
* The first value is the lower threshold; the second is the higher
* threshold. However, vendors may interpret these values however they wish.
*/
uint16_t vendor_range[2];
} dif_entropy_test_config_t;
/**
* Hardware instantiation parameters for an entropy source.
*
* This struct describes information about the underlying hardware that is
* not determined until the hardware design is used as part of a top-level
* design.
*/
typedef struct dif_entropy_params {
/**
* The base address for the entropy source hardware registers.
*/
mmio_region_t base_addr;
} dif_entropy_params_t;
/**
* Runtime configuration for an entropy source.
*
* This struct describes runtime information for one-time configuration of the
* hardware.
*/
typedef struct dif_entropy_config {
/**
* The mode to configure the entropy source in.
*/
dif_entropy_mode_t mode;
/**
* Which health tests to enable.
*
* The variants of `dif_entropy_test` are used to index fields in this
* array.
*
* Note that the value at `kDifEntropyTestMailbox` is ignored, since this test
* is driven by the firmware, not the hardware.
*/
bool tests[kDifEntropyTestNumVariants];
/**
* If set, all health-test-related registers will be cleared.
*/
// TODO: Consider adding a separate setter for this config bit depending on
// hardware behavior.
bool reset_health_test_registers;
/**
* Specifies which single-bit-mode to use, if any at all.
*/
dif_entropy_single_bit_mode_t single_bit_mode;
/**
* If set, entropy will be routed to a firmware-visible register instead of
* being distributed to other hardware IPs.
*/
// Open Question: Make this its own function? Seems like something that would
// be toggled a lot.
bool route_to_firmware;
/**
* If set, FIPS compliant entropy will be generated by this module after being
* processed by an SP 800-90B compliant conditioning function.
*
* Software may opt for implementing FIPS mode of operation without hardware
* support by setting this field to false. In such case, software is
* responsible for implementing the conditioning function.
*/
bool fips_mode;
/**
* Configuration parameters for health tests.
*/
dif_entropy_test_config_t test_config;
/**
* The rate at which the entropy bits are generated, in clock cycles.
*/
uint16_t sample_rate;
/**
* Seed used to load into the LFSR initial state. The maximum allowable value
* is 15. See `dif_entropy_mode.kDifEntropyModeLfsr` for more details.
*/
uint16_t lfsr_seed;
} dif_entropy_config_t;
/**
* A handle to an entropy source.
*
* This type should be treated as opaque by users.
*/
typedef struct dif_entropy {
dif_entropy_params_t params;
} dif_entropy_t;
/**
* Revision information for an entropy source.
*
* The fields of this struct have an implementation-specific interpretation.
*/
typedef struct dif_entropy_revision {
uint8_t abi_revision;
uint8_t hw_revision;
uint8_t chip_type;
} dif_entropy_revision_t;
/**
* Statistics on entropy source health tests.
*/
typedef struct dif_entropy_test_stats {
/**
* Watermarks indicating where the value emitted by a particular test has
* ranged through; the low watermark is the lowest observed value, while the
* high watermark is the highest.
*
* Each pair of watermarks is presented as a range from lowest to highest.
*/
// TODO: Document behavior for repcnt and bucket tests.
uint16_t watermarks[2][kDifEntropyTestNumVariants];
/**
* The number of times a particular test has failed.
*
* For tests that ensure the value lies in a range (such as the "Markov"
* test), the array will contain the number of underflows and overflows of
* this range, respectively; for tests that only have an upper range, the
* first array element will be zeroed, and the second will be the number
* of fails.
*
* For `dif_entropy_test.kDifEntropyTestRepCount` and
* `dif_entropy_test.kDifEntropyTestBucket` the first array element will
* be the number of fails, and the second will be zeroed.
*/
uint32_t fails[2][kDifEntropyTestNumVariants];
/**
* The number of alerts emitted by a particular test.
*
* This has the same layout as `fails`.
*/
uint8_t alerts[2][kDifEntropyTestNumVariants];
} dif_entropy_test_stats_t;
/**
* The result of an entropy source operation.
*/
typedef enum dif_entropy_result {
/**
* Indicates that the operation succeeded.
*/
kDifEntropyOk = 0,
/**
* Indicates some unspecified failure.
*/
kDifEntropyError = 1,
/**
* Indicates that some parameter passed into a function failed a
* precondition.
*
* When this value is returned, no hardware operations occured.
*/
kDifEntropyBadArg = 2,
/**
* Indicates that this operation has been locked out, and can never
* succeed until hardware reset.
*/
kDifEntropyLocked = 3,
/**
* Indicates that entropy is not yet available for software consumption
*/
kDifEntropyDataUnAvailable = 4,
/**
* Indicates that entropy is not idle
*/
kDifEntropyNotIdle = 5,
} dif_entropy_result_t;
/**
* An entropy source interrupt request type.
*/
typedef enum dif_entropy_irq {
/**
* Indicates that bits of entropy are available to consume.
*/
kDifEntropyIrqAvailable,
/**
* Indicates that the health test has failed and the alert count has been
* met.
*/
kDifEntropyIrqUnhealthy,
/**
* Indicates that an internal error occured in the FIFO, or if an illegal
* state machine state is reached.
*/
kDifEntropyIrqFatalError,
} dif_entropy_irq_t;
/**
* A snapshot of the enablement state of the interrupts for an entropy source.
*
* This is an opaque type, to be used with the `dif_entropy_irq_disable_all()`
* and `dif_entropy_irq_restore_all()` functions.
*/
typedef uint32_t dif_entropy_irq_snapshot_t;
/**
* An entropy source alert type.
*/
typedef enum dif_entropy_alert {
/**
* Indicates that the health test criteria were not met.
*/
kDifEntropyAlert,
/**
* Indicates that an internal error occurred.
*/
kDifEntropyFatal,
} dif_entropy_alert_t;
/**
* Creates a new handle for entropy source.
*
* This function does not actuate the hardware.
*
* @param params Hardware instantiation parameters.
* @param[out] entropy Out param for the initialized handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_init(dif_entropy_params_t params,
dif_entropy_t *entropy);
/**
* Configures entropy source with runtime information.
*
* This function should need to be called once for the lifetime of `handle`.
*
* @param entropy An entropy source handle.
* @param config Runtime configuration parameters.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_configure(const dif_entropy_t *entropy,
dif_entropy_config_t config);
/**
* Queries the entropy source IP for its revision information.
*
* @param entropy An entropy source handle.
* @param[out] revision Out-param for revision data.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_get_revision(const dif_entropy_t *entropy,
dif_entropy_revision_t *revision);
/**
* Queries the entropy source for health statistics.
*
* Calling this function also clears the relevant status registers.
*
* @param entropy An entropy source handle.
* @param fips_mode The test mode to query statistics for.
* @param[out] stats Out-param for stats data.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_get_stats(const dif_entropy_t *entropy,
bool fips_mode,
dif_entropy_test_stats_t *stats);
/**
* Locks out entropy source functionality.
*
* This function is reentrant: calling it while functionality is locked will
* have no effect and return `kDifEntropyOk`.
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_lock(const dif_entropy_t *entropy);
/**
* Checks whether this entropy source is locked.
*
* @param entropy An entropy source handle.
* @param[out] is_locked Out-param for the locked state.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_is_locked(const dif_entropy_t *entropy,
bool *is_locked);
/**
* Checks to see if entropy is available for software consumption
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_avail(const dif_entropy_t *entropy);
/**
* Reads off a word of entropy from the entropy source.
*
* @param entropy An entropy source handle.
* @param[out] word Out-param for the entropy.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_read(const dif_entropy_t *entropy,
uint32_t *word);
/**
* Returns whether a particular interrupt is currently pending.
*
* @param entropy An entropy source handle.
* @param irq An interrupt type.
* @param[out] is_pending Out-param for whether the interrupt is pending.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_is_pending(const dif_entropy_t *entropy,
dif_entropy_irq_t irq,
bool *is_pending);
/**
* Acknowledges a particular interrupt, indicating to the hardware that it has
* been successfully serviced.
*
* @param entropy An entropy source handle.
* @param irq An interrupt type.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_acknowledge(const dif_entropy_t *entropy,
dif_entropy_irq_t irq);
/**
* Checks whether a particular interrupt is currently enabled or disabled.
*
* @param entropy An entropy source handle.
* @param irq An interrupt type.
* @param[out] state Out-param toggle state of the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_get_enabled(const dif_entropy_t *entropy,
dif_entropy_irq_t irq,
dif_entropy_toggle_t *state);
/**
* Sets whether a particular interrupt is currently enabled or disabled.
*
* @param entropy An entropy source handle.
* @param irq An interrupt type.
* @param state The new toggle state for the interrupt.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_set_enabled(const dif_entropy_t *entropy,
dif_entropy_irq_t irq,
dif_entropy_toggle_t state);
/**
* Forces a particular interrupt, causing it to be serviced as if hardware had
* asserted it.
*
* @param entropy An entropy source handle.
* @param irq An interrupt type.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_force(const dif_entropy_t *entropy,
dif_entropy_irq_t irq);
/**
* Disables all interrupts, optionally snapshotting all toggle state for later
* restoration.
*
* @param entropy An entropy source handle.
* @param[out] snapshot Out-param for the snapshot; may be `NULL`.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_disable_all(
const dif_entropy_t *entropy, dif_entropy_irq_snapshot_t *snapshot);
/**
* Restores interrupts from the given snapshot.
*
* This function can be used with `dif_entropy_irq_disable_all()` to temporary
* interrupt save-and-restore.
*
* @param entropy An entropy source handle.
* @param snapshot A snapshot to restore from.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_irq_restore_all(
const dif_entropy_t *entropy, const dif_entropy_irq_snapshot_t *snapshot);
/**
* Forces a particular alert, causing it to be emitted as if the hardware had
* done so.
*
* @param entropy An entropy source handle.
* @param alert An alert type.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_alert_force(const dif_entropy_t *entropy,
dif_entropy_alert_t alert);
/**
* Performs an override read from the entropy pipeline.
*
* This function pauses entropy flow out of the pre-conditioner FIFO and
* instead flows words into `buf`. Normal operation of the entropy pipeline
* will not resume until `dif_entropy_fifo_reconnect()` is called.
*
* `buf` may be `NULL`; in this case, reads will be discarded.
*
* @param entropy An entropy source 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.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_read(const dif_entropy_t *entropy,
uint32_t *buf, size_t len);
/**
* Performs an override write to the entropy pipeline.
*
* This function pauses entropy flow into the pre-conditioner FIFO and
* instead flows words out of `buf`. Normal operation of the entropy pipeline
* will not resume until `dif_entropy_fifo_reconnect()` is called.
*
* @param entropy An entropy source handle.
* @param buf A buffer to push words from into the pipeline.
* @param len The number of words to read from `buf`.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_write(const dif_entropy_t *entropy,
const uint32_t *buf, size_t len);
/**
* Gets the current number of entries in the pre-conditioner FIFO.
*
* This function pauses the flow through the FIFO.
*
* @param entropy An entropy source handle.
* @param[out] len The number of words in the FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_get_len(const dif_entropy_t *entropy,
uint8_t *len);
/**
* Gets the current capacity of the pre-conditioner FIFO.
*
* @param entropy An entropy source handle.
* @param[out] capacity The number of words of capacity in the FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_get_capacity(const dif_entropy_t *entropy,
uint8_t *capacity);
/**
* Sets the current capacity of the pre-conditioner FIFO.
*
* The `capacity` value must be less or equal to the physical capacity
* of the fifo, defined as `kDifEntropyFifoMaxCapacity`.
*
* @param entropy An entropy source handle.
* @param capacity The new capacity for the FIFO.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_set_capacity(const dif_entropy_t *entropy,
uint8_t capacity);
/**
* Reconnects the entropy pipeline after an operation that pauses it.
*
* This is a separate function call to avoid races between software and hardware
* when performing multiple such operations, such as getting the length followed
* by a read.
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_fifo_reconnect(const dif_entropy_t *entropy);
/**
* Disables the entropy module
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_disable(const dif_entropy_t *entropy);
/**
* Get main entropy fsm idle status
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
DIF_WARN_UNUSED_RESULT
dif_entropy_result_t dif_entropy_get_idle(const dif_entropy_t *entropy);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ENTROPY_H_