DPE: Add CDI and key pair derivation

Signed-off-by: Maulik Patel <maulik.patel@arm.com>
Change-Id: I33854414c5206b65831687f3280f125327763227
diff --git a/partitions/dice_protection_environment/CMakeLists.txt b/partitions/dice_protection_environment/CMakeLists.txt
index b5eb637..6f2fb34 100644
--- a/partitions/dice_protection_environment/CMakeLists.txt
+++ b/partitions/dice_protection_environment/CMakeLists.txt
@@ -21,6 +21,7 @@
     PRIVATE
         dpe_cmd_decode.c
         dpe_context_mngr.c
+        dpe_crypto_interface.c
         dpe_impl.c
         dpe_log.c
         dpe_req_mngr.c
diff --git a/partitions/dice_protection_environment/dpe_context_mngr.c b/partitions/dice_protection_environment/dpe_context_mngr.c
index 8750922..0b826a8 100644
--- a/partitions/dice_protection_environment/dpe_context_mngr.c
+++ b/partitions/dice_protection_environment/dpe_context_mngr.c
@@ -9,9 +9,21 @@
 #include <assert.h>
 #include <string.h>
 #include "dice_protection_environment.h"
+#include "dpe_crypto_interface.h"
 #include "dpe_log.h"
 #include "psa/crypto.h"
 
+#ifdef TFM_S_REG_TEST
+#define TEST_ROT_CDI_VAL {                                                  \
+                            0xD2, 0x90, 0x66, 0x07, 0x2A, 0x2D, 0x2A, 0x00, \
+                            0x91, 0x9D, 0xD9, 0x15, 0x14, 0xBE, 0x2D, 0xCC, \
+                            0xA3, 0x9F, 0xDE, 0xC3, 0x35, 0x75, 0x84, 0x6E, \
+                            0x4C, 0xB9, 0x28, 0xAC, 0x7A, 0x4E, 0X00, 0x7F  \
+                         }
+#endif /* TFM_S_REG_TEST */
+
+#define CONTEXT_DATA_MAX_SIZE sizeof(struct component_context_data_t)
+
 static struct component_context_t component_ctx_array[MAX_NUM_OF_COMPONENTS];
 static struct layer_context_t layer_ctx_array[MAX_NUM_OF_LAYERS];
 
@@ -80,6 +92,8 @@
 {
     layer_ctx_array[i].state = LAYER_STATE_CLOSED;
     layer_ctx_array[i].parent_layer_idx = INVALID_LAYER_IDX;
+    (void)psa_destroy_key(layer_ctx_array[i].data.cdi_key_id);
+    (void)psa_destroy_key(layer_ctx_array[i].data.attest_key_id);
     (void)memset(&layer_ctx_array[i].data, 0, sizeof(struct layer_context_data_t));
 }
 
@@ -177,11 +191,143 @@
     return false;
 }
 
