feat(dice): add DPE driver to measured boot
Implement a DPE specific backend within the
generic measured boot framework.
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
Change-Id: Ia3a0eac0ee6f7b4b337a93d08286613e7c8186b4
diff --git a/drivers/measured_boot/rss/dice_prot_env.c b/drivers/measured_boot/rss/dice_prot_env.c
new file mode 100644
index 0000000..6417cdc
--- /dev/null
+++ b/drivers/measured_boot/rss/dice_prot_env.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <psa/crypto_types.h>
+#include <psa/crypto_values.h>
+
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+#include <drivers/measured_boot/rss/dice_prot_env.h>
+#include <lib/cassert.h>
+#include <lib/psa/dice_protection_environment.h>
+
+#include <platform_def.h>
+
+#define DPE_ALG_SHA512 0
+#define DPE_ALG_SHA384 1
+#define DPE_ALG_SHA256 2
+
+#if DPE_ALG_ID == DPE_ALG_SHA512
+#define CRYPTO_MD_ID CRYPTO_MD_SHA512
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_512
+#elif DPE_ALG_ID == DPE_ALG_SHA384
+#define CRYPTO_MD_ID CRYPTO_MD_SHA384
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_384
+#elif DPE_ALG_ID == DPE_ALG_SHA256
+#define CRYPTO_MD_ID CRYPTO_MD_SHA256
+#define PSA_CRYPTO_MD_ID PSA_ALG_SHA_256
+#else
+# error Invalid DPE hash algorithm.
+#endif /* DPE_ALG_ID */
+
+/* Ensure that computed hash values fits into the DiceInputValues structure */
+CASSERT(DICE_HASH_SIZE >= DPE_DIGEST_SIZE,
+ assert_digest_size_bigger_than_allocated_buffer);
+
+static int initial_context_handle;
+
+static void map_metadata_to_dice_inputs(struct dpe_metadata *metadata,
+ DiceInputValues *dice_inputs)
+{
+ /* Hash of the content certificate signing key (public part) */
+ memcpy(dice_inputs->authority_hash, metadata->signer_id,
+ DPE_DIGEST_SIZE);
+
+ /* SW type string identifier */
+ assert(metadata->sw_type_size < DICE_CODE_DESCRIPTOR_MAX_SIZE);
+ dice_inputs->code_descriptor = metadata->sw_type;
+ dice_inputs->code_descriptor_size = metadata->sw_type_size;
+}
+
+void dpe_init(struct dpe_metadata *metadata)
+{
+ assert(metadata != NULL);
+
+ /* Init the non-const members of the metadata structure */
+ while (metadata->id != DPE_INVALID_ID) {
+ /* Terminating 0 character is not needed due to CBOR encoding */
+ metadata->sw_type_size =
+ strlen((const char *)&metadata->sw_type);
+ metadata++;
+ }
+
+ /* TODO: Obtain ctx handle and assign it to initial_context_handle */
+}
+
+int dpe_measure_and_record(struct dpe_metadata *metadata,
+ uintptr_t data_base, uint32_t data_size,
+ uint32_t data_id)
+{
+ static int current_context_handle;
+ DiceInputValues dice_inputs = { 0 };
+ int new_parent_context_handle;
+ int new_context_handle;
+ dpe_error_t ret;
+ int rc;
+
+ assert(metadata != NULL);
+
+ /* Get the metadata associated with this image. */
+ while ((metadata->id != DPE_INVALID_ID) && (metadata->id != data_id)) {
+ metadata++;
+ }
+
+ /* If image is not present in metadata array then skip */
+ if (metadata->id == DPE_INVALID_ID) {
+ return 0;
+ }
+
+ /* Calculate hash */
+ rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
+ (void *)data_base, data_size,
+ dice_inputs.code_hash);
+ if (rc != 0) {
+ return rc;
+ }
+
+ map_metadata_to_dice_inputs(metadata, &dice_inputs);
+
+ /* Only at the first call */
+ if (current_context_handle == 0) {
+ current_context_handle = initial_context_handle;
+ }
+
+ VERBOSE("Calling dpe_derive_context, image_id: %d\n", metadata->id);
+ ret = dpe_derive_context(current_context_handle,
+ metadata->retain_parent_context,
+ metadata->allow_new_context_to_derive,
+ metadata->create_certificate,
+ &dice_inputs,
+ 0, /* target_locality */
+ false, /* return_certificate */
+ true, /* allow_new_context_to_export */
+ false, /* export_cdi */
+ &new_context_handle,
+ &new_parent_context_handle,
+ NULL, 0, NULL, /* new_certificate_* */
+ NULL, 0, NULL); /* exported_cdi_* */
+ if (ret == DPE_NO_ERROR) {
+ current_context_handle = new_parent_context_handle;
+ if (metadata->allow_new_context_to_derive == true) {
+ /* Share new_context_handle with child component:
+ * e.g: BL2, BL33.
+ */
+ VERBOSE("Share new_context_handle with child: 0x%x\n",
+ new_context_handle);
+ /* TODO: share context handle */
+ }
+ } else {
+ ERROR("dpe_derive_context failed: %d\n", ret);
+ }
+
+ return (ret == DPE_NO_ERROR) ? 0 : -1;
+}
+
+int dpe_set_signer_id(struct dpe_metadata *metadata,
+ const void *pk_oid,
+ const void *pk_ptr,
+ size_t pk_len)
+{
+ unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
+ int rc;
+ bool hash_calc_done = false;
+
+ assert(metadata != NULL);
+
+ /*
+ * Do an exhaustive search over the platform metadata to find
+ * all images whose key OID matches the one passed in argument.
+ *
+ * Note that it is not an error if do not get any matches.
+ * The platform may decide not to measure all of the images
+ * in the system.
+ */
+ while (metadata->id != DPE_INVALID_ID) {
+ /* Get the metadata associated with this key-oid */
+ if (metadata->pk_oid == pk_oid) {
+ if (hash_calc_done == false) {
+ /* Calculate public key hash */
+ rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
+ (void *)pk_ptr,
+ pk_len, hash_data);
+ if (rc != 0) {
+ return rc;
+ }
+
+ hash_calc_done = true;
+ }
+
+ /*
+ * Fill the signer-ID field with the newly/already
+ * computed hash of the public key and update its
+ * signer ID size field with compile-time decided
+ * digest size.
+ */
+ (void)memcpy(metadata->signer_id,
+ hash_data,
+ DPE_DIGEST_SIZE);
+ metadata->signer_id_size = DPE_DIGEST_SIZE;
+ }
+
+ metadata++;
+ }
+
+ return 0;
+}