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__ */