-static dpe_error_t derive_child_create_certificate(uint16_t curr_idx)
+/* Attest_CDI Input requires {measurement_value, config, authority, mode, hidden} in
+ * same order
+ */
+static psa_status_t get_component_data_for_attest_cdi(uint8_t *dest_buf,
+                                                      size_t max_size,
+                                                      size_t *dest_size,
+                                                      const struct component_context_t *comp_ctx)
 {
-    //TODO: Implementation pending
+    size_t out_size = 0;
+
+    if ((DICE_HASH_SIZE + DICE_INLINE_CONFIG_SIZE + DICE_HASH_SIZE +
+         sizeof(comp_ctx->data.mode) + DICE_HIDDEN_SIZE > max_size )) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    memcpy(&dest_buf[out_size], comp_ctx->data.measurement_value, DICE_HASH_SIZE);
+    out_size += DICE_HASH_SIZE;
+
+    memcpy(&dest_buf[out_size], comp_ctx->data.config_value, DICE_INLINE_CONFIG_SIZE);
+    out_size += DICE_INLINE_CONFIG_SIZE;
+
+    memcpy(&dest_buf[out_size], comp_ctx->data.signer_id, DICE_HASH_SIZE);
+    out_size += DICE_HASH_SIZE;
+
+    memcpy(&dest_buf[out_size], &comp_ctx->data.mode, sizeof(comp_ctx->data.mode));
+    out_size += sizeof(comp_ctx->data.mode);
+
+    memcpy(&dest_buf[out_size], comp_ctx->data.hidden, DICE_HIDDEN_SIZE);
+    out_size += DICE_HIDDEN_SIZE;
+
+    *dest_size = out_size;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t compute_layer_cdi_attest_input(uint16_t curr_layer_idx)
+{
+    psa_status_t status;
+    uint8_t component_ctx_data[CONTEXT_DATA_MAX_SIZE];
+    size_t ctx_data_size, hash_len;
+    int idx;
+
+    psa_hash_operation_t hash_op = psa_hash_operation_init();
+    status = psa_hash_setup(&hash_op, DPE_HASH_ALG);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    //TODO:
+    /* How to combine measurements of multiple SW components into a single hash
+     * is not yet defined by the Open DICE profile. This implementation
+     * concatenates the data of all SW components which belong to the same layer
+     * and hash it.
+     */
+    for (idx = 0; idx < MAX_NUM_OF_COMPONENTS; idx++) {
+        if (component_ctx_array[idx].linked_layer_idx == curr_layer_idx) {
+            /* This component belongs to current layer */
+            /* Concatenate all context data for this component */
+            status = get_component_data_for_attest_cdi(component_ctx_data,
+                                                       sizeof(component_ctx_data),
+                                                       &ctx_data_size,
+                                                       &component_ctx_array[idx]);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            status = psa_hash_update(&hash_op,
+                                     component_ctx_data,
+                                     ctx_data_size);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+    }
+
+    status = psa_hash_finish(&hash_op,
+                             &layer_ctx_array[curr_layer_idx].attest_cdi_hash_input[0],
+                             sizeof(layer_ctx_array[curr_layer_idx].attest_cdi_hash_input),
+                             &hash_len);
+
+    assert(hash_len == DPE_HASH_ALG_SIZE);
+
+    return status;
+}
+
+static dpe_error_t derive_child_create_certificate(uint16_t layer_idx)
+{
+    uint16_t parent_idx;
+    psa_status_t status;
+
+    assert(layer_idx < MAX_NUM_OF_LAYERS);
     /* Finalise the layer */
-    layer_ctx_array[curr_idx].state = LAYER_STATE_FINALISED;
+    layer_ctx_array[layer_idx].state = LAYER_STATE_FINALISED;
+
+    /* For RoT Layer, CDI values are calculated by BL1_1 */
+    if (layer_idx != DPE_ROT_LAYER_IDX) {
+
+        parent_idx = layer_ctx_array[layer_idx].parent_layer_idx;
+        assert(parent_idx < MAX_NUM_OF_LAYERS);
+
+        status = compute_layer_cdi_attest_input(layer_idx);
+        if (status != PSA_SUCCESS) {
+            return DPE_INTERNAL_ERROR;
+        }
+
+        status = derive_attestation_cdi(&layer_ctx_array[layer_idx],
+                                        &layer_ctx_array[parent_idx]);
+        if (status != PSA_SUCCESS) {
+            return DPE_INTERNAL_ERROR;
+        }
+
+        status = derive_sealing_cdi(&layer_ctx_array[layer_idx]);
+        if (status != PSA_SUCCESS) {
+            return DPE_INTERNAL_ERROR;
+        }
+    }
+
+    status = derive_wrapping_key(&layer_ctx_array[layer_idx]);
+    if (status != PSA_SUCCESS) {
+        return DPE_INTERNAL_ERROR;
+    }
+
+    status = derive_attestation_key(&layer_ctx_array[layer_idx]);
+    if (status != PSA_SUCCESS) {
+        return DPE_INTERNAL_ERROR;
+    }
+
+    status = create_layer_certificate(&layer_ctx_array[layer_idx]);
+    if (status != PSA_SUCCESS) {
+        return DPE_INTERNAL_ERROR;
+    }
+
+    status = store_layer_certificate(&layer_ctx_array[layer_idx]);
+    if (status != PSA_SUCCESS) {
+        return DPE_INTERNAL_ERROR;
+    }
+
     return DPE_NO_ERROR;
 }
 
@@ -304,12 +450,24 @@
                                  int *new_child_ctx_handle,
                                  int *new_parent_ctx_handle)
 {
-    dpe_error_t status;
+    dpe_error_t err;
     struct component_context_t *child_ctx, *parent_ctx, *new_ctx;
     uint16_t input_child_idx, input_parent_idx;
 
 #ifdef TFM_S_REG_TEST
+    //TODO: Remove this TEST_ROT_CDI_VAL CDI once actual CDI is calculated by BL1_1
+    psa_status_t status;
+    uint8_t dpe_rot_cdi[DICE_CDI_SIZE] = TEST_ROT_CDI_VAL;
+
     if (layer_ctx_array[DPE_ROT_LAYER_IDX].state != LAYER_STATE_FINALISED) {
+
+        status = create_layer_cdi_key(&layer_ctx_array[DPE_ROT_LAYER_IDX],
+                                      &dpe_rot_cdi[0],
+                                      sizeof(dpe_rot_cdi));
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
         return derive_rot_context(dice_inputs,
                                   new_child_ctx_handle,
                                   new_parent_ctx_handle);
@@ -348,15 +506,15 @@
     }
 
     /* Copy dice input to the child component context */
-    status = copy_dice_input(child_ctx, dice_inputs);
-    if (status != DPE_NO_ERROR) {
-        return status;
+    err = copy_dice_input(child_ctx, dice_inputs);
+    if (err != DPE_NO_ERROR) {
+        return err;
     }
 
     if (create_certificate) {
-        status = derive_child_create_certificate(child_ctx->linked_layer_idx);
-        if (status != DPE_NO_ERROR) {
-            return status;
+        err = derive_child_create_certificate(child_ctx->linked_layer_idx);
+        if (err != DPE_NO_ERROR) {
+            return err;
         }
     }
 
diff --git a/partitions/dice_protection_environment/dpe_context_mngr.h b/partitions/dice_protection_environment/dpe_context_mngr.h
index 8e679f6..807de46 100644
--- a/partitions/dice_protection_environment/dpe_context_mngr.h
+++ b/partitions/dice_protection_environment/dpe_context_mngr.h
@@ -12,6 +12,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include "dice_protection_environment.h"
+#include "dpe_crypto_config.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -66,9 +67,10 @@
 };
 
 struct layer_context_data_t {
-    uint8_t cdi_attest[DICE_CDI_SIZE];
+    psa_key_id_t cdi_key_id;
     uint8_t cdi_seal[DICE_CDI_SIZE];
     uint8_t wrapping_key[DICE_WRAPPING_KEY_SIZE];
+    psa_key_id_t attest_key_id;
     uint8_t cert_buf[DICE_CERT_SIZE];
     size_t cert_buf_size;
 };
@@ -82,6 +84,7 @@
 struct layer_context_t {
     struct layer_context_data_t data;
     uint16_t parent_layer_idx;
+    uint8_t attest_cdi_hash_input[DPE_HASH_ALG_SIZE];
     enum layer_state_t state;
 };
 
diff --git a/partitions/dice_protection_environment/dpe_crypto_config.h b/partitions/dice_protection_environment/dpe_crypto_config.h
new file mode 100644
index 0000000..8bef476
--- /dev/null
+++ b/partitions/dice_protection_environment/dpe_crypto_config.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __DPE_CRYPTO_CONFIG_H__
+#define __DPE_CRYPTO_CONFIG_H__
+
+#include "psa/crypto.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DPE Crypto configuration for CDI derivation */
+#define DPE_HASH_ALG      PSA_ALG_SHA_256
+#define DPE_HASH_ALG_SIZE PSA_HASH_LENGTH(DPE_HASH_ALG)
+
+#define DPE_CDI_KEY_TYPE  PSA_KEY_TYPE_DERIVE
+#define DPE_CDI_KEY_ALG   PSA_ALG_HKDF(PSA_ALG_SHA_256)
+#define DPE_CDI_KEY_BITS  256
+#define DPE_CDI_KEY_USAGE PSA_KEY_USAGE_DERIVE
+
+/* Below labels as per
+ * https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#attestation-cdi
+ */
+#define DPE_ATTEST_CDI_LABEL "CDI_Attest"
+#define DPE_SEAL_CDI_LABEL   "CDI_Seal"
+
+#define DPE_ATTEST_KEY_CURVE_TYPE PSA_ECC_FAMILY_SECP_R1
+#define DPE_ATTEST_KEY_TYPE       PSA_KEY_TYPE_ECC_KEY_PAIR(DPE_ATTEST_KEY_CURVE_TYPE)
+#define DPE_ATTEST_KEY_ALG        PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+#define DPE_ATTEST_KEY_BITS       PSA_BYTES_TO_BITS(PSA_HASH_LENGTH(PSA_ALG_SHA_256))
+#define DPE_ATTEST_KEY_USAGE      PSA_KEY_USAGE_SIGN_HASH
+
+#define DPE_ATTEST_KEY_PAIR_LABEL "Key Pair"
+#define DPE_ATTEST_KEY_SALT {                                         \
+    0x63, 0xB6, 0xA0, 0x4D, 0x2C, 0x07, 0x7F, 0xC1, 0x0F, 0x63, 0x9F, \
+    0x21, 0xDA, 0x79, 0x38, 0x44, 0x35, 0x6C, 0xC2, 0xB0, 0xB4, 0x41, \
+    0xB3, 0xA7, 0x71, 0x24, 0x03, 0x5C, 0x03, 0xF8, 0xE1, 0xBE, 0x60, \
+    0x35, 0xD3, 0x1F, 0x28, 0x28, 0x21, 0xA7, 0x45, 0x0A, 0x02, 0x22, \
+    0x2A, 0xB1, 0xB3, 0xCF, 0xF1, 0x67, 0x9B, 0x05, 0xAB, 0x1C, 0xA5, \
+    0xD1, 0xAF, 0xFB, 0x78, 0x9C, 0xCD, 0x2B, 0x0B, 0x3B }
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DPE_CRYPTO_CONFIG_H__ */
diff --git a/partitions/dice_protection_environment/dpe_crypto_interface.c b/partitions/dice_protection_environment/dpe_crypto_interface.c
new file mode 100644
index 0000000..8f83666
--- /dev/null
+++ b/partitions/dice_protection_environment/dpe_crypto_interface.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "dpe_crypto_interface.h"
+#include <stdbool.h>
+#include <string.h>
+#include "dpe_context_mngr.h"
+#include "dpe_crypto_config.h"
+#include "psa/crypto.h"
+#include "tfm_crypto_defs.h"
+
+static const char attest_cdi_label[] = DPE_ATTEST_CDI_LABEL;
+static const char attest_key_pair_label[] = DPE_ATTEST_KEY_PAIR_LABEL;
+static const uint8_t attest_key_salt[] = DPE_ATTEST_KEY_SALT;
+
+static psa_status_t perform_derivation(psa_key_id_t base_key,
+                                       const psa_key_attributes_t *key_attr,
+                                       const uint8_t *key_label,
+                                       size_t key_label_len,
+                                       const uint8_t *salt,
+                                       size_t salt_len,
+                                       psa_key_id_t *out_key_id)
+{
+    psa_status_t status;
+    psa_key_derivation_operation_t op = PSA_KEY_DERIVATION_OPERATION_INIT;
+
+    assert((key_label_len != 0) && (key_label != NULL) &&
+           (base_key != 0) && (key_attr != NULL) &&
+           (salt_len != 0) && (salt != NULL));
+
+    status = psa_key_derivation_setup(&op, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_key_derivation_input_bytes(&op, PSA_KEY_DERIVATION_INPUT_SALT,
+                                            salt, salt_len);
+    if (status != PSA_SUCCESS) {
+        goto err_abort;
+    }
+
+    status = psa_key_derivation_input_key(&op, PSA_KEY_DERIVATION_INPUT_SECRET,
+                                          base_key);
+    if (status != PSA_SUCCESS) {
+        goto err_abort;
+    }
+
+    /* Supply the key label as an input to the key derivation */
+    status = psa_key_derivation_input_bytes(&op, PSA_KEY_DERIVATION_INPUT_INFO,
+                                           key_label, key_label_len);
+    if (status != PSA_SUCCESS) {
+        goto err_abort;
+    }
+
+    status = psa_key_derivation_output_key(key_attr, &op, out_key_id);
+    if (status != PSA_SUCCESS) {
+        goto err_abort;
+    }
+
+    /* Free resources associated with the key derivation operation */
+    status = psa_key_derivation_abort(&op);
+    if (status == PSA_SUCCESS) {
+        goto done;
+    }
+
+    (void)psa_destroy_key(*out_key_id);
+
+err_abort:
+    (void)psa_key_derivation_abort(&op);
+
+done:
+    return status;
+}
+
+psa_status_t derive_attestation_cdi(struct layer_context_t *layer_ctx,
+                                    const struct layer_context_t *parent_layer_ctx)
+{
+    psa_key_attributes_t derive_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Set key attributes for CDI key */
+    psa_set_key_type(&derive_key_attr, DPE_CDI_KEY_TYPE);
+    psa_set_key_algorithm(&derive_key_attr, DPE_CDI_KEY_ALG);
+    psa_set_key_bits(&derive_key_attr, DPE_CDI_KEY_BITS);
+    psa_set_key_usage_flags(&derive_key_attr, DPE_CDI_KEY_USAGE);
+
+    /* Perform CDI derivation */
+    /* Parent layer CDI is the base key (input secret to key derivation) */
+    return perform_derivation(parent_layer_ctx->data.cdi_key_id,
+                              &derive_key_attr,
+                              (uint8_t *) &attest_cdi_label[0],
+                              sizeof(attest_cdi_label),
+                              layer_ctx->attest_cdi_hash_input,
+                              sizeof(layer_ctx->attest_cdi_hash_input),
+                              &layer_ctx->data.cdi_key_id);
+}
+
+psa_status_t derive_attestation_key(struct layer_context_t *layer_ctx)
+{
+    psa_key_attributes_t attest_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Set key attributes for Attest key pair derivation */
+    psa_set_key_type(&attest_key_attr, DPE_ATTEST_KEY_TYPE);
+    psa_set_key_algorithm(&attest_key_attr, DPE_ATTEST_KEY_ALG);
+    psa_set_key_bits(&attest_key_attr, DPE_ATTEST_KEY_BITS);
+    psa_set_key_usage_flags(&attest_key_attr, DPE_ATTEST_KEY_USAGE);
+
+    /* Perform key pair derivation */
+    return perform_derivation(layer_ctx->data.cdi_key_id,
+                              &attest_key_attr,
+                              (uint8_t *)&attest_key_pair_label[0],
+                              sizeof(attest_key_pair_label),
+                              attest_key_salt,
+                              sizeof(attest_key_salt),
+                              &layer_ctx->data.attest_key_id);
+}
+
+psa_status_t create_layer_cdi_key(struct layer_context_t *layer_ctx,
+                                  const uint8_t *cdi_input,
+                                  size_t cdi_input_size)
+{
+    psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Set key attributes for CDI key */
+    psa_set_key_type(&base_attributes, DPE_CDI_KEY_TYPE);
+    psa_set_key_algorithm(&base_attributes, DPE_CDI_KEY_ALG);
+    psa_set_key_bits(&base_attributes, DPE_CDI_KEY_BITS);
+    psa_set_key_usage_flags(&base_attributes, DPE_CDI_KEY_USAGE);
+
+    return psa_import_key(&base_attributes,
+                          cdi_input,
+                          cdi_input_size,
+                          &layer_ctx->data.cdi_key_id);
+}
+
+psa_status_t derive_sealing_cdi(struct layer_context_t *layer_ctx)
+{
+    //TODO:
+    (void)layer_ctx;
+    return PSA_SUCCESS;
+}
+
+psa_status_t derive_wrapping_key(struct layer_context_t *layer_ctx)
+{
+    //TODO:
+    (void)layer_ctx;
+    return PSA_SUCCESS;
+}
+
+psa_status_t create_layer_certificate(struct layer_context_t *layer_ctx)
+{
+    //TODO:
+    (void)layer_ctx;
+    return PSA_SUCCESS;
+}
+
+psa_status_t store_layer_certificate(struct layer_context_t *layer_ctx)
+{
+    //TODO:
+    (void)layer_ctx;
+    return PSA_SUCCESS;
+}
diff --git a/partitions/dice_protection_environment/dpe_crypto_interface.h b/partitions/dice_protection_environment/dpe_crypto_interface.h
new file mode 100644
index 0000000..02ab5b1
--- /dev/null
+++ b/partitions/dice_protection_environment/dpe_crypto_interface.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __DPE_CRYPTO_INTERFACE_H__
+#define __DPE_CRYPTO_INTERFACE_H__
+
+#include <stddef.h>
+#include <stdint.h>
+#include "dpe_context_mngr.h"
+#include "psa/error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Derives attestation key pair for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t derive_attestation_key(struct layer_context_t *layer_ctx);
+
+/**
+ * \brief Creates a layer's CDI key from input.
+ *
+ * \param[in] layer_ctx       Pointer to layer context.
+ * \param[in] cdi_input       Pointer to the input buffer.
+ * \param[in] cdi_input_size  Size of the input buffer.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t create_layer_cdi_key(struct layer_context_t *layer_ctx,
+                                  const uint8_t *cdi_input,
+                                  size_t cdi_input_size);
+
+/**
+ * \brief Derives attestation CDI for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ * \param[in] parent_layer_ctx  Pointer to parent layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t derive_attestation_cdi(struct layer_context_t *layer_ctx,
+                                    const struct layer_context_t *parent_layer_ctx);
+/**
+ * \brief Derives sealing CDI for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t derive_sealing_cdi(struct layer_context_t *layer_ctx);
+
+/**
+ * \brief Derives wrapping key pair for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t derive_wrapping_key(struct layer_context_t *layer_ctx);
+
+/**
+ * \brief Create and sign the certificate for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t create_layer_certificate(struct layer_context_t *layer_ctx);
+
+/**
+ * \brief Stores signed certificate for a layer
+ *
+ * \param[in] layer_ctx  Pointer to current layer context.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t store_layer_certificate(struct layer_context_t *layer_ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DPE_CRYPTO_INTERFACE_H__ */