blob: 8e2387fd5c83806029780fc8ef3453406875d12c [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_SRC_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ENTROPY_SRC_H_
/**
* @file
* @brief <a href="/hw/ip/entropy_src/doc/">Entropy Source</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_entropy_src_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
enum {
/**
* Maximum pre-conditioning FIFO capacity.
*/
// TODO: Synchronize value with hardware.
kDifEntropySrcFifoMaxCapacity = 64,
/**
* Default firmware observe FIFO threshold.
*
* Default value used to trigger the `kDifEntropySrcIrqEsObserveFifoReady`
* interrupt when enabled.
*/
kDifEntropyFifoIntDefaultThreshold = 32,
};
/**
* A statistical test on the bits emitted by an entropy source.
*/
typedef enum dif_entropy_src_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.
*/
kDifEntropySrcTestRepCount,
/**
* 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.
*/
kDifEntropySrcTestAdaptiveProportion,
/**
* A bucket test.
*
* This test looks for correlations between individual noise channels.
*/
kDifEntropySrcTestBucket,
/**
* A "Markov" test.
*
* This test looks for unexpected first-order temporal correlations
* between individual noise channels.
*/
kDifEntropySrcTestMarkov,
/**
* A firmware-driven "mailbox" test.
*
* This test allows firmware to inspect 2kbit blocks of entropy, and signal
* potential concerns to the hardware.
*/
kDifEntropySrcTestMailbox,
/**
* A vendor-specific test implemented externally to the IP.
*/
kDifEntropySrcTestVendorSpecific,
/** \internal */
kDifEntropySrcTestNumVariants,
} dif_entropy_src_test_t;
/**
* A mode of operation for the entropy source.
*/
typedef enum dif_entropy_src_mode {
/**
* Indicates that the source is disabled.
*/
kDifEntropySrcModeDisabled = 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.
*/
kDifEntropySrcModePtrng = 1,
} dif_entropy_src_mode_t;
/**
* A single-bit RNG mode, where only one bit is sampled.
*/
typedef enum dif_entropy_src_single_bit_mode {
/**
* Single-bit-mode, sampling the zeroth bit.
*/
kDifEntropySrcSingleBitMode0 = 0,
/**
* Single-bit-mode, sampling the first bit.
*/
kDifEntropySrcSingleBitMode1 = 1,
/**
* Single-bit-mode, sampling the second bit.
*/
kDifEntropySrcSingleBitMode2 = 2,
/**
* Single-bit-mode, sampling the third bit.
*/
kDifEntropySrcSingleBitMode3 = 3,
/**
* Indicates that single-bit-mode is disabled.
*/
kDifEntropySrcSingleBitModeDisabled = 4,
} dif_entropy_src_single_bit_mode_t;
/**
* Criteria used by various entropy source health tests to decide whether the
* test has failed.
*/
typedef struct dif_entropy_src_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_src_test_config_t;
/**
* Firmware override parameters for an entropy source.
*/
typedef struct dif_entropy_src_fw_override_config {
/**
* Enables firmware monitoring of the post-health test entropy via
* `dif_entropy_fifo_read()` calls.
*/
bool enable;
/**
* Enables fimrware to insert entropy bits back into the pre-coditioner block
* via `dif_entropy_fifo_write()` calls. This feature is useful when the
* firmware is required to implement additional health checks, and to perform
* known answer tests of the preconditioner function.
*
* This field requires `fw_override_enable` to be set.
*/
bool entropy_insert_enable;
/**
* This field sets the depth of the observe FIFO hardware buffer used when
* `fw_override_enable` is set to true.
*/
uint8_t buffer_threshold;
} dif_entropy_src_fw_override_config_t;
/**
* Runtime configuration for an entropy source.
*
* This struct describes runtime information for one-time configuration of the
* hardware.
*/
typedef struct dif_entropy_src_config {
/**
* The mode to configure the entropy source in.
*/
dif_entropy_src_mode_t mode;
/**
* Which health tests to enable.
*
* The variants of `dif_entropy_src_test` are used to index fields in this
* array.
*
* Note that the value at `kDifEntropySrcTestMailbox` is ignored, since this
* test is driven by the firmware, not the hardware.
*/
bool tests[kDifEntropySrcTestNumVariants];
/**
* 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_src_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_src_test_config_t test_config;
/**
* Configuration parameters for firmware override buffer.
*/
dif_entropy_src_fw_override_config_t fw_override;
} dif_entropy_src_config_t;
/**
* Revision information for an entropy source.
*
* The fields of this struct have an implementation-specific interpretation.
*/
typedef struct dif_entropy_src_revision {
uint8_t abi_revision;
uint8_t hw_revision;
uint8_t chip_type;
} dif_entropy_src_revision_t;
/**
* Statistics on entropy source health tests.
*/
typedef struct dif_entropy_src_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][kDifEntropySrcTestNumVariants];
/**
* 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_src_test.kDifEntropySrcTestRepCount` and
* `dif_entropy_src_test.kDifEntropySrcTestBucket` the first array element
* will be the number of fails, and the second will be zeroed.
*/
uint32_t fails[2][kDifEntropySrcTestNumVariants];
/**
* The number of alerts emitted by a particular test.
*
* This has the same layout as `fails`.
*/
uint8_t alerts[2][kDifEntropySrcTestNumVariants];
} dif_entropy_src_test_stats_t;
/**
* An entropy source alert type.
*/
typedef enum dif_entropy_src_alert {
/**
* Indicates that the health test criteria were not met.
*/
kDifEntropySrcAlert,
/**
* Indicates that an internal error occurred.
*/
kDifEntropySrcFatal,
} dif_entropy_src_alert_t;
/**
* Creates a new handle for entropy source.
*
* This function does not actuate the hardware.
*
* @param base_addr Hardware instantiation parameters.
* @param[out] entropy Out param for the initialized handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_init(mmio_region_t base_addr,
dif_entropy_src_t *entropy_src);
/**
* 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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_configure(const dif_entropy_src_t *entropy_src,
dif_entropy_src_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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_get_revision(const dif_entropy_src_t *entropy_src,
dif_entropy_src_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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_get_stats(const dif_entropy_src_t *entropy_src,
bool fips_mode,
dif_entropy_src_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 `kDifEntropySrcOk`.
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_lock(const dif_entropy_src_t *entropy_src);
/**
* 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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_is_locked(const dif_entropy_src_t *entropy_src,
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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_avail(const dif_entropy_src_t *entropy_src);
/**
* 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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_read(const dif_entropy_src_t *entropy_src,
uint32_t *word);
/**
* 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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_alert_force(const dif_entropy_src_t *entropy_src,
dif_entropy_src_alert_t alert);
/**
* Performs an override read from the entropy pipeline.
*
* Entropy source must be configured with firmware override mode enabled, and
* the `len` parameter must be strictly less than the FIFO threshold set in the
* firware override parameters.
*
* `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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_fifo_read(const dif_entropy_src_t *entropy_src,
uint32_t *buf, size_t len);
/**
* Performs an override write to the entropy pipeline.
*
* Entropy source must be configured with firmware override and insert mode
* enabled, otherwise the function will return
* `kDifBadArg`.
*
* @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.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_fifo_write(const dif_entropy_src_t *entropy_src,
const uint32_t *buf, size_t len);
/**
* Disables the entropy module
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_disable(const dif_entropy_src_t *entropy_src);
/**
* Get main entropy fsm idle status
*
* @param entropy An entropy source handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_entropy_src_get_idle(const dif_entropy_src_t *entropy_src);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_ENTROPY_SRC_H_