CC3XX: Add DRBGs (CTR, HMAC, HASH)

Verified through some of the vectors available in the DRBGVS set.

Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: Ib1c864f6c866e0c06fce29d6c8abfec1b39bc0ac
diff --git a/platform/ext/accelerator/cc312/cc312-rom/CMakeLists.txt b/platform/ext/accelerator/cc312/cc312-rom/CMakeLists.txt
index 16a273c..e789524 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/CMakeLists.txt
+++ b/platform/ext/accelerator/cc312/cc312-rom/CMakeLists.txt
@@ -22,6 +22,11 @@
         ./cc3xx_kdf.c
         ./cc3xx_pka.c
         ./cc3xx_poly1305.c
+        ./cc3xx_hmac.c
+        ./cc3xx_drbg_ctr.c
+        ./cc3xx_drbg_hash.c
+        ./cc3xx_drbg_hmac.c
+        ./cc3xx_drbg.c
 )
 
 target_include_directories(cc312_rom
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.c
new file mode 100644
index 0000000..59399b2
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <assert.h>
+#include "cc3xx_drbg.h"
+#include "cc3xx_config.h"
+
+cc3xx_err_t cc3xx_drbg_init(
+    cc3xx_drbg_id_t id,
+    struct cc3xx_drbg_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len)
+{
+    assert(id < CC3XX_DRBG_MAX);
+
+    state->id = id;
+
+    switch(id) {
+#ifdef CC3XX_CONFIG_DRBG_CTR_ENABLE
+    case CC3XX_DRBG_CTR:
+        return cc3xx_drbg_ctr_init(
+            &state->ctr,
+            entropy, entropy_len,
+            nonce, nonce_len,
+            personalization, personalization_len);
+#endif /* CC3XX_CONFIG_DRBG_CTR_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HMAC_ENABLE
+    case CC3XX_DRBG_HMAC:
+        return cc3xx_drbg_hmac_instantiate(
+            &state->hmac,
+            entropy, entropy_len,
+            nonce, nonce_len,
+            personalization, personalization_len);
+#endif /* CC3XX_CONFIG_DRBG_HMAC_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HASH_ENABLE
+    case CC3XX_DRBG_HASH:
+        return cc3xx_drbg_hash_init(
+            &state->hash,
+            entropy, entropy_len,
+            nonce, nonce_len,
+            personalization, personalization_len);
+#endif /* CC3XX_CONFIG_DRBG_HASH_ENABLE */
+    default:
+        return CC3XX_ERR_DRBG_INVALID_ID;
+    }
+}
+
+cc3xx_err_t cc3xx_drbg_generate(
+    struct cc3xx_drbg_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    switch(state->id) {
+#ifdef CC3XX_CONFIG_DRBG_CTR_ENABLE
+    case CC3XX_DRBG_CTR:
+        return cc3xx_drbg_ctr_generate(
+            &state->ctr, len_bits, returned_bits, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_CTR_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HMAC_ENABLE
+    case CC3XX_DRBG_HMAC:
+        return cc3xx_drbg_hmac_generate(
+            &state->hmac, len_bits, returned_bits, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_HMAC_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HASH_ENABLE
+    case CC3XX_DRBG_HASH:
+        return cc3xx_drbg_hash_generate(
+            &state->hash, len_bits, returned_bits, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_HASH_ENABLE */
+    default:
+        return CC3XX_ERR_DRBG_INVALID_ID;
+    }
+}
+
+cc3xx_err_t cc3xx_drbg_reseed(
+    struct cc3xx_drbg_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    switch(state->id) {
+#ifdef CC3XX_CONFIG_DRBG_CTR_ENABLE
+    case CC3XX_DRBG_CTR:
+        return cc3xx_drbg_ctr_reseed(
+            &state->ctr, entropy, entropy_len, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_CTR_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HMAC_ENABLE
+    case CC3XX_DRBG_HMAC:
+        return cc3xx_drbg_hmac_reseed(
+            &state->hmac, entropy, entropy_len, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_HMAC_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HASH_ENABLE
+    case CC3XX_DRBG_HASH:
+        return cc3xx_drbg_hash_reseed(
+            &state->hash, entropy, entropy_len, additional_input, additional_input_len);
+#endif /* CC3XX_CONFIG_DRBG_HASH_ENABLE */
+    default:
+        return CC3XX_ERR_DRBG_INVALID_ID;
+    }
+}
+
+cc3xx_err_t cc3xx_drbg_uninit(struct cc3xx_drbg_state_t *state)
+{
+    switch(state->id) {
+#ifdef CC3XX_CONFIG_DRBG_CTR_ENABLE
+    case CC3XX_DRBG_CTR:
+        return cc3xx_drbg_ctr_uninit(&state->ctr);
+#endif /* CC3XX_CONFIG_DRBG_CTR_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HMAC_ENABLE
+    case CC3XX_DRBG_HMAC:
+        return cc3xx_drbg_hmac_uninit(&state->hmac);
+#endif /* CC3XX_CONFIG_DRBG_HMAC_ENABLE */
+#ifdef CC3XX_CONFIG_DRBG_HASH_ENABLE
+    case CC3XX_DRBG_HASH:
+        return cc3xx_drbg_hash_uninit(&state->hash);
+#endif /* CC3XX_CONFIG_DRBG_HASH_ENABLE */
+    default:
+        return CC3XX_ERR_DRBG_INVALID_ID;
+    }
+}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.h
new file mode 100644
index 0000000..1852906
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CC3XX_DRBG_H__
+#define __CC3XX_DRBG_H__
+
+/**
+ * @file Contains a generic interface towards a DRBG mechanism that
+ *       can be chosen at runtime during the instantiation phase of
+ *       the DRBG, i.e. when calling cc3xx_drbg_init()
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include "cc3xx_error.h"
+#include "cc3xx_config.h"
+
+#include "cc3xx_drbg_ctr.h"
+#include "cc3xx_drbg_hash.h"
+#include "cc3xx_drbg_hmac.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief This enum defines which DRBG mechanism to use. Allowed
+ *        values are CC3XX_DRBG_CTR, CC3XX_DRBG_HASH, CC3XX_DRBG_HMAC
+ */
+typedef enum {
+    CC3XX_DRBG_CTR = 0,
+    CC3XX_DRBG_HMAC,
+    CC3XX_DRBG_HASH,
+    CC3XX_DRBG_MAX = CC3XX_DRBG_HASH + 1,
+} cc3xx_drbg_id_t;
+
+/**
+ * @brief Generic context for a DRBG generator
+ *
+ */
+struct cc3xx_drbg_state_t {
+    cc3xx_drbg_id_t id;
+    union {
+        struct cc3xx_drbg_ctr_state_t ctr;
+        struct cc3xx_drbg_hmac_state_t hmac;
+        struct cc3xx_drbg_hash_state_t hash;
+    };
+};
+
+/**
+ * @brief Instantiate the DRBG
+ *
+ * @param id    The ID of the DRBG to instantiate, of type \ref cc3xx_drbg_id_t
+ * @param state A pointer to a state structure
+ * @param entropy Buffer containing the entropy for the instantiation
+ * @param entropy_len Size in bytes of the entropy buffer \param entropy
+ * @param nonce Buffer containing the nonce
+ * @param nonce_len Size in bytes of the nonce buffer \param nonce
+ * @param personalization Buffer containing the personalization string
+ * @param personalization_len Size in bytes of the personalization buffer \param personalization
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_init(
+    cc3xx_drbg_id_t id,
+    struct cc3xx_drbg_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len);
+
+/**
+ * @brief Generates random bits from the DRBG instance
+ *
+ * @param state Pointer to an instantiated DRBG generator
+ * @param len_bits Size in bits to be generated. Must be byte aligned for simplicity
+ * @param returned_bits Pointer holding the returned random bit string
+ * @param additional_input Pointer to the additional input to be used
+ * @param additional_input_len Size in bytes of the additional input to be used
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_generate(
+    struct cc3xx_drbg_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Reseeds the DRBG
+ *
+ * @param state A pointer to a state structure
+ * @param entropy Entropy to be used for reseeding
+ * @param entropy_len Size in bytes of the entropy pointed by \param entropy
+ * @param additional_input Optional pointer containing additional input for reseeding
+ * @param additional_input_len Size in bytes of the buffer pointed by \param additional_input
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_reseed(
+    struct cc3xx_drbg_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Un-initializes the state structure associated to the underlying DRBG
+ *
+ * @param state Pointer to the structure
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_uninit(struct cc3xx_drbg_state_t *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CC3XX_DRBG_H__ */
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.c
new file mode 100644
index 0000000..eda5f46
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include "cc3xx_pka.h"
+#include "cc3xx_endian_helpers.h"
+#include "cc3xx_drbg_ctr.h"
+#include "cc3xx_rng.h"
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+#include "cc3xx_stdlib.h"
+#endif
+
+static void long_inc_int(uint32_t *acc, size_t acc_size, bool is_increment)
+{
+    cc3xx_pka_reg_id_t r0;
+    assert(acc_size == CC3XX_DRBG_CTR_BLOCKLEN);
+
+    /* Accumulation happen only on 128 bit accumulators */
+    cc3xx_pka_init(CC3XX_DRBG_CTR_BLOCKLEN);
+
+    /* Allocate a register among those not in use, given configured size */
+    r0 = cc3xx_pka_allocate_reg();
+
+    /* Initialize the accumulator register with the current value of acc */
+    cc3xx_pka_write_reg(r0, (const uint32_t *)acc, CC3XX_DRBG_CTR_BLOCKLEN);
+
+    /* Perform the actual operation */
+    cc3xx_pka_add_si(r0, is_increment ? 1 : -1, r0);
+
+    /* Read back the accumulator register */
+    cc3xx_pka_read_reg(r0, acc, CC3XX_DRBG_CTR_BLOCKLEN);
+
+    /* Uninit the engine */
+    cc3xx_pka_uninit();
+}
+
+static inline void long_inc(uint32_t *acc, size_t acc_size)
+{
+    long_inc_int(acc, acc_size, true);
+}
+
+static inline void long_dec(uint32_t *acc, size_t acc_size)
+{
+    long_inc_int(acc, acc_size, false);
+}
+
+/**
+ * @brief Produces seedlen bits of data through the underlying block
+ *        cipher (AES) set in CTR mode, and uses the produced data to update
+ *        the values of (Key, V) to be used as a state
+ *
+ * @param state    A pointer to a state structure
+ * @param data     provided data for the update process
+ * @param data_len Length of the update operation
+ *
+ * @return cc3xx_err_t
+ */
+static cc3xx_err_t cc3xx_drbg_ctr_update(
+    struct cc3xx_drbg_ctr_state_t *state,
+    const uint8_t *data, const size_t data_len)
+{
+    cc3xx_err_t err;
+
+    assert(data_len <= CC3XX_DRBG_CTR_SEEDLEN);
+
+    long_inc((uint32_t *)state->block_v, sizeof(state->block_v));
+
+    err = cc3xx_aes_init(CC3XX_AES_DIRECTION_ENCRYPT,
+                         CC3XX_AES_MODE_CTR,
+                         CC3XX_AES_KEY_ID_USER_KEY,
+                         (const uint32_t *)state->key_k, sizeof(state->key_k),
+                         (const uint32_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    cc3xx_aes_set_output_buffer((uint8_t *)state->key_k, CC3XX_DRBG_CTR_SEEDLEN);
+
+    err = cc3xx_aes_update(data, data_len);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    /* allow for the update() to happen on less than 256 bit of data */
+    if (data_len < CC3XX_DRBG_CTR_SEEDLEN) {
+        uint8_t all_zeros[CC3XX_DRBG_CTR_SEEDLEN - data_len];
+        memset(all_zeros, 0, sizeof(all_zeros));
+        err = cc3xx_aes_update(all_zeros, sizeof(all_zeros));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+    }
+
+    err = cc3xx_aes_finish(NULL);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_ctr_init(
+    struct cc3xx_drbg_ctr_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len)
+{
+    cc3xx_err_t err;
+    uint32_t personalized_entropy[CC3XX_DRBG_CTR_SEEDLEN_WORDS];
+    uint8_t *seed_material = (uint8_t *)entropy;
+    size_t idx;
+
+    /* The entropy must be equal to 256 bit. The spec allows for a lower
+     * amout of entropy to be passed during instantiation, then using a
+     * derivation function at this point to reach 256 bit. But this implementation
+     * focuses on lower complexity hence the derivation function is not used
+     */
+    assert(entropy_len == CC3XX_DRBG_CTR_SEEDLEN);
+
+    /* This implementation does not use a derivation function, hence the nonce
+     * is not used during the instantiation procedure
+     */
+    (void)nonce;
+    (void)nonce_len;
+
+    if (personalization != NULL) {
+
+        /* If present and less than 256 bit, it's equivalent to be zero padded */
+        assert(personalization_len <= CC3XX_DRBG_CTR_SEEDLEN);
+
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+        cc3xx_dpa_hardened_word_copy(personalized_entropy,
+                                     (uint32_t *)entropy,
+                                     CC3XX_DRBG_CTR_SEEDLEN_WORDS);
+#else
+        memcpy(personalized_entropy, entropy, CC3XX_DRBG_CTR_SEEDLEN);
+#endif
+        for (idx = 0; idx < personalization_len; idx++) {
+            ((uint8_t *)personalized_entropy)[idx] ^= personalization[idx];
+        }
+        seed_material = (uint8_t *)personalized_entropy;
+    }
+
+    memset(state, 0, sizeof(struct cc3xx_drbg_ctr_state_t));
+
+    err = cc3xx_drbg_ctr_update(state, seed_material, CC3XX_DRBG_CTR_SEEDLEN);
+    if (err != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    state->reseed_counter = 1;
+
+out:
+    if (personalization != NULL) {
+        /* Make sure the seed material on the stack gets overwritten with random values */
+        cc3xx_secure_erase_buffer(personalized_entropy, CC3XX_DRBG_CTR_SEEDLEN_WORDS);
+    }
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_ctr_generate(
+    struct cc3xx_drbg_ctr_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+    const uint8_t all_zeros[CC3XX_DRBG_CTR_SEEDLEN] = {0};
+    const uint8_t *p_additional_input = all_zeros;
+    size_t produced_bits = 0;
+    size_t num_whole_blocks = (len_bits/8)/CC3XX_DRBG_CTR_SEEDLEN;
+    struct cc3xx_aes_state_t aes_state;
+    size_t idx;
+
+    if (state->reseed_counter == UINT32_MAX) {
+        /* When we reach 2^32 invocations we must reseed */
+        return CC3XX_ERR_DRBG_RESEED_REQUIRED;
+    }
+
+    /* The implementation constraints the output length to be byte aligned to
+     * reduce complexity
+     */
+    assert(len_bits != 0);
+    assert((len_bits % 8) == 0);
+
+    if (additional_input != NULL) {
+
+        assert(additional_input_len <= CC3XX_DRBG_CTR_SEEDLEN);
+
+        err = cc3xx_drbg_ctr_update(state, additional_input, additional_input_len);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        p_additional_input = additional_input;
+    }
+
+    long_inc((uint32_t *)state->block_v, sizeof(state->block_v));
+
+    err = cc3xx_aes_init(CC3XX_AES_DIRECTION_ENCRYPT,
+                         CC3XX_AES_MODE_CTR,
+                         CC3XX_AES_KEY_ID_USER_KEY,
+                         (const uint32_t *)state->key_k, sizeof(state->key_k),
+                         (const uint32_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    cc3xx_aes_set_output_buffer(returned_bits, len_bits/8); /* length is in bytes */
+
+    for (idx = 0; idx < num_whole_blocks; idx++) {
+        err = cc3xx_aes_update(all_zeros, sizeof(all_zeros));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        produced_bits += (CC3XX_DRBG_CTR_SEEDLEN * 8);
+    }
+
+    /* Deal with a partial block */
+    if ((len_bits - produced_bits) != 0) {
+        /* Produce the last block */
+        err = cc3xx_aes_update(all_zeros, (len_bits - produced_bits)/8); /* in bytes */
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+    }
+
+    /* We need to get the value of the counter back from the AES subsystem
+     * as it's required in update()
+     */
+    cc3xx_aes_get_state(&aes_state);
+
+    err = cc3xx_aes_finish(NULL);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+    cc3xx_dpa_hardened_word_copy((uint32_t *)state->block_v,
+                                 aes_state.ctr,
+                                 CC3XX_DRBG_CTR_BLOCKLEN_WORDS);
+#else
+    memcpy(state->block_v, aes_state.ctr, sizeof(state->block_v));
+#endif
+    long_dec((uint32_t *)state->block_v, sizeof(state->block_v));
+
+    /* Update for back tracking resistance */
+    err = cc3xx_drbg_ctr_update(state, p_additional_input, CC3XX_DRBG_CTR_SEEDLEN);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    state->reseed_counter++;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_ctr_reseed(
+    struct cc3xx_drbg_ctr_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+    uint32_t personalized_entropy[CC3XX_DRBG_CTR_SEEDLEN_WORDS];
+    uint8_t *seed_material = (uint8_t *)entropy;
+    size_t idx;
+
+    assert(entropy_len == CC3XX_DRBG_CTR_SEEDLEN);
+
+    if (additional_input != NULL) {
+        assert(additional_input_len <= CC3XX_DRBG_CTR_SEEDLEN);
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+        cc3xx_dpa_hardened_word_copy(personalized_entropy,
+                                     (uint32_t *)entropy,
+                                     CC3XX_DRBG_CTR_SEEDLEN_WORDS);
+#else
+        memcpy(personalized_entropy, entropy, entropy_len);
+#endif
+        for (idx = 0; idx < additional_input_len; idx++) {
+            ((uint8_t *)personalized_entropy)[idx] ^= additional_input[idx];
+        }
+        seed_material = (uint8_t *)personalized_entropy;
+    }
+
+    err = cc3xx_drbg_ctr_update(state, seed_material, entropy_len);
+    if (err != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    state->reseed_counter = 1;
+
+out:
+    if (additional_input != NULL) {
+        /* Make sure the seed material on the stack gets overwritten with random values */
+        cc3xx_secure_erase_buffer(personalized_entropy, CC3XX_DRBG_CTR_SEEDLEN_WORDS);
+    }
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_ctr_uninit(struct cc3xx_drbg_ctr_state_t *state)
+{
+    /* Secure erase only the sensitive material*/
+    cc3xx_secure_erase_buffer((uint32_t *)state, CC3XX_DRBG_CTR_SEEDLEN_WORDS);
+
+    memset(state, 0, sizeof(struct cc3xx_drbg_ctr_state_t));
+
+    return CC3XX_ERR_SUCCESS;
+}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.h
new file mode 100644
index 0000000..f17fa91
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_ctr.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CC3XX_DRBG_CTR_H__
+#define __CC3XX_DRBG_CTR_H__
+
+#include "cc3xx_error.h"
+#include "cc3xx_aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief CTR mode uses AES only as underlying block cipher
+ *
+ */
+#define CC3XX_DRBG_CTR_BLOCKLEN (AES_BLOCK_SIZE)
+
+/**
+ * @brief CTR mode uses AES-128 only as underlying block cipher
+ *
+ */
+#define CC3XX_DRBG_CTR_KEYLEN (16)
+
+/**
+ * @brief AES-128 key length in words, as used by the CTR_DRBG module
+ *
+ */
+#define CC3XX_DRBG_CTR_KEYLEN_WORDS ((CC3XX_DRBG_CTR_KEYLEN)/(4))
+
+/**
+ * @brief CTR mode uses AES only as underlying block cipher, and this
+ *        define provides the value of the AES block length in words
+ *
+ */
+#define CC3XX_DRBG_CTR_BLOCKLEN_WORDS ((CC3XX_DRBG_CTR_BLOCKLEN)/(4))
+
+/**
+ * @brief CTR_DRBG defines SEEDLEN as BLOCKLEN + KEYLEN
+ *
+ */
+#define CC3XX_DRBG_CTR_SEEDLEN (CC3XX_DRBG_CTR_BLOCKLEN + CC3XX_DRBG_CTR_KEYLEN)
+
+/**
+ * @brief CTR_DRBG defines SEEDLEN as BLOCKLEN + KEYLEN (This is in words)
+ *
+ */
+#define CC3XX_DRBG_CTR_SEEDLEN_WORDS (CC3XX_DRBG_CTR_BLOCKLEN_WORDS + CC3XX_DRBG_CTR_KEYLEN_WORDS)
+
+/**
+ * @brief Contains the state of the CTR_DRBG
+ *
+ */
+struct cc3xx_drbg_ctr_state_t {
+    uint32_t key_k[CC3XX_DRBG_CTR_KEYLEN_WORDS];
+    uint32_t block_v[CC3XX_DRBG_CTR_BLOCKLEN_WORDS];
+    uint32_t reseed_counter;
+};
+
+/**
+ * @brief Instantiate the CTR_DRBG
+ *
+ * @param state               A pointer to a state structure
+ * @param entropy             Buffer containing the entropy for the instantiation
+ * @param entropy_len         Size in bytes of the entropy buffer \param entropy
+ * @param nonce               Buffer containing the nonce
+ * @param nonce_len           Size in bytes of the nonce buffer \param nonce
+ * @param personalization     Buffer containing the personalization string
+ * @param personalization_len Size in bytes of the personalization buffer \param personalization
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_ctr_init(
+    struct cc3xx_drbg_ctr_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len);
+
+/**
+ * @brief Generates random bits from the CTR_DRBG instance
+ *
+ * @param state                Pointer to an instantiated CTR_DRBG generator
+ * @param len_bits             Size in bits to be generated. Must be byte aligned for simplicity
+ * @param returned_bits        Pointer where the random bits will be written to
+ * @param additional_input     Pointer to the additional input to be used
+ * @param additional_input_len Size in bytes of the additional input to be used
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_ctr_generate(
+    struct cc3xx_drbg_ctr_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Reseeds the CTR_DRBG
+ *
+ * @param state                A pointer to a state structure
+ * @param entropy              Entropy to be used for reseeding
+ * @param entropy_len          Size in bytes of the entropy pointed by \param entropy
+ * @param additional_input     Optional pointer containing additional input for reseeding
+ * @param additional_input_len Size in bytes of the buffer pointed by \param additional_input
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_ctr_reseed(
+    struct cc3xx_drbg_ctr_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Un-initializes the state structure associated to the CTR_DRBG
+ *
+ * @param state Pointer to the state structure
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_ctr_uninit(
+    struct cc3xx_drbg_ctr_state_t *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CC3XX_DRBG_CTR_H__ */
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.c
new file mode 100644
index 0000000..2005cd3
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include "cc3xx_hash.h"
+#include "cc3xx_drbg_hash.h"
+#include "cc3xx_endian_helpers.h"
+#include "cc3xx_pka.h"
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+#include "cc3xx_stdlib.h"
+#endif
+
+/**
+ * @brief Ceiling of a / b
+ */
+#define CEIL(a, b) ((a) + (b) - 1)/(b)
+
+/** \note Throughout the file sizeof(state_v) and sizeof(constant_c) are
+ *        decreased by 1 byte because they have been defined with 1 byte
+ *        more in the \ref struct cc3xx_drbg_hash_state_t to be 4 bytes
+ *        aligned
+ */
+
+static void long_acc(uint8_t *acc, const uint8_t *val, size_t acc_size, size_t val_size)
+{
+    /* Need to convert BE -> LE -> BE again if PKA is configured for LE */
+    cc3xx_pka_reg_id_t r0, r1;
+    assert(acc_size == CC3XX_DRBG_HASH_SEEDLEN);
+
+    /* Accumulation happen only on 440 bit accumulators */
+    cc3xx_pka_init(CC3XX_DRBG_HASH_SEEDLEN);
+
+    /* Allocate a register among those not in use, given configured size */
+    r0 = cc3xx_pka_allocate_reg();
+
+    /* Initialize the accumulator register with the current value of acc */
+    cc3xx_pka_write_reg(r0, (const uint32_t *)acc, CC3XX_DRBG_HASH_SEEDLEN);
+
+    /* Request another register for the value to accumulate */
+    r1 = cc3xx_pka_allocate_reg();
+
+    /* Write the value to accumulate into the register */
+    cc3xx_pka_write_reg(r1, (const uint32_t *)val, val_size);
+
+    /* Perform the actual operation */
+    cc3xx_pka_add(r0, r1, r0);
+
+    /* Read back the accumulator register */
+    cc3xx_pka_read_reg(r0, (uint32_t *)acc, CC3XX_DRBG_HASH_SEEDLEN);
+
+    /* Uninit the engine */
+    cc3xx_pka_uninit();
+}
+
+/* Hardcode support for SHA-256 based HMAC only */
+static const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
+
+/**
+ * @brief Hash derivation function as specified by NIST SP 800-90 Section 10.3.1
+ *
+ * @param hash_inputs_num Total number of the hash_inputs being passed to the update function
+ * @param hash_inputs     An array of three buffer pointers that can be used in the derivation process
+ * @param hash_inputs_len An array of three size_t values that contain the size of each buffer passed
+ * @param out             Buffer containing the output of the derivation function
+ * @param out_len_bits    Size in bits of the buffer containing the result of the derivation operation
+ * @return cc3xx_err_t
+ */
+static cc3xx_err_t hash_df(
+    size_t hash_inputs_num,
+    const uint8_t **hash_inputs,
+    const size_t *hash_inputs_len,
+    uint8_t *out,
+    size_t out_len_bits)
+{
+    /* The number of full SHA-256 hashes output (256 bit) that we need to cover the requested
+     * output of out_len_bits = 440 bit, i.e. the CC3XX_DRBG_HASH_SEEDLEN
+     */
+    const size_t num_hash = 2;
+    cc3xx_err_t err;
+    uint8_t counter_out_len_bits[5] = {0x01, 0x00, 0x00, 0x01, 0xB8}; /* 0x01 || out_len_bits */
+    size_t idx;
+    size_t hash_input_idx;
+    uint32_t temp[SHA256_OUTPUT_SIZE / sizeof(uint32_t)];
+
+    /* Number of bits to return must be fixed to 440 for the implementation, i.e. 0x1B8 */
+    assert(out_len_bits == CC3XX_DRBG_HASH_SEEDLEN * 8);
+
+    for (idx = 0; idx < num_hash; idx++) {
+
+        err = cc3xx_hash_init(alg);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        err = cc3xx_hash_update(counter_out_len_bits, sizeof(counter_out_len_bits));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        for (hash_input_idx = 0; hash_input_idx < hash_inputs_num && hash_inputs_len[hash_input_idx] != 0; hash_input_idx++) {
+            err = cc3xx_hash_update(hash_inputs[hash_input_idx], hash_inputs_len[hash_input_idx]);
+            if (err != CC3XX_ERR_SUCCESS) {
+                return err;
+            }
+        }
+
+        cc3xx_hash_finish((idx != num_hash - 1) ? (uint32_t *)out : temp, SHA256_OUTPUT_SIZE);
+
+        if (idx != num_hash - 1) {
+            out += SHA256_OUTPUT_SIZE;
+        }
+        counter_out_len_bits[0]++;
+    }
+
+    memcpy(out, temp, CC3XX_DRBG_HASH_SEEDLEN - SHA256_OUTPUT_SIZE);
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hash_init(
+    struct cc3xx_drbg_hash_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len)
+{
+    cc3xx_err_t err;
+    uint8_t byte0 = 0x0;
+    const uint8_t *data[3] = {entropy, nonce, personalization};
+    size_t data_len[3] = {entropy_len, nonce_len, personalization_len};
+
+    err = hash_df(3, data, data_len, state->value_v, CC3XX_DRBG_HASH_SEEDLEN * 8);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    data[0] = &byte0;
+    data[1] = state->value_v;
+    data_len[0] = sizeof(byte0);
+    data_len[1] = sizeof(state->value_v) - 1;
+
+    err = hash_df(2, data, data_len, state->constant_c, CC3XX_DRBG_HASH_SEEDLEN * 8);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    state->reseed_counter = 1;
+
+    return err;
+}
+
+/**
+ * @brief Hash based generation process as specified by NIST SP 800-90 Section 10.1.1.4
+ *
+ * @param block_v       block_v containing the seed to be used by the hashgen process
+ * @param out_len_bits  Number of bits requested to be generated, byte aligned
+ * @param returned_bits Buffer containing the bits generated using the hash based process
+ * @return cc3xx_err_t
+ */
+static cc3xx_err_t hash_gen_process(uint8_t *block_v, size_t out_len_bits, uint8_t *returned_bits)
+{
+    cc3xx_err_t err;
+    size_t idx;
+    size_t gen_num_m = CEIL(out_len_bits, SHA256_OUTPUT_SIZE * 8); /* Number of hash generations */
+    uint32_t data[(CC3XX_DRBG_HASH_SEEDLEN + 1) / sizeof(uint32_t)];
+    uint32_t partial_last_block[SHA256_OUTPUT_SIZE / sizeof(uint32_t)];
+#ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
+    size_t num_words_to_copy = sizeof(data) / sizeof(uint32_t);
+    cc3xx_dpa_hardened_word_copy((uint32_t *)data, (uint32_t *)block_v, num_words_to_copy);
+#else
+    memcpy(data, block_v, CC3XX_DRBG_HASH_SEEDLEN);
+#endif
+
+    for (idx = 0; idx < gen_num_m; idx++) {
+        const uint8_t byte1 = 0x1;
+        uint32_t *p_output_buf = NULL;
+
+        err = cc3xx_hash_init(alg);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        err = cc3xx_hash_update((uint8_t *)data, CC3XX_DRBG_HASH_SEEDLEN);
+        if (err!= CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        if (idx != gen_num_m - 1) {
+            p_output_buf = (uint32_t *)returned_bits;
+        } else {
+            /* We need to discriminate the case where the last generation is for a whole
+             * block or a partial block
+             */
+            if (out_len_bits % (SHA256_OUTPUT_SIZE * 8)) {
+                p_output_buf = partial_last_block;
+            } else {
+                p_output_buf = (uint32_t *)returned_bits;
+            }
+        }
+
+        cc3xx_hash_finish(p_output_buf, SHA256_OUTPUT_SIZE);
+
+        long_acc((uint8_t *)data, &byte1, CC3XX_DRBG_HASH_SEEDLEN, sizeof(byte1));
+
+        returned_bits += SHA256_OUTPUT_SIZE;
+    }
+
+    returned_bits -= SHA256_OUTPUT_SIZE;
+
+    if (out_len_bits % (SHA256_OUTPUT_SIZE * 8)) {
+        memcpy(returned_bits, partial_last_block, out_len_bits % (SHA256_OUTPUT_SIZE * 8));
+    }
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hash_generate(
+    struct cc3xx_drbg_hash_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+    const uint8_t byte3 = 0x03;
+    uint8_t reseed_counter[4];
+    uint32_t hash_output_buffer[SHA256_OUTPUT_SIZE / sizeof(uint32_t)];
+    /* The reseed counter must be treated as a BE number, so use a local
+     * buffer to format it as a big endian number for the long addition
+     */
+    uint32_t *p_reseed_counter = (uint32_t *) reseed_counter;
+
+    if (state->reseed_counter == UINT32_MAX) {
+        /* When we reach 2^32 invocations we must reseed */
+        return CC3XX_ERR_DRBG_RESEED_REQUIRED;
+    }
+
+    /* The implementation constraints the output length to be byte aligned to
+     * reduce complexity
+     */
+    assert(len_bits != 0);
+    assert((len_bits % 8) == 0);
+
+    if (additional_input_len && additional_input != NULL) {
+        const uint8_t byte2 = 0x02;
+
+        err = cc3xx_hash_init(alg);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        err = cc3xx_hash_update(&byte2, sizeof(byte2));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        err = cc3xx_hash_update(state->value_v, sizeof(state->value_v) - 1);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        err = cc3xx_hash_update(additional_input, additional_input_len);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        cc3xx_hash_finish(hash_output_buffer, SHA256_OUTPUT_SIZE);
+        long_acc(state->value_v, (uint8_t *)hash_output_buffer,
+                 sizeof(state->value_v) - 1, sizeof(hash_output_buffer));
+    }
+
+    err = hash_gen_process(state->value_v, len_bits, returned_bits);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    err = cc3xx_hash_init(alg);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hash_update(&byte3, sizeof(byte3));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hash_update(state->value_v, sizeof(state->value_v) - 1);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    cc3xx_hash_finish(hash_output_buffer, SHA256_OUTPUT_SIZE);
+
+    /* V = V + H + C + reseed_counter */
+    long_acc(state->value_v, (uint8_t *)hash_output_buffer,
+             sizeof(state->value_v) - 1, sizeof(hash_output_buffer));
+    long_acc(state->value_v, state->constant_c,
+             sizeof(state->value_v) - 1, sizeof(state->constant_c) - 1);
+
+    *p_reseed_counter = bswap_32(state->reseed_counter);
+    long_acc(state->value_v, reseed_counter,
+             sizeof(state->value_v) - 1, sizeof(reseed_counter));
+
+    state->reseed_counter++;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hash_reseed(
+    struct cc3xx_drbg_hash_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+    const uint8_t byte0 = 0x0;
+    /* temporary buffer for (byte1 || V). Note that hash_df does not work in-place */
+    uint8_t temp[1 + sizeof(state->value_v) - 1] = {0x01};
+    const uint8_t *data[3] = {temp, entropy, additional_input};
+    size_t data_len[3] = {sizeof(temp), entropy_len, additional_input_len};
+
+    /* temp concatenates 0x01 || V */
+    memcpy(&temp[1], state->value_v, sizeof(state->value_v) - 1);
+
+    err = hash_df(3, data, data_len, state->value_v, CC3XX_DRBG_HASH_SEEDLEN * 8);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    data[0] = &byte0;
+    data[1] = state->value_v;
+    data_len[0] = sizeof(byte0);
+    data_len[1] = sizeof(state->value_v) - 1;
+
+    err = hash_df(2, data, data_len, state->constant_c, CC3XX_DRBG_HASH_SEEDLEN * 8);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    state->reseed_counter = 1;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hash_uninit(struct cc3xx_drbg_hash_state_t *state)
+{
+    cc3xx_secure_erase_buffer((uint32_t *)state, sizeof(struct cc3xx_drbg_hash_state_t)/4);
+    return CC3XX_ERR_SUCCESS;
+}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.h
new file mode 100644
index 0000000..5aac40f
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hash.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CC3XX_DRBG_HASH_H__
+#define __CC3XX_DRBG_HASH_H__
+
+#include <stdint.h>
+#include "cc3xx_error.h"
+
+#include "cc3xx_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The value of seedlen is fixed by the spec to 440 bits. This
+ *        defines is used to convert it to bytes
+ */
+#define CC3XX_DRBG_HASH_SEEDLEN (440/8)
+
+/**
+ * @brief Contains the state of the HASH_DRBG
+ *
+ */
+struct cc3xx_drbg_hash_state_t {
+    uint8_t value_v[CC3XX_DRBG_HASH_SEEDLEN + 1]; /* +1 for word alignment */
+    uint8_t constant_c[CC3XX_DRBG_HASH_SEEDLEN + 1];
+    uint32_t reseed_counter;
+};
+
+/**
+ * @brief Instantiate the HASH_DRBG generator
+ *
+ * @param state Pointer to a \ref cc3xx_drbg_hash_state_t context
+ * @param entropy Pointer to the collected entropy
+ * @param entropy_len Size in bytes of the entropy
+ * @param nonce Pointer to the nonce to be used
+ * @param nonce_len Size in bytes of the nonce
+ * @param personalization Pointer to the personalisation string to be used
+ * @param personalization_len Size in bytes of the personalisation string
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hash_init(
+    struct cc3xx_drbg_hash_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len);
+
+/**
+ * @brief Generates random bits from the HASH_DRBG instance
+ *
+ * @param state Pointer to an instantiated HASH_DRBG generator
+ * @param len_bits Size in bits to be generated. Must be byte aligned for simplicity
+ * @param returned_bits Pointer holding the returned random bit string
+ * @param additional_input Pointer to the additional input to be used
+ * @param additional_input_len Size in bytes of the additional input to be used
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hash_generate(
+    struct cc3xx_drbg_hash_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Reseeds the HASH_DRBG instance
+ *
+ * @param state Pointer to an instantiated HASH_DRBG generator to reseed
+ * @param entropy Pointer to the additional entropy to use for reseeding
+ * @param entropy_len Size in bytes of the additional entropy
+ * @param additional_input Pointer to the additional input to use for reseeding
+ * @param additional_input_len Size in bytes of the additional input buffer
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hash_reseed(
+    struct cc3xx_drbg_hash_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Un-initializes the state structure associated to the HASH_DRBG
+ *
+ * @param state Pointer to the structure
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hash_uninit(struct cc3xx_drbg_hash_state_t *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CC3XX_DRBG_HASH_H__ */
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c
new file mode 100644
index 0000000..83ae108
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include "cc3xx_stdlib.h"
+#include "cc3xx_hmac.h"
+#include "cc3xx_drbg_hmac.h"
+
+#define BITS_TO_BYTES(x) (((x) + 7)/8)
+#define BYTES_TO_BITS(x) ((x)*8)
+
+/**
+ * @brief Update the state (K,V)
+ *
+ * @param hmac_inputs_num Number of inputs for the update operation, it can be zero
+ * @param state A pointer to a state structure
+ * @param hmac_inputs Inputs for the update operation, passed as an array of hmac_inputs_num pointers
+ * @param hmac_inputs_len Lengths for the update operation, passed as an array of hmac_inputs_num values
+ * @return cc3xx_err_t
+ */
+static cc3xx_err_t cc3xx_drbg_hmac_update(
+    size_t hmac_inputs_num,
+    struct cc3xx_drbg_hmac_state_t *state,
+    const uint8_t **hmac_inputs, const size_t *hmac_inputs_len)
+{
+    const uint8_t byte0 = 0x00; const uint8_t byte1 = 0x01;
+    cc3xx_err_t err;
+    size_t idx;
+
+    /* 1. K = HMAC(K, V || 0x00 || provided_data) */
+    err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, &byte0, sizeof(byte0));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    /* provided_data can be given into up to 3 chunks, starting from 0 index */
+    for (idx = 0; idx < hmac_inputs_num && hmac_inputs_len[idx] != 0; idx++) {
+        err = cc3xx_hmac_update(&state->h, hmac_inputs[idx], hmac_inputs_len[idx]);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+    }
+
+    err = cc3xx_hmac_finish(&state->h, state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    /* 2. V = HMAC(K, V) */
+    err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_finish(&state->h, state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    /* 3. If no provided_data has been passed, just return here */
+    if (hmac_inputs_num == 0) {
+        return err;
+    }
+
+    /* 4. K = HMAC(K, V || 0x01 || provided_data) */
+    err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, &byte1, sizeof(byte1));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    for (idx = 0; idx < hmac_inputs_num && hmac_inputs_len[idx] != 0; idx++) {
+        err = cc3xx_hmac_update(&state->h, hmac_inputs[idx], hmac_inputs_len[idx]);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+    }
+
+    err = cc3xx_hmac_finish(&state->h, state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    /* 5. V = HMAC(K, V) */
+    err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+    err = cc3xx_hmac_finish(&state->h, state->block_v, sizeof(state->block_v));
+
+    /* return updated (K, V) state */
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hmac_instantiate(
+    struct cc3xx_drbg_hmac_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len)
+{
+    cc3xx_err_t err;
+
+    /* Initialize the state */
+    memset(state->block_v, 0x01, sizeof(state->block_v));
+    memset(state->key_k, 0x00, sizeof(state->key_k));
+
+    /* Prepare the seed material to be passed to update() */
+    const uint8_t *seed[3] = {entropy, nonce, personalization};
+    const size_t seed_len[3] = {entropy_len, nonce_len, personalization_len};
+
+    err = cc3xx_drbg_hmac_update(3, state, seed, seed_len);
+
+    state->reseed_counter = 1;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hmac_generate(
+    struct cc3xx_drbg_hmac_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+    size_t generated_bits = 0;
+    const uint8_t *data[3] = {NULL};
+    size_t data_len[3] = {0};
+    size_t idx;
+    size_t last_hmac_update_num = 0;
+
+    if (state->reseed_counter == UINT32_MAX) {
+        /* When we reach 2^32 invocations we must reseed */
+        return CC3XX_ERR_DRBG_RESEED_REQUIRED;
+    }
+
+    if (additional_input_len && additional_input != NULL) {
+        data[0] = additional_input;
+        data_len[0] = additional_input_len;
+        err = cc3xx_drbg_hmac_update(1, state, data, data_len);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+    }
+
+    /* While len(temp) < requested_number_of_bits, as per spec */
+    while (generated_bits < len_bits) {
+        uint32_t temp[CC3XX_DRBG_HMAC_OUTLEN/4];
+        size_t bytes_to_copy;
+        /* V = HMAC(K, V) */
+        err = cc3xx_hmac_set_key(&state->h, (const uint8_t *)state->key_k, sizeof(state->key_k));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        err = cc3xx_hmac_update(&state->h, (const uint8_t *)state->block_v, sizeof(state->block_v));
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+        err = cc3xx_hmac_finish(&state->h, temp, CC3XX_DRBG_HMAC_OUTLEN);
+        if (err != CC3XX_ERR_SUCCESS) {
+            return err;
+        }
+
+        bytes_to_copy = len_bits - generated_bits < BYTES_TO_BITS(CC3XX_DRBG_HMAC_OUTLEN) ?
+                        BITS_TO_BYTES(len_bits - generated_bits) : CC3XX_DRBG_HMAC_OUTLEN;
+        memcpy(&returned_bits[BITS_TO_BYTES(generated_bits)], temp, bytes_to_copy);
+
+        generated_bits += BYTES_TO_BITS(CC3XX_DRBG_HMAC_OUTLEN);
+
+        memcpy(state->block_v, temp, CC3XX_DRBG_HMAC_OUTLEN);
+    }
+
+    /* We need to mask the last byte in case len_bits % 8 is different than 0 */
+    if (len_bits % 8) {
+        uint8_t mask = 0UL;
+        for (idx = 0; idx < len_bits % 8; idx++) {
+            mask |= 1UL << (8 - idx - 1);
+        }
+
+        returned_bits[BITS_TO_BYTES(len_bits) - 1] &= mask;
+    }
+
+    /* The update is done with no additional_input to update() */
+    if (additional_input != NULL && additional_input_len != 0) {
+        data[0] = additional_input;
+        data_len[0] = additional_input_len;
+        last_hmac_update_num = 1;
+    }
+
+    err = cc3xx_drbg_hmac_update(last_hmac_update_num, state, data, data_len);
+
+    state->reseed_counter++;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hmac_reseed(
+    struct cc3xx_drbg_hmac_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len)
+{
+    cc3xx_err_t err;
+
+    /* The update is done with no personalization string update() */
+    const uint8_t *data[3] = {entropy, additional_input, NULL};
+    const size_t data_len[3] = {entropy_len, additional_input_len, 0};
+
+    err = cc3xx_drbg_hmac_update(2, state, data, data_len);
+    if (err != CC3XX_ERR_SUCCESS) {
+        return err;
+    }
+
+    state->reseed_counter = 1;
+
+    return err;
+}
+
+cc3xx_err_t cc3xx_drbg_hmac_uninit(struct cc3xx_drbg_hmac_state_t *state)
+{
+    cc3xx_secure_erase_buffer((uint32_t *)state, sizeof(struct cc3xx_drbg_hmac_state_t)/4);
+    return CC3XX_ERR_SUCCESS;
+}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.h
new file mode 100644
index 0000000..c368f33
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_drbg_hmac.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CC3XX_DRBG_HMAC_H__
+#define __CC3XX_DRBG_HMAC_H__
+
+#include <stdint.h>
+#include "cc3xx_error.h"
+
+#include "cc3xx_hmac.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The assumption is that it will be a multiple of 4. It depends on the
+ *        underlying hash function being used, which for the cc3xx driver is
+ *        retricted to SHA-256
+ */
+#define CC3XX_DRBG_HMAC_OUTLEN SHA256_OUTPUT_SIZE
+
+/**
+ * @brief Contains the state of the HMAC_DRBG
+ *
+ */
+struct cc3xx_drbg_hmac_state_t {
+    struct cc3xx_hmac_state_t h;
+    uint32_t block_v[CC3XX_DRBG_HMAC_OUTLEN / sizeof(uint32_t)];
+    uint32_t key_k[CC3XX_DRBG_HMAC_OUTLEN / sizeof(uint32_t)];
+    uint32_t reseed_counter;
+};
+
+/**
+ * @brief Instantiate the HMAC_DRBG
+ *
+ * @param state A pointer to a state structure
+ * @param entropy Buffer containing the entropy for the instantiation
+ * @param entropy_len Size in bytes of the entropy buffer \param entropy
+ * @param nonce Buffer containing the nonce
+ * @param nonce_len Size in bytes of the nonce buffer \param nonce
+ * @param personalization Buffer containing the personalization string
+ * @param personalization_len Size in bytes of the personalization buffer \param personalization
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hmac_instantiate(
+    struct cc3xx_drbg_hmac_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *nonce, size_t nonce_len,
+    const uint8_t *personalization, size_t personalization_len);
+
+/**
+ * @brief Generate up to len bytes of data
+ *
+ * @param state A pointer to a state structure
+ * @param len_bits Size in bits to be generated. Note that this does not need to be byte aligned.
+ * @param returned_bits Buffer to hold returned bits, must be of size ceil(len_bits/8) bytes
+ * @param additional_input Optional pointer containing the additional input to be added
+ * @param additional_input_len Size in bytes of the additional input \param additional_input
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hmac_generate(
+    struct cc3xx_drbg_hmac_state_t *state,
+    size_t len_bits, uint8_t *returned_bits,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Reseeds the HMAC_DRBG
+ *
+ * @param state A pointer to a state structure
+ * @param entropy Entropy to be used for reseeding
+ * @param entropy_len Size in bytes of the entropy pointed by \param entropy
+ * @param additional_input Optional pointer containing additional input for reseeding
+ * @param additional_input_len Size in bytes of the buffer pointed by \param additional_input
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hmac_reseed(
+    struct cc3xx_drbg_hmac_state_t *state,
+    const uint8_t *entropy, size_t entropy_len,
+    const uint8_t *additional_input, size_t additional_input_len);
+
+/**
+ * @brief Un-initializes the state structure associated to the HMAC_DRBG
+ *
+ * @param state Pointer to the structure
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_drbg_hmac_uninit(struct cc3xx_drbg_hmac_state_t *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CC3XX_DRBG_HMAC_H__ */
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_error.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_error.h
index 312085f..9811748 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_error.h
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_error.h
@@ -34,6 +34,9 @@
     CC3XX_ERR_GCM_VARIABLE_IV_NOT_IMPLEMENTED,
     CC3XX_ERR_CHACHA_IV_SIZE_INCORRECT,
     CC3XX_ERR_DFA_VIOLATION,
+    CC3XX_ERR_DRBG_RESEED_REQUIRED,
+    CC3XX_ERR_DRBG_INVALID_ID,
+    CC3XX_ERR_MAX_VALUE = UINT32_MAX
 };
 
 #ifdef __cplusplus
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
index 1db4517..0e9709b 100644
--- a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hash.h
@@ -37,7 +37,7 @@
 
 /**
  * \brief                        Initialize a hash operation.
-
+ *
  * \param[in]  alg               Which hash algorithm should be initialized.
  *
  * \return                       CC3XX_ERR_SUCCESS on success, another
@@ -47,7 +47,7 @@
 
 /**
  * \brief                        Input data into a hash operation.
-
+ *
  * \param[in]  buf               A pointer to the data to be input.
  * \param[in]  length            The size of the data to be input.
  *
@@ -59,8 +59,8 @@
 /**
  * \brief                        Get the current state of the hash operation.
  *                               Allows for restartable hash operations.
-
- * \param[out] state            The cc3xx_hash_state_t to write the state into.
+ *
+ * \param[out] state             The cc3xx_hash_state_t to write the state into.
  */
 void cc3xx_hash_get_state(struct cc3xx_hash_state_t *state);
 
@@ -68,27 +68,27 @@
  * \brief                        Set the current state of the hash operation.
  *                               Allows for restartable hash operations.
  *
- * \note                         This funtion initializes the hardware, there is
- *                               no need to seperately call cc3xx_hash_init.
-
- * \param[in]  state            The cc3xx_hash_state_t to read the state from.
+ * \note                         This function initializes the hardware, there is
+ *                               no need to separately call cc3xx_hash_init.
+ *
+ * \param[in]  state             The cc3xx_hash_state_t to read the state from.
  */
 void cc3xx_hash_set_state(const struct cc3xx_hash_state_t *state);
 
 /**
  * \brief                        Finish a hash operation, and output the hash.
  *
- * \param[out]  res             The result of the hash operation.
- * \param[in]   length          The size of the result buffer. Must match the
- *                              hash output size. Checked by assert only.
+ * \param[out]  res              The result of the hash operation.
+ * \param[in]   length           The size of the result buffer. Must match the
+ *                               hash output size. Checked by assert only.
  */
 void cc3xx_hash_finish(uint32_t *res, size_t length);
 
 /**
- * \brief                       Uninitialize the hash engine.
+ * \brief                        Uninitialize the hash engine.
  *
- * \note                        The hash engine is not implicitly uninitialized
- *                              on an error.
+ * \note                         The hash engine is not implicitly uninitialized
+ *                               on an error.
  *
  */
 void cc3xx_hash_uninit(void);
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c
new file mode 100644
index 0000000..07841eb
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include "cc3xx_hash.h"
+#include "cc3xx_hmac.h"
+
+#define SHA256_BLOCK_SIZE (64)
+
+/* Hardcode support for SHA-256 based HMAC only */
+static const cc3xx_hash_alg_t alg = CC3XX_HASH_ALG_SHA256;
+
+cc3xx_err_t cc3xx_hmac_set_key(
+    struct cc3xx_hmac_state_t *state,
+    const uint8_t *key,
+    size_t key_size)
+{
+    const uint8_t ipad = 0x36;
+    cc3xx_err_t err;
+    size_t idx;
+    /* In case the key is higher than B, it must be hashed first */
+    uint32_t hash_key_output[SHA256_BLOCK_SIZE / sizeof(uint32_t)];
+    const uint8_t *p_key = key;
+    size_t key_length = key_size;
+
+    if ((err = cc3xx_hash_init(alg)) != CC3XX_ERR_SUCCESS)
+        goto out;
+
+    if (key_size > CC3XX_HMAC_BLOCK_SIZE) {
+        /* hash the key to L bytes */
+        err = cc3xx_hash_update(key, key_size);
+        if (err != CC3XX_ERR_SUCCESS) {
+            goto out;
+        }
+        p_key = (const uint8_t *)hash_key_output;
+        key_length = SHA256_OUTPUT_SIZE;
+    }
+
+    cc3xx_hash_finish(hash_key_output, sizeof(hash_key_output));
+
+    /* K ^ ipad */
+    for (idx = 0; idx < key_length; idx++) {
+        state->key[idx] = p_key[idx] ^ ipad;
+    }
+
+    memset(&state->key[key_length], ipad, CC3XX_HMAC_BLOCK_SIZE - key_length);
+
+    /* H(K ^ ipad) */
+    if ((err = cc3xx_hash_init(alg)) != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    err = cc3xx_hash_update(state->key, CC3XX_HMAC_BLOCK_SIZE);
+
+out:
+    if (err == CC3XX_ERR_SUCCESS) {
+        cc3xx_hash_get_state(&state->hash);
+    }
+    cc3xx_hash_uninit();
+    return err;
+}
+
+cc3xx_err_t cc3xx_hmac_update(
+    struct cc3xx_hmac_state_t *state,
+    const uint8_t *data,
+    size_t data_length)
+{
+    cc3xx_err_t err;
+
+    cc3xx_hash_set_state(&state->hash);
+
+    /* H(K ^ ipad | data)*/
+    err = cc3xx_hash_update(data, data_length);
+
+    if (err == CC3XX_ERR_SUCCESS) {
+        cc3xx_hash_get_state(&state->hash);
+    }
+    cc3xx_hash_uninit();
+    return err;
+}
+
+cc3xx_err_t cc3xx_hmac_finish(
+    struct cc3xx_hmac_state_t *state,
+    uint32_t *tag,
+    size_t tag_size)
+{
+    uint32_t scratch[SHA256_OUTPUT_SIZE / sizeof(uint32_t)];
+    const uint8_t ixopad = 0x36 ^ 0x5c; /* ipad ^ opad */
+    cc3xx_err_t err;
+    size_t idx;
+
+    assert(tag_size >= SHA256_OUTPUT_SIZE);
+
+    cc3xx_hash_set_state(&state->hash);
+
+    /* Produce H(K ^ ipad | data) */
+    cc3xx_hash_finish(scratch, sizeof(scratch));
+
+    /* K ^ opad */
+    for (idx = 0; idx < CC3XX_HMAC_BLOCK_SIZE; idx++) {
+        state->key[idx] ^= ixopad;
+    }
+
+    /* H( K ^ opad | H(K ^ ipad | data)) */
+    err = cc3xx_hash_init(alg);
+    if (err != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    err = cc3xx_hash_update(state->key, CC3XX_HMAC_BLOCK_SIZE);
+    if (err != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    err = cc3xx_hash_update((const uint8_t *)scratch, sizeof(scratch));
+    if (err != CC3XX_ERR_SUCCESS) {
+        goto out;
+    }
+
+    cc3xx_hash_finish(tag, tag_size);
+
+out:
+    if (err == CC3XX_ERR_SUCCESS) {
+        cc3xx_hash_get_state(&state->hash);
+    }
+    cc3xx_hash_uninit();
+    return err;
+}
diff --git a/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h
new file mode 100644
index 0000000..5866e8b
--- /dev/null
+++ b/platform/ext/accelerator/cc312/cc312-rom/cc3xx_hmac.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CC3XX_HMAC_H__
+#define __CC3XX_HMAC_H__
+
+#include <stdint.h>
+#include "cc3xx_error.h"
+#include "cc3xx_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The size in Bytes, i.e. B, associated to the HMAC block size
+ *
+ */
+#define CC3XX_HMAC_BLOCK_SIZE (64)
+
+/**
+ * @brief Contains the state of the HMAC operation
+ *
+ */
+struct cc3xx_hmac_state_t {
+    uint8_t key[CC3XX_HMAC_BLOCK_SIZE];
+    struct cc3xx_hash_state_t hash; /* Allows to restart low-level hash */
+} __attribute__((aligned(4)));
+
+/**
+ * @brief Sets the key for the HMAC operation on the state
+ *
+ * @param state A pointer to a state structure
+ * @param key Buffer containing the key
+ * @param key_size Size in bytes of the buffer \param key
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_hmac_set_key(
+    struct cc3xx_hmac_state_t *state,
+    const uint8_t *key,
+    size_t key_size);
+
+/**
+ * @brief Update the HMAC operation with a new chunk of data to authenticate
+ *
+ * @param state A pointer to a state structure
+ * @param data Buffer containing the data to use for the update
+ * @param data_length Size in bytes of the buffer \param data
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_hmac_update(
+    struct cc3xx_hmac_state_t *state,
+    const uint8_t *data,
+    size_t data_length);
+
+/**
+ * @brief Finalize the HMAC operation by producing the authentication tag
+ *
+ * @param state A pointer to a state structure
+ * @param tag Output buffer
+ * @param tag_size Size in bytes of the buffer \param tag
+ * @return cc3xx_err_t
+ */
+cc3xx_err_t cc3xx_hmac_finish(
+    struct cc3xx_hmac_state_t *state,
+    uint32_t *tag,
+    size_t tag_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CC3XX_HMAC_H__ */
diff --git a/platform/ext/target/arm/rss/common/cc312/cc3xx_config.h b/platform/ext/target/arm/rss/common/cc312/cc3xx_config.h
index 9e1f038..5eb74e9 100644
--- a/platform/ext/target/arm/rss/common/cc312/cc3xx_config.h
+++ b/platform/ext/target/arm/rss/common/cc312/cc3xx_config.h
@@ -73,6 +73,13 @@
 /* Whether RNG is enabled */
 #define CC3XX_CONFIG_RNG_ENABLE
 
+/* Whether the CTR_DRBG is enabled through the generic interface */
+#define CC3XX_CONFIG_DRBG_CTR_ENABLE
+/* Whether the HMAC_DRBG is enabled through the generic interface */
+#define CC3XX_CONFIG_DRBG_HMAC_ENABLE
+/* Whether the HASH_DRBG is enabled through the generic interface */
+#define CC3XX_CONFIG_DRBG_HASH_ENABLE
+
 /* Whether an external TRNG should be used in place of the standard CC3XX TRNG */
 #ifdef RSS_OTP_TRNG
 #define CC3XX_CONFIG_RNG_EXTERNAL_TRNG