CC3XX: Support in the Noise Source for requests to bump quality
The Noise Source might support external requests from its callers,
mainly the Entropy module, to bump its configuration parameters to
possibly improve quality of the returned noise bits. Change the
entropy module to make use of this new API.
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I77fce015ecb5e6a071a74d22ed2736a78e99de3f
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_noise_source.h b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_noise_source.h
index 64ba9cc..dbf619c 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_noise_source.h
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/include/cc3xx_noise_source.h
@@ -240,6 +240,16 @@
*/
cc3xx_err_t cc3xx_lowlevel_noise_source_finish(void);
+/**
+ * @brief Bumps the configuration parameters of the noise source, if it allows that
+ *
+ * @param[in, out] ctx Pointer to the context to use for possible bumping up of the parameters
+ *
+ * @return true A config parameters change has happened
+ * @return false A config parameters change has not happened or it was not possible
+ */
+bool cc3xx_lowlevel_noise_source_bump_parameters(struct cc3xx_noise_source_ctx_t *ctx);
+
#ifdef __cplusplus
}
#endif
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 3702936..eea4d5d 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
@@ -213,6 +213,7 @@
{
cc3xx_err_t err;
size_t num_words = 0;
+ bool retry = false;
assert((entropy_len % CC3XX_TRNG_SAMPLE_SIZE) == 0);
@@ -220,41 +221,47 @@
cc3xx_lowlevel_noise_source_context_init(&g_trng_ctx);
}
- err = cc3xx_lowlevel_noise_source_init(&g_trng_ctx);
- if (err != CC3XX_ERR_SUCCESS) {
- return err;
- }
-
- if (!g_entropy_tests.startup_done) {
- /* Perform any required configuration on the TRNG first */
- cc3xx_lowlevel_noise_source_sp800_90b_mode(&g_trng_ctx);
- /* Perform the extensive collection on startup */
- err = startup_test(CC3XX_TRNG_SAMPLE_SIZE);
+ do {
+ /* Initialise the Noise Source */
+ err = cc3xx_lowlevel_noise_source_init(&g_trng_ctx);
if (err != CC3XX_ERR_SUCCESS) {
- goto cleanup;
- }
- g_entropy_tests.startup_done = true;
- }
-
- for (size_t i = 0; i < entropy_len / CC3XX_TRNG_SAMPLE_SIZE; i++) {
- /* Get a full reading from the noise source and put it at the right offset */
- err = cc3xx_lowlevel_noise_source_get_sample(
- &g_trng_ctx, &entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t));
- if (err != CC3XX_ERR_SUCCESS) {
- goto cleanup;
+ return err;
}
- /* The entropy source is always in SP 800-90B mode, i.e. continuosly testing itself */
- err = continuous_health_test(&entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE, &g_entropy_tests);
- if (err != CC3XX_ERR_SUCCESS) {
- goto cleanup;
+ if (!g_entropy_tests.startup_done) {
+ /* Perform any required configuration on the Noise Source first */
+ cc3xx_lowlevel_noise_source_sp800_90b_mode(&g_trng_ctx);
+ /* Perform the extensive collection on startup */
+ err = startup_test(CC3XX_TRNG_SAMPLE_SIZE);
+ if (err != CC3XX_ERR_SUCCESS) {
+ goto cleanup;
+ }
+ g_entropy_tests.startup_done = true;
}
- num_words += CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t);
- }
+ for (size_t i = 0; i < entropy_len / CC3XX_TRNG_SAMPLE_SIZE; i++) {
+ /* Get a full reading from the noise source and put it at the right offset */
+ err = cc3xx_lowlevel_noise_source_get_sample(
+ &g_trng_ctx, &entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t));
+ if (err != CC3XX_ERR_SUCCESS) {
+ goto cleanup;
+ }
+
+ /* The entropy source is always in SP 800-90B mode, i.e. continuosly testing itself */
+ err = continuous_health_test(&entropy[num_words], CC3XX_TRNG_SAMPLE_SIZE, &g_entropy_tests);
+ if (err != CC3XX_ERR_SUCCESS) {
+ goto cleanup;
+ }
+
+ num_words += CC3XX_TRNG_SAMPLE_SIZE / sizeof(uint32_t);
+ }
cleanup:
- cc3xx_lowlevel_noise_source_finish();
+ cc3xx_lowlevel_noise_source_finish();
+ if (err != CC3XX_ERR_SUCCESS) {
+ retry = cc3xx_lowlevel_noise_source_bump_parameters(&g_trng_ctx);
+ }
+ } while ((err != CC3XX_ERR_SUCCESS) && retry);
return err;
}
diff --git a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_noise_source.c b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_noise_source.c
index 84fdf7e..6fc4383 100644
--- a/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_noise_source.c
+++ b/platform/ext/target/arm/drivers/cc3xx/low_level_driver/src/cc3xx_noise_source.c
@@ -171,36 +171,29 @@
return (product > UINT32_MAX) ? UINT32_MAX : (uint32_t)product;
}
-static void trng_bump_rosc_id_and_subsampling_rate(struct cc3xx_noise_source_ctx_t *ctx)
+static bool trng_bump_rosc_id_and_subsampling_rate(uint32_t *rosc_id, uint32_t *rosc_subsampling_rate)
{
- uint32_t rosc_id = P_CC3XX->rng.trng_config & TRNG_ROSC_ID_MASK;
- uint32_t rosc_subsampling_rate = P_CC3XX->rng.sample_cnt1;
-
- if ((rosc_id == CC3XX_RNG_ROSC_ID_3) && (rosc_subsampling_rate == UINT32_MAX)) {
+ if ((*rosc_id == CC3XX_RNG_ROSC_ID_3) && (*rosc_subsampling_rate == UINT32_MAX)) {
/* Cannot bump further */
- return;
+ return false;
}
- if (rosc_id < CC3XX_RNG_ROSC_ID_3) {
+ if (*rosc_id < CC3XX_RNG_ROSC_ID_3) {
/* For each subsampling rate, bump the rosc id */
- rosc_id++;
+ (*rosc_id)++;
} else {
/* Double the subsampling rate when rosc id is at its max*/
- rosc_id = CC3XX_RNG_ROSC_ID_0;
- rosc_subsampling_rate = trng_double_subsampling_rate(rosc_subsampling_rate);
+ *rosc_id = CC3XX_RNG_ROSC_ID_0;
+ *rosc_subsampling_rate = trng_double_subsampling_rate(*rosc_subsampling_rate);
}
- P_CC3XX->rng.trng_config = rosc_id | (0x1U << 2);
- P_CC3XX->rng.sample_cnt1 = rosc_subsampling_rate;
-
- /* Update the context */
- ctx->rosc.id = rosc_id;
- ctx->rosc.subsampling_rate = rosc_subsampling_rate;
+ return true;
}
static bool trng_error_handler(struct cc3xx_noise_source_ctx_t *ctx)
{
uint32_t trng_errors = trng_get_errors();
+ uint32_t rosc_id, rosc_subsampling_rate;
#ifdef CC3XX_CONFIG_TRNG_DMA
size_t dma_samples_num;
#endif
@@ -221,6 +214,10 @@
dma_samples_num = P_CC3XX->rng.rng_dma_samples_num;
#endif
+ /* Get the ROSC-related config parameters from the TRNG */
+ rosc_id = P_CC3XX->rng.trng_config & TRNG_ROSC_ID_MASK;
+ rosc_subsampling_rate = P_CC3XX->rng.sample_cnt1;
+
/* Disable random source before resetting the bit counter */
P_CC3XX->rng.rnd_source_enable = 0x0U;
@@ -230,8 +227,15 @@
/* Clear the interrupt bits */
P_CC3XX->rng.rng_icr = 0xFFFFFFFF;
- /* Bump the rosc id and subsampling rate */
- trng_bump_rosc_id_and_subsampling_rate(ctx);
+ /* Bump the rosc id and subsampling rate, if there is room for it */
+ if (trng_bump_rosc_id_and_subsampling_rate(&rosc_id, &rosc_subsampling_rate)) {
+ /* Update the TRNG parameters */
+ P_CC3XX->rng.trng_config = rosc_id | (0x1U << 2);
+ P_CC3XX->rng.sample_cnt1 = rosc_subsampling_rate;
+ /* Update the context as well */
+ ctx->rosc.id = rosc_id;
+ ctx->rosc.subsampling_rate = rosc_subsampling_rate;
+ }
/* Restart TRNG */
trng_init(
@@ -321,7 +325,7 @@
};
}
#else
-void cc3xx_lowlevel_noise_source_context_init(void *ctx)
+void cc3xx_lowlevel_noise_source_context_init(struct cc3xx_noise_source_ctx_t *ctx)
{
(void)ctx;
}
@@ -338,7 +342,7 @@
return CC3XX_ERR_SUCCESS;
}
#else
-cc3xx_err_t cc3xx_lowlevel_noise_source_init(void *ctx)
+cc3xx_err_t cc3xx_lowlevel_noise_source_init(struct cc3xx_noise_source_ctx_t *ctx)
{
(void)ctx;
trng_init();
@@ -400,7 +404,7 @@
CC3XX_TRNG_AUTOCORR_TEST_BYPASS, CC3XX_TRNG_CRNGT_TEST_ACTIVE, CC3XX_TRNG_VNC_TEST_BYPASS);
}
#else
-void cc3xx_lowlevel_noise_source_sp800_90b_mode(void *ctx)
+void cc3xx_lowlevel_noise_source_sp800_90b_mode(struct cc3xx_noise_source_ctx_t *ctx)
{
/* The external noise source must allow SP800-90B, perform any step required to enable it */
(void)ctx;
@@ -429,13 +433,27 @@
ctx->debug_control = hw_entropy_tests_control;
}
#else
-void cc3xx_lowlevel_noise_source_set_hw_test_bypass(void *ctx)
+void cc3xx_lowlevel_noise_source_set_hw_test_bypass(struct cc3xx_noise_source_ctx_t *ctx)
{
/* If an external noise source has the option to separately configure the HW, plug it here */
(void)ctx;
}
#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
+#ifndef CC3XX_CONFIG_RNG_EXTERNAL_TRNG
+bool cc3xx_lowlevel_noise_source_bump_parameters(struct cc3xx_noise_source_ctx_t *ctx)
+{
+ return trng_bump_rosc_id_and_subsampling_rate((uint32_t *)&ctx->rosc.id, &ctx->rosc.subsampling_rate);
+}
+#else
+bool cc3xx_lowlevel_noise_source_bump_parameters(struct cc3xx_noise_source_ctx_t *ctx)
+{
+ /* If an external noise source has the option to bump config parameters, plug it here */
+ (void)ctx;
+ return false;
+}
+#endif /* CC3XX_CONFIG_RNG_EXTERNAL_TRNG */
+
#ifdef CC3XX_CONFIG_TRNG_COLLECT_STATISTCS
void cc3xx_lowlevel_noise_source_get_stats(struct cc3xx_noise_source_stats_t *stats)
{