CC3XX: Refactor the TRNG module
* Avoid using a global context in the TRNG module itself
* Refactor the call flow of TRNG need to follow, as now
an explicit call to initialise the provided context has
to be done
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I1db5641484d6f9fcafd57a3469768d748a708abd
diff --git a/bl1/bl1_1/shared_lib/interface/bl1_random.h b/bl1/bl1_1/shared_lib/interface/bl1_random.h
index 73f249f..f5d3a76 100644
--- a/bl1/bl1_1/shared_lib/interface/bl1_random.h
+++ b/bl1/bl1_1/shared_lib/interface/bl1_random.h
@@ -56,7 +56,7 @@
*
* @return int32_t 0 on success
*/
-int32_t bl1_random_generate_noise_stateless(uint8_t *output, size_t output_size);
+int32_t bl1_random_generate_noise(uint8_t *output, size_t output_size);
#ifdef __cplusplus
}
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_entropy.h b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_entropy.h
index 4785cbe..d5a2652 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_entropy.h
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_entropy.h
@@ -20,7 +20,7 @@
#endif
/**
- * @brief Size of the sample produced by the underlying source of randomness in a
+ * @brief Size of the sample produced by the underlying noise source in a
* single reading
*/
#define CC3XX_ENTROPY_SIZE (CC3XX_TRNG_SAMPLE_SIZE)
@@ -37,6 +37,12 @@
*/
cc3xx_err_t cc3xx_lowlevel_entropy_get(uint32_t *entropy, size_t entropy_len);
+/**
+ * @brief Returns a generic pointer to the context of the underlying noise source
+ *
+ */
+void *cc3xx_lowlevel_entropy_get_noise_source_ctx(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_trng.h b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_trng.h
index e7fdcb2..3499030 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_trng.h
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_trng.h
@@ -48,7 +48,6 @@
/**
* @brief: Indicates that the autocorrelation test failed four times in a row.
* When AUTOCORR_ERR is set, TRNG ceases to function until next reset.
- *
*/
__PACKED_ENUM cc3xx_trng_autocorr_test_state {
CC3XX_TRNG_AUTOCORR_TEST_ACTIVE,
@@ -58,7 +57,6 @@
/**
* @brief: Indicates CRNGT in the TRNG test failed. Failure occurs when two
* consecutive blocks of 16 collected bits are equal.
- *
*/
__PACKED_ENUM cc3xx_trng_crngt_test_state {
CC3XX_TRNG_CRNGT_TEST_ACTIVE,
@@ -68,27 +66,15 @@
/**
* @brief: Indicates von Neumann balancer error. Error in von Neumann balancer
* occurs if all 32 of the consecutive collected bits are identical.
- *
*/
__PACKED_ENUM cc3xx_trng_vnc_test_state {
CC3XX_TRNG_VNC_TEST_ACTIVE,
CC3XX_TRNG_VNC_TEST_BYPASS
};
-#ifdef CC3XX_CONFIG_TRNG_COLLECT_STATISTCS
-struct cc3xx_trng_stats {
- size_t autocorr_err_stats;
- size_t crngt_err_stats;
- size_t vnc_err_stats;
-};
-#endif /* CC3XX_CONFIG_TRNG_COLLECT_STATISTCS */
-
/**
* @brief The type describes the IDs of the available ring oscillators (ROSCs) from
* which entropy can be generated.
- *
- * @note If an external TRNG is used then these defines do not apply
- *
*/
__PACKED_ENUM cc3xx_rng_rosc_id_t {
CC3XX_RNG_ROSC_ID_0 = 0, /*!< ROSC ID 0 */
@@ -97,8 +83,41 @@
CC3XX_RNG_ROSC_ID_3 = 3, /*!< ROSC ID 3 */
};
+/**
+ * @brief The ROSC config holds the parameters for a ring oscillator (ROSC) from
+ * which entropy is collected by consecutive sampling. It holds the ID of
+ * the ROSC from which to sample and the interval in number of cycles for
+ * consecutive samples
+ */
+struct rosc_config_t {
+ uint32_t subsampling_rate; /*!< Number of rng_clk cycles between consecutive
+ ROSC samples */
+ enum cc3xx_rng_rosc_id_t id; /*!< Selected ring oscillator (ROSC) */
+};
+
+/**
+ * @brief Context associated to a TRNG mode of operation. Default values are set at
+ * context initialisation time through \a cc3xx_lowlevel_trng_init_context,
+ * but can be overridden by calling \a cc3xx_lowlevel_trng_set_context
+ */
+struct cc3xx_trng_ctx_t {
+ bool is_config_valid; /*!< Indicates whether the contents are a valid config */
+ uint32_t debug_control; /*!< The TRNG_DEBUG_CONTROL register configuration */
+ struct rosc_config_t rosc; /*!< The Ring OSCillator configuration */
+};
+
#ifdef CC3XX_CONFIG_TRNG_COLLECT_STATISTCS
/**
+ * @brief Structure keeping track of the error statistics observed since last clearing
+ *
+ */
+struct cc3xx_trng_stats {
+ size_t autocorr_err_stats; /*!< AUTOCORR test failures */
+ size_t crngt_err_stats; /*!< CRNGT test failures */
+ size_t vnc_err_stats; /*!< VNC test failures */
+};
+
+/**
* @brief Gets the TRNG error counters
*
* @param[in] stats statistics structure to be populated with current error counters.
@@ -113,85 +132,93 @@
void cc3xx_lowlevel_trng_clear_stats(void);
#endif /* CC3XX_CONFIG_TRNG_COLLECT_STATISTCS */
+static inline bool is_context_valid(struct cc3xx_trng_ctx_t *ctx) {
+ return ctx && ctx->is_config_valid;
+}
+/**
+ * @brief Macro that checks if the \ref cc3xx_trng_ctx_t context has valid contents
+ *
+ */
+#define CC3XX_IS_TRNG_CONTEXT_VALID(ctx) is_context_valid(ctx)
+
+/**
+ * @brief Initialises the provided context to valid values. It must be
+ * called before calling any other API
+ *
+ * @param[out] ctx Pointer to the context of the TRNG to set in SP800-90B mode
+ *
+ */
+void cc3xx_lowlevel_trng_context_init(struct cc3xx_trng_ctx_t *ctx);
+
/**
* @brief SP800-90B section 4.4 recommends two continuous health tests
* to be performed at startup and during normal operation of the
* noise source to verify the quality ot the entropy bits produced,
* namely the Repetition Count Test (4.4.1) and Adaptive Proportion
- * Test (4.4.2)
+ * Test (4.4.2). This API enables that mode of operation
*
- * @param[in] enable Set to \a true to put the TRNG in SP800-90B compatible mode, i.e.
- * disables the AUTOCORR tests and VNC balancer tests performed by
+ * @note It configures the context to disable the AUTOCORR tests and VNC
+ * balancer tests performed by the hardware
+ *
+ * @param[in, out] ctx Pointer to the context of the TRNG to set in SP800-90B mode
+ * @param[in] enable Set to \a true to put the the context in SP800-90B compatible mode,
+ * i.e. disables the AUTOCORR tests and VNC balancer tests performed by
* the hardware
*/
-void cc3xx_lowlevel_trng_sp800_90b_mode(bool enable);
+void cc3xx_lowlevel_trng_sp800_90b_mode(struct cc3xx_trng_ctx_t *ctx);
/**
- * @brief Sets the global configuration (ROSC_ID, subsampling rate) for
+ * @brief Sets the TRNG configuration on the provided context for
* the usage of the TRNG by the other APIs used by this
* module. If this is not called, default parameters
- * defined at build time will be used, i.e.
- * (CC3XX_CONFIG_RNG_RING_OSCILLATOR_ID,
- * CC3XX_CONFIG_RNG_SUBSAMPLING_RATE)
+ * defined at initialisation time will be used, i.e.
+ * \a CC3XX_CONFIG_RNG_RING_OSCILLATOR_ID and
+ * \a CC3XX_CONFIG_RNG_SUBSAMPLING_RATE
*
- * @param[in] rosc_id ROSC ID to be used, a number between 0 and 3
- * @param[in] subsampling_rate Specifies the number of rng_clk cycles between collection
+ * @param[out] ctx Pointer to the context on which to set the configuration
+ * @param[in] rosc_id ROSC ID to be used, a number between 0 and 3
+ * @param[in] subsampling_rate Specifies the number of rng_clk cycles between collection
* of consecutive samples of the selected ring oscillator
*
* @return cc3xx_err_t CC3XX_ERR_SUCCESS on success, or
* CC3XX_ERR_RNG_INVALID_TRNG_CONFIG if invalid parameters
* are passed
*/
-cc3xx_err_t cc3xx_lowlevel_trng_set_config(enum cc3xx_rng_rosc_id_t rosc_id, uint32_t subsampling_rate);
-
-/**
- * @brief Validates the global configuration of the TRNG
- *
- * @return cc3xx_err_t CC3XX_ERR_SUCCESS on success, or CC3XX_ERR_RNG_INVALID_TRNG_CONFIG if
- * an invalid configuration is detected
- */
-cc3xx_err_t cc3xx_lowlevel_trng_validate_config(void);
+cc3xx_err_t cc3xx_lowlevel_trng_set_config(
+ struct cc3xx_trng_ctx_t *ctx,
+ enum cc3xx_rng_rosc_id_t rosc_id,
+ uint32_t subsampling_rate);
/**
* @brief Sets the TRNG_DEBUG_CONTROL register to bypass mode for the
* respective HW tests, in the global configuration (state) structure
*
- * @param[in] autocorr_state Set to \a CC3XX_TRNG_AUTOCORR_TEST_BYPASS to bypass the AUTOCORR test
- * @param[in] crngt_state Set to \a CC3XX_TRNG_CRNGT_TEST_BYPASS to bypass the CRNGT test
- * @param[in] vnc_state Set to \a CC3XX_TRNG_VNC_TEST_BYPASS to bypass the VNC test
+ * @param[out] ctx Pointer to the context on which to set the hardware bypasses
+ * @param[in] autocorr_state Set to \a CC3XX_TRNG_AUTOCORR_TEST_BYPASS to bypass the AUTOCORR test
+ * @param[in] crngt_state Set to \a CC3XX_TRNG_CRNGT_TEST_BYPASS to bypass the CRNGT test
+ * @param[in] vnc_state Set to \a CC3XX_TRNG_VNC_TEST_BYPASS to bypass the VNC test
*
*/
void cc3xx_lowlevel_trng_set_hw_test_bypass(
+ struct cc3xx_trng_ctx_t *ctx,
enum cc3xx_trng_autocorr_test_state autocorr_state,
enum cc3xx_trng_crngt_test_state crngt_state,
enum cc3xx_trng_vnc_test_state vnc_state);
/**
- * @brief Reads the sample out of the TRNG, without accessing the global config state
+ * @brief Initialises the TRNG before a call to \a cc3xx_lowlevel_trng_get_sample. It requires
+ * a pointer to a context to be passed in
*
- * @param[out] buf Output buffer, word aligned, into which the sample is read
- * @param[in] word_count Size in words of the \p buf output buffer, must be equal to
- * the number of words of P_CC3XX->rng.ehr_data, i.e. CC3XX_TRNG_SAMPLE_SIZE
- * when expressed in bytes
+ * @param[in, out] ctx Pointer to the context to use for the initialisation
*
- * @note If the ROSC ID or the subsampling rate get bumped during a reading, the new
- * values won't be saved in the global config. This function does not access
- * any global config or state so it is safe to use when globals are not set up.
- * HW tests are not bypassed when this function is used
- *
- * @note This is a one-shot function, unlike the \a cc3xx_lowlevel_trng_get_sample
- * which requires separate calls to \a cc3xx_lowlevel_trng_init first, and
- * \a cc3xx_lowlevel_trng_finish afterwards
- *
- * @return cc3xx_err_t CC3XX_ERR_SUCCESS on success, CC3XX_ERR_RNG_TOO_MANY_ATTEMPTS in
- * case errors have been detected on each generation. The maximum
- * number of generations is controlled by CC3XX_CONFIG_RNG_MAX_ATTEMPTS
+ * @return cc3xx_err_t CC3XX_ERR_SUCCESS
*/
-cc3xx_err_t cc3xx_lowlevel_trng_get_sample_stateless(uint32_t *buf, size_t word_count);
+cc3xx_err_t cc3xx_lowlevel_trng_init(struct cc3xx_trng_ctx_t *ctx);
/**
* @brief Reads the sample out of the TRNG
*
+ * @param[in, out] ctx Pointer to the context to use for the reading
* @param[out] buf Output buffer, word aligned, into which the sample is read
* @param[in] word_count Size in words of the \p buf output buffer, must be equal to
* the number of words of P_CC3XX->rng.ehr_data, i.e. CC3XX_TRNG_SAMPLE_SIZE
@@ -204,14 +231,7 @@
* case errors have been detected on each generation. The maximum
* number of generations is controlled by CC3XX_CONFIG_RNG_MAX_ATTEMPTS
*/
-cc3xx_err_t cc3xx_lowlevel_trng_get_sample(uint32_t *buf, size_t word_count);
-
-/**
- * @brief Initialises the TRNG before a call to \a cc3xx_lowlevel_trng_get_sample
- *
- * @return cc3xx_err_t CC3XX_ERR_SUCCESS
- */
-cc3xx_err_t cc3xx_lowlevel_trng_init(void);
+cc3xx_err_t cc3xx_lowlevel_trng_get_sample(struct cc3xx_trng_ctx_t *ctx, uint32_t *buf, size_t word_count);
/**
* @brief De-initialises the TRNG by disabling the random source and the clock
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_entropy.c b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_entropy.c
index 9bbb8cf..7fa7a77 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_entropy.c
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_entropy.c
@@ -68,6 +68,14 @@
*/
#define SP800_90B_REPETITION_COUNT_CUTOFF_RATE (81UL)
+/* Static context of the TRNG config used by the entropy module itself */
+static struct cc3xx_trng_ctx_t g_trng_ctx = {0};
+
+void *cc3xx_lowlevel_entropy_get_noise_source_ctx(void)
+{
+ return (void *)&g_trng_ctx;
+}
+
/* Static context of the entropy source continuous health tests */
static struct health_tests_ctx_t {
size_t total_bits_count; /*!< Number of total bits observed for the Adaptive Proportion Test window */
@@ -191,7 +199,7 @@
/* Collects 528 sample bytes on startup for testing */
for (size_t i = 0; i < 22; i++) {
- err = cc3xx_lowlevel_trng_get_sample(random_bits, entropy_byte_size / sizeof(uint32_t));
+ err = cc3xx_lowlevel_trng_get_sample(&g_trng_ctx, random_bits, entropy_byte_size / sizeof(uint32_t));
if (err != CC3XX_ERR_SUCCESS) {
break;
}
@@ -207,16 +215,18 @@
assert((entropy_len % CC3XX_TRNG_SAMPLE_SIZE) == 0);
- err = cc3xx_lowlevel_trng_validate_config();
+ if (!CC3XX_IS_TRNG_CONTEXT_VALID(&g_trng_ctx)) {
+ cc3xx_lowlevel_trng_context_init(&g_trng_ctx);
+ }
+
+ err = cc3xx_lowlevel_trng_init(&g_trng_ctx);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
- cc3xx_lowlevel_trng_init();
-
if (!g_entropy_tests.startup_done) {
/* Perform any required configuration on the TRNG first */
- cc3xx_lowlevel_trng_sp800_90b_mode(true);
+ cc3xx_lowlevel_trng_sp800_90b_mode(&g_trng_ctx);
/* Perform the extensive collection on startup */
err = startup_test(CC3XX_TRNG_SAMPLE_SIZE);
if (err != CC3XX_ERR_SUCCESS) {
@@ -227,7 +237,7 @@
for (size_t i = 0; i < entropy_len / CC3XX_TRNG_SAMPLE_SIZE; i++) {
- err = cc3xx_lowlevel_trng_get_sample(&entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t));
+ err = cc3xx_lowlevel_trng_get_sample(&g_trng_ctx, &entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t));
if (err != CC3XX_ERR_SUCCESS) {
goto cleanup;
}
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_trng.c b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_trng.c
index b8752f9..e63f76f 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_trng.c
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_trng.c
@@ -51,32 +51,6 @@
#define TRNG_DONE_MASK (1U << EHR_VALID_INT)
#endif /* CC3XX_CONFIG_TRNG_DMA */
-/**
- * @brief The ROSC config holds the parameters for a ring oscillator (ROSC) from
- * which entropy is collected by consecutive sampling. It holds the ID of
- * the ROSC from which to sample and the interval in number of cycles for
- * consecutive samples
- */
-struct rosc_config_t {
- uint32_t subsampling_rate; /*!< Number of rng_clk cycles between consecutive
- ROSC samples */
- enum cc3xx_rng_rosc_id_t id; /*!< Selected ring oscillator (ROSC) */
-};
-
-/**
- * @brief Object describing a TRNG configuration. Default values are set at
- * build time, but can be overridden by calling \a cc3xx_lowlevel_rng_set_config
- * for the ROSC config, and \a cc3xx_lowlevel_rng_set_debug_control to set
- * the \a TRNG_DEBUG_CONTROL.
- */
-static struct {
- struct rosc_config_t rosc; /*!< The Ring OSCillator configuration */
- uint32_t debug_control; /*!< The TRNG_DEBUG_CONTROL configuration */
-} g_trng_config = {
- .rosc.subsampling_rate = CC3XX_CONFIG_RNG_SUBSAMPLING_RATE,
- .rosc.id = CC3XX_CONFIG_RNG_RING_OSCILLATOR_ID,
- .debug_control = 0x0UL};
-
#ifdef CC3XX_CONFIG_TRNG_COLLECT_STATISTCS
/**
* @brief When \a CC3XX_CONFIG_TRNG_COLLECT_STATISTICS is set,
@@ -158,12 +132,12 @@
}
#ifdef CC3XX_CONFIG_TRNG_DMA
-static void trng_init_dma(size_t sample_count)
+static void trng_init_dma(struct cc3xx_trng_ctx_t *ctx, size_t sample_count)
{
- /* Fill the RNG SRAM with entropy */
+ /* Fill the RNG SRAM with entropy */
P_CC3XX->rng.rng_dma_samples_num = sample_count;
P_CC3XX->rng.rng_dma_sram_addr = 0x0U;
- P_CC3XX->rng.rng_dma_src_mask = 0x1U << g_trng_config.rosc.id;
+ P_CC3XX->rng.rng_dma_src_mask = 0x1U << ctx->rosc.id;
P_CC3XX->rng.rng_dma_enable = 0x1U;
}
@@ -190,7 +164,7 @@
return (product > UINT32_MAX) ? UINT32_MAX : (uint32_t)product;
}
-static void trng_bump_rosc_id_and_subsampling_rate(bool stateless)
+static void trng_bump_rosc_id_and_subsampling_rate(struct cc3xx_trng_ctx_t *ctx)
{
uint32_t rosc_id = P_CC3XX->rng.trng_config & 0b11;
uint32_t rosc_subsampling_rate = P_CC3XX->rng.sample_cnt1;
@@ -212,13 +186,12 @@
P_CC3XX->rng.trng_config = rosc_id | (0x1U << 2);
P_CC3XX->rng.sample_cnt1 = rosc_subsampling_rate;
- if (!stateless) {
- g_trng_config.rosc.id = rosc_id;
- g_trng_config.rosc.subsampling_rate = rosc_subsampling_rate;
- }
+ /* Update the context */
+ ctx->rosc.id = rosc_id;
+ ctx->rosc.subsampling_rate = rosc_subsampling_rate;
}
-static bool trng_error_handler(bool stateless)
+static bool trng_error_handler(struct cc3xx_trng_ctx_t *ctx)
{
uint32_t trng_errors = trng_get_errors();
#ifdef CC3XX_CONFIG_TRNG_DMA
@@ -251,22 +224,22 @@
P_CC3XX->rng.rng_icr = 0xFFFFFFFF;
/* Bump the rosc id and subsampling rate */
- trng_bump_rosc_id_and_subsampling_rate(stateless);
+ trng_bump_rosc_id_and_subsampling_rate(ctx);
/* Restart TRNG */
trng_init(
- P_CC3XX->rng.trng_config & 0b11,
+ P_CC3XX->rng.trng_config & 0b11, /* Extract the ROSC_ID from the register */
P_CC3XX->rng.sample_cnt1,
P_CC3XX->rng.trng_debug_control);
#ifdef CC3XX_CONFIG_TRNG_DMA
- trng_init_dma(dma_samples_num);
+ trng_init_dma(ctx, dma_samples_num);
#endif
return true;
}
-static cc3xx_err_t trng_wait_for_sample(bool stateless)
+static cc3xx_err_t trng_wait_for_sample(struct cc3xx_trng_ctx_t *ctx)
{
uint32_t attempt_count = 0;
@@ -275,7 +248,7 @@
* failed.
*/
do {
- if (trng_error_handler(stateless)) {
+ if (trng_error_handler(ctx)) {
attempt_count++;
}
} while (!is_trng_done() && attempt_count < CC3XX_CONFIG_RNG_MAX_ATTEMPTS);
@@ -297,29 +270,22 @@
return CC3XX_ERR_SUCCESS;
}
-static cc3xx_err_t trng_get_sample(uint32_t *entropy, size_t word_count, bool stateless)
+static cc3xx_err_t trng_get_sample(struct cc3xx_trng_ctx_t *ctx, uint32_t *entropy, size_t word_count)
{
cc3xx_err_t err;
- if (!stateless) {
- if (!g_trng_config.rosc.subsampling_rate) {
- FATAL_ERR(CC3XX_ERR_RNG_INVALID_TRNG_CONFIG);
- return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
- }
- }
-
#ifdef CC3XX_CONFIG_TRNG_DMA
size_t dma_samples_num = ROUND_UP(word_count, CC3XX_TRNG_WORDS_PER_SAMPLE) /
CC3XX_TRNG_WORDS_PER_SAMPLE;
assert(word_count <= CC3XX_TRNG_SRAM_MAX_WORDS);
- trng_init_dma(dma_samples_num);
+ trng_init_dma(ctx, dma_samples_num);
#else
assert(word_count == CC3XX_TRNG_WORDS_PER_SAMPLE);
#endif /* CC3XX_CONFIG_TRNG_DMA */
- err = trng_wait_for_sample(stateless);
+ err = trng_wait_for_sample(ctx);
if (err != CC3XX_ERR_SUCCESS) {
return err;
}
@@ -333,13 +299,30 @@
/*!
* \defgroup cc3xx_trng Set of functions implementing the API to access the TRNG
* for reading random bits
- *
*/
/*!@{*/
-cc3xx_err_t cc3xx_lowlevel_trng_init(void)
+void cc3xx_lowlevel_trng_context_init(struct cc3xx_trng_ctx_t *ctx)
{
#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
- trng_init(g_trng_config.rosc.id, g_trng_config.rosc.subsampling_rate, g_trng_config.debug_control);
+ assert(ctx != NULL);
+
+ *ctx = (struct cc3xx_trng_ctx_t){
+ .is_config_valid = true,
+ .rosc.id = CC3XX_CONFIG_RNG_RING_OSCILLATOR_ID,
+ .rosc.subsampling_rate = CC3XX_CONFIG_RNG_SUBSAMPLING_RATE,
+ .debug_control = 0x0UL
+ };
+#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
+}
+
+cc3xx_err_t cc3xx_lowlevel_trng_init(struct cc3xx_trng_ctx_t *ctx)
+{
+#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
+ assert(ctx != NULL);
+ if (!(ctx->is_config_valid)) {
+ return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
+ }
+ trng_init(ctx->rosc.id, ctx->rosc.subsampling_rate, ctx->debug_control);
#else
trng_init();
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
@@ -353,44 +336,24 @@
return CC3XX_ERR_SUCCESS;
}
-cc3xx_err_t cc3xx_lowlevel_trng_get_sample_stateless(uint32_t *buf, size_t word_count)
-{
- cc3xx_err_t err;
-#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
- const bool stateless = true;
-
- /* In stateless mode do not set any TRNG test bypass */
- trng_init(CC3XX_CONFIG_RNG_RING_OSCILLATOR_ID, CC3XX_CONFIG_RNG_SUBSAMPLING_RATE, 0x0);
- err = trng_get_sample(buf, word_count, stateless);
-#else
- trng_init();
- err = trng_get_random(buf, word_count);
-#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
- if (err != CC3XX_ERR_SUCCESS) {
- return err;
- }
- trng_finish();
- return err;
-}
-
-cc3xx_err_t cc3xx_lowlevel_trng_get_sample(uint32_t *buf, size_t word_count)
+cc3xx_err_t cc3xx_lowlevel_trng_get_sample(struct cc3xx_trng_ctx_t *ctx, uint32_t *buf, size_t word_count)
{
#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
- const bool stateless = false;
- /* Unless called from the _stateless APIs, the get_sample will update
- * the global config of the TRNG, i.e. to retain state for future calls
- */
- return trng_get_sample(buf, word_count, stateless);
+ assert(ctx != NULL);
+ return trng_get_sample(ctx, buf, word_count);
#else
return trng_get_random(buf, word_count);
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
}
cc3xx_err_t cc3xx_lowlevel_trng_set_config(
+ struct cc3xx_trng_ctx_t *ctx,
enum cc3xx_rng_rosc_id_t rosc_id,
uint32_t subsampling_rate)
{
#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
+ assert(ctx != NULL);
+
if (!((rosc_id >= CC3XX_RNG_ROSC_ID_0) && (rosc_id <= CC3XX_RNG_ROSC_ID_3))) {
FATAL_ERR(CC3XX_ERR_RNG_INVALID_TRNG_CONFIG);
return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
@@ -401,8 +364,8 @@
return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
}
- g_trng_config.rosc.id = rosc_id;
- g_trng_config.rosc.subsampling_rate = subsampling_rate;
+ ctx->rosc.id = rosc_id;
+ ctx->rosc.subsampling_rate = subsampling_rate;
return CC3XX_ERR_SUCCESS;
#else
@@ -410,40 +373,22 @@
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
}
-cc3xx_err_t cc3xx_lowlevel_trng_validate_config(void)
+void cc3xx_lowlevel_trng_sp800_90b_mode(struct cc3xx_trng_ctx_t *ctx)
{
#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
- if (!g_trng_config.rosc.subsampling_rate) {
- FATAL_ERR(CC3XX_ERR_RNG_INVALID_TRNG_CONFIG);
- return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
- }
-
- if (!((g_trng_config.rosc.id >= CC3XX_RNG_ROSC_ID_0) &&
- (g_trng_config.rosc.id <= CC3XX_RNG_ROSC_ID_3))) {
- FATAL_ERR(CC3XX_ERR_RNG_INVALID_TRNG_CONFIG);
- return CC3XX_ERR_RNG_INVALID_TRNG_CONFIG;
- }
-
- return CC3XX_ERR_SUCCESS;
-#else
- return CC3XX_ERR_NOT_IMPLEMENTED;
-#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
-}
-
-void cc3xx_lowlevel_trng_sp800_90b_mode(bool enable)
-{
-#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
- if (enable) {
- cc3xx_lowlevel_trng_set_hw_test_bypass(true, false, true);
- }
+ cc3xx_lowlevel_trng_set_hw_test_bypass(ctx,
+ CC3XX_TRNG_AUTOCORR_TEST_BYPASS, CC3XX_TRNG_CRNGT_TEST_ACTIVE, CC3XX_TRNG_VNC_TEST_BYPASS);
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
}
void cc3xx_lowlevel_trng_set_hw_test_bypass(
+ struct cc3xx_trng_ctx_t *ctx,
enum cc3xx_trng_autocorr_test_state autocorr_state,
enum cc3xx_trng_crngt_test_state crngt_state,
enum cc3xx_trng_vnc_test_state vnc_state)
{
+ assert(ctx != NULL);
+
#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
uint32_t hw_entropy_tests_control = 0x0UL;
@@ -454,7 +399,7 @@
hw_entropy_tests_control |=
(vnc_state == CC3XX_TRNG_VNC_TEST_BYPASS) ? (1UL << 1) : 0x0UL;
- g_trng_config.debug_control = hw_entropy_tests_control;
+ ctx->debug_control = hw_entropy_tests_control;
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
}
diff --git a/platform/ext/target/arm/rse/common/bl1/cc3xx/cc3xx_rom_random.c b/platform/ext/target/arm/rse/common/bl1/cc3xx/cc3xx_rom_random.c
index 3c23099..8f3217d 100644
--- a/platform/ext/target/arm/rse/common/bl1/cc3xx/cc3xx_rom_random.c
+++ b/platform/ext/target/arm/rse/common/bl1/cc3xx/cc3xx_rom_random.c
@@ -20,19 +20,29 @@
return cc3xx_lowlevel_rng_get_random(output, output_size, CC3XX_RNG_LFSR);
}
-int32_t bl1_random_generate_noise_stateless(uint8_t *output, size_t output_size)
+int32_t bl1_random_generate_noise(uint8_t *output, size_t output_size)
{
uint32_t buf[CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t)];
cc3xx_err_t err;
- size_t counter = 0;
- for (counter = 0; counter < output_size; counter++) {
+ struct cc3xx_trng_ctx_t ctx = {0};
+ cc3xx_lowlevel_trng_context_init(&ctx);
+
+ err = cc3xx_lowlevel_trng_init(&ctx);
+ if (err != CC3XX_ERR_SUCCESS) {
+ return (int32_t)err;
+ }
+
+ for (size_t counter = 0; counter < output_size; counter++) {
if ((counter % CC3XX_TRNG_SAMPLE_SIZE) == 0) {
do {
- err = cc3xx_lowlevel_trng_get_sample_stateless(buf, sizeof(buf) / sizeof(uint32_t));
+ err = cc3xx_lowlevel_trng_get_sample(&ctx, buf, sizeof(buf) / sizeof(uint32_t));
} while (err != CC3XX_ERR_SUCCESS);
}
output[counter] = ((uint8_t *)buf)[counter];
}
+
+ cc3xx_lowlevel_trng_finish();
+
return 0;
}
diff --git a/platform/ext/target/arm/rse/common/device/source/startup_rse_bl1_1.c b/platform/ext/target/arm/rse/common/device/source/startup_rse_bl1_1.c
index c45ebc1..455c673 100644
--- a/platform/ext/target/arm/rse/common/device/source/startup_rse_bl1_1.c
+++ b/platform/ext/target/arm/rse/common/device/source/startup_rse_bl1_1.c
@@ -234,13 +234,13 @@
stdio_is_initialized_reset();
- /* generate a random word to clear secret values */
+ /* generate a random word to clear secret values */
bl1_trng_generate_random((uint8_t *)&random_word, sizeof(random_word));
lcm_get_sp_enabled(&lcm_dev_s, &sp_enabled);
lcm_get_lcs(&lcm_dev_s, &lcs);
- bl1_random_generate_noise_stateless(prbg_seed, sizeof(prbg_seed));
+ bl1_random_generate_noise(prbg_seed, sizeof(prbg_seed));
kmu_init(&kmu_dev_s, prbg_seed);
/* Clear PRBG seed from the stack */
@@ -253,7 +253,7 @@
* we need to generate a new TRAM key.
*/
if (sp_enabled == LCM_TRUE && (lcs == LCM_LCS_CM || lcs == LCM_LCS_DM)) {
- bl1_random_generate_noise_stateless(tram_key, sizeof(tram_key));
+ bl1_random_generate_noise(tram_key, sizeof(tram_key));
kmu_set_key(&kmu_dev_s, RSE_KMU_SLOT_TRAM_KEY, tram_key, sizeof(tram_key));
@@ -263,7 +263,7 @@
}
/* generate a random word to initialise the DTCM */
- bl1_random_generate_noise_stateless((uint8_t *)&random_word, sizeof(random_word));
+ bl1_random_generate_noise((uint8_t *)&random_word, sizeof(random_word));
}
kmu_set_key_export_config(&kmu_dev_s, RSE_KMU_SLOT_TRAM_KEY, &tram_key_export_config);