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);