DPE: Add Certify Key command
Create a leaf certificate and return the certificate chain.
Signed-off-by: Maulik Patel <maulik.patel@arm.com>
Change-Id: Ib82312af7b653df5c46bc5c11e93d7ff53ad1894
diff --git a/partitions/dice_protection_environment/dpe_context_mngr.c b/partitions/dice_protection_environment/dpe_context_mngr.c
index 1698c65..2cd040a 100644
--- a/partitions/dice_protection_environment/dpe_context_mngr.c
+++ b/partitions/dice_protection_environment/dpe_context_mngr.c
@@ -101,6 +101,8 @@
{
layer_ctx_array[i].state = LAYER_STATE_CLOSED;
layer_ctx_array[i].parent_layer_idx = INVALID_LAYER_IDX;
+ (void)memset(&layer_ctx_array[i].attest_cdi_hash_input, 0,
+ sizeof(layer_ctx_array[i].attest_cdi_hash_input));
(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));
@@ -275,6 +277,16 @@
}
}
+ if (layer_ctx_array[curr_layer_idx].data.attest_key_label_len != 0) {
+
+ status = psa_hash_update(&hash_op,
+ &layer_ctx_array[curr_layer_idx].data.attest_key_label[0],
+ layer_ctx_array[curr_layer_idx].data.attest_key_label_len);
+ 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),
@@ -285,70 +297,72 @@
return status;
}
-
-static dpe_error_t derive_child_create_certificate(uint16_t layer_idx)
+static dpe_error_t create_layer_certificate(uint16_t layer_idx)
{
uint16_t parent_layer_idx;
psa_status_t status;
dpe_error_t err;
+ struct layer_context_t *layer_ctx, *parent_layer_ctx;
assert(layer_idx < MAX_NUM_OF_LAYERS);
- /* Finalise the layer */
- layer_ctx_array[layer_idx].state = LAYER_STATE_FINALISED;
+ layer_ctx = &layer_ctx_array[layer_idx];
+ /* Finalise the layer */
+ layer_ctx->state = LAYER_STATE_FINALISED;
+ parent_layer_idx = layer_ctx->parent_layer_idx;
+ assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
+ parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
/* For RoT Layer, CDI and issuer seed values are calculated by BL1_1 */
- if (layer_idx != DPE_ROT_LAYER_IDX) {
+ if ((layer_idx != DPE_ROT_LAYER_IDX) &&
+ (!layer_ctx->is_external_pub_key_provided)) {
- parent_layer_idx = layer_ctx_array[layer_idx].parent_layer_idx;
- assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
+ /* Except for RoT Layer with no external public key supplied */
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_layer_idx]);
+ status = derive_attestation_cdi(layer_ctx, parent_layer_ctx);
if (status != PSA_SUCCESS) {
return DPE_INTERNAL_ERROR;
}
- status = derive_sealing_cdi(&layer_ctx_array[layer_idx]);
+ status = derive_sealing_cdi(layer_ctx);
if (status != PSA_SUCCESS) {
return DPE_INTERNAL_ERROR;
}
- } else {
- /* There is no parent for RoT layer */
- parent_layer_idx = 0;
}
- status = derive_wrapping_key(&layer_ctx_array[layer_idx]);
+ status = derive_wrapping_key(layer_ctx);
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;
+ if (!layer_ctx->is_external_pub_key_provided) {
+ status = derive_attestation_key(layer_ctx);
+ if (status != PSA_SUCCESS) {
+ return DPE_INTERNAL_ERROR;
+ }
}
- status = derive_id_from_public_key(&layer_ctx_array[layer_idx]);
+ status = derive_id_from_public_key(layer_ctx);
if (status != PSA_SUCCESS) {
return DPE_INTERNAL_ERROR;
}
err = encode_layer_certificate(layer_idx,
- &layer_ctx_array[layer_idx],
- &layer_ctx_array[parent_layer_idx]);
+ layer_ctx,
+ parent_layer_ctx);
if (err != DPE_NO_ERROR) {
return err;
}
log_intermediate_certificate(layer_idx,
- &layer_ctx_array[layer_idx].data.cert_buf[0],
- layer_ctx_array[layer_idx].data.cert_buf_len);
+ &layer_ctx->data.cert_buf[0],
+ layer_ctx->data.cert_buf_len);
- return store_layer_certificate(&layer_ctx_array[layer_idx]);
+ return store_layer_certificate(layer_ctx);
}
static uint16_t open_new_layer(void)
@@ -405,6 +419,9 @@
child_comp_ctx->in_use = true;
/* Link context to RoT Layer */
child_comp_ctx->linked_layer_idx = DPE_ROT_LAYER_IDX;
+ /* There is no parent for RoT layer */
+ layer_ctx_array[DPE_ROT_LAYER_IDX].parent_layer_idx = 0;
+
/* Parent is same as child for RoT context */
child_comp_ctx->parent_idx = 0;
/* Parent not deriving any more children */
@@ -412,7 +429,7 @@
//TODO: Update expected_mhu_id of derived child
/* Create certificate for RoT layer */
- status = derive_child_create_certificate(DPE_ROT_LAYER_IDX);
+ status = create_layer_certificate(DPE_ROT_LAYER_IDX);
if (status != DPE_NO_ERROR) {
return status;
}
@@ -548,7 +565,7 @@
}
if (create_certificate) {
- err = derive_child_create_certificate(child_ctx->linked_layer_idx);
+ err = create_layer_certificate(child_ctx->linked_layer_idx);
if (err != DPE_NO_ERROR) {
return err;
}
@@ -683,3 +700,130 @@
}
}
+struct layer_context_t* get_layer_ctx_ptr(uint16_t layer_idx)
+{
+ /* Safety case */
+ if (layer_idx >= MAX_NUM_OF_LAYERS) {
+ return NULL;
+ }
+
+ return &layer_ctx_array[layer_idx];
+}
+
+dpe_error_t certify_key_request(int input_ctx_handle,
+ bool retain_context,
+ const uint8_t *public_key,
+ size_t public_key_size,
+ const uint8_t *label,
+ size_t label_size,
+ uint8_t *certificate_chain_buf,
+ size_t certificate_chain_buf_size,
+ size_t *certificate_chain_actual_size,
+ uint8_t *derived_public_key_buf,
+ size_t derived_public_key_buf_size,
+ size_t *derived_public_key_actual_size,
+ int *new_context_handle)
+{
+ uint16_t input_ctx_idx, input_layer_idx, parent_layer_idx;
+ dpe_error_t err;
+ psa_status_t status;
+ struct layer_context_t *parent_layer_ctx, *layer_ctx;
+
+ log_certify_key(input_ctx_handle, retain_context, public_key, public_key_size,
+ label, label_size);
+
+ /* Validate input handle */
+ if (!is_input_handle_valid(input_ctx_handle)) {
+ return DPE_INVALID_ARGUMENT;
+ }
+
+ if (label_size > DPE_EXTERNAL_LABEL_MAX_SIZE) {
+ return DPE_INVALID_ARGUMENT;
+ }
+
+ /* Get component index from the input handle */
+ input_ctx_idx = GET_IDX(input_ctx_handle);
+ /* Get current linked layer idx */
+ input_layer_idx = component_ctx_array[input_ctx_idx].linked_layer_idx;
+ assert(input_layer_idx < MAX_NUM_OF_LAYERS);
+
+ layer_ctx = &layer_ctx_array[input_layer_idx];
+ if (public_key_size > sizeof(layer_ctx->data.attest_pub_key)) {
+ return DPE_INVALID_ARGUMENT;
+ }
+
+ if ((public_key_size > 0) && (public_key != NULL)) {
+ layer_ctx->is_external_pub_key_provided = true;
+ /* Copy the public key provided */
+ memcpy(&layer_ctx->data.attest_pub_key[0],
+ public_key,
+ public_key_size);
+ layer_ctx->data.attest_pub_key_len = public_key_size;
+
+ /* If public key is provided, then provided label (if any) is ignored */
+ layer_ctx->data.attest_key_label_len = 0;
+
+ } else {
+ /* No external public key is provided */
+ layer_ctx->is_external_pub_key_provided = false;
+
+ if ((label_size > 0) && (label != NULL)) {
+ /* Copy the label provided */
+ memcpy(&layer_ctx->data.attest_key_label[0],
+ label,
+ label_size);
+ layer_ctx->data.attest_key_label_len = label_size;
+
+ } else {
+ layer_ctx->data.attest_key_label_len = 0;
+ }
+ }
+
+ /* Correct layer should already be assigned in last call of
+ * derive child command
+ */
+ /* Finalise the current layer & create leaf certificate */
+ err = create_layer_certificate(input_layer_idx);
+ if (err != DPE_NO_ERROR) {
+ return err;
+ }
+
+ /* Get parent layer derived public key to verify the certificate signature */
+ parent_layer_idx = layer_ctx_array[input_layer_idx].parent_layer_idx;
+ assert(parent_layer_idx < MAX_NUM_OF_LAYERS);
+ parent_layer_ctx = &layer_ctx_array[parent_layer_idx];
+
+ if (derived_public_key_buf_size < sizeof(parent_layer_ctx->data.attest_pub_key)) {
+ return DPE_INVALID_ARGUMENT;
+ }
+
+ memcpy(derived_public_key_buf,
+ &parent_layer_ctx->data.attest_pub_key[0],
+ parent_layer_ctx->data.attest_pub_key_len);
+ *derived_public_key_actual_size = parent_layer_ctx->data.attest_pub_key_len;
+
+ /* Get certificate chain */
+ err = get_certificate_chain(input_layer_idx,
+ certificate_chain_buf,
+ certificate_chain_buf_size,
+ certificate_chain_actual_size);
+ if (err != DPE_NO_ERROR) {
+ return err;
+ }
+
+ log_certificate_chain(certificate_chain_buf, *certificate_chain_actual_size);
+
+ /* Renew handle for the same context */
+ *new_context_handle = input_ctx_handle;
+ status = renew_nonce(new_context_handle);
+ if (status != PSA_SUCCESS) {
+ return DPE_INTERNAL_ERROR;
+ }
+ component_ctx_array[input_ctx_idx].nonce = GET_NONCE(*new_context_handle);
+
+ /* Clear the context label and key contents */
+ memset(&layer_ctx->data.attest_key_label[0], 0u, layer_ctx->data.attest_key_label_len);
+ memset(&layer_ctx->data.attest_pub_key[0], 0u, layer_ctx->data.attest_pub_key_len);
+
+ return DPE_NO_ERROR;
+}