blob: 9a18d91f1da7712f026ca91ef900c6850fc87ddb [file] [log] [blame]
/*
* Copyright (c) 2023, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "dpe_crypto_interface.h"
#include <assert.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 exported_attest_cdi_label[] = DPE_ATTEST_EXPORTED_CDI_LABEL;
static const char attest_key_pair_label[] = DPE_ATTEST_KEY_PAIR_LABEL;
static const char id_label[] = DPE_ID_LABEL;
static const uint8_t attest_key_salt[] = DPE_ATTEST_KEY_SALT;
static const uint8_t id_salt[] = DPE_ID_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) */
if (layer_ctx->is_cdi_to_be_exported) {
return perform_derivation(parent_layer_ctx->data.cdi_key_id,
&derive_key_attr,
(uint8_t *) &exported_attest_cdi_label[0],
sizeof(exported_attest_cdi_label),
layer_ctx->attest_cdi_hash_input,
sizeof(layer_ctx->attest_cdi_hash_input),
&layer_ctx->data.cdi_key_id);
} else {
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_status_t status;
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 */
status = 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);
if (status != PSA_SUCCESS) {
return status;
}
return psa_export_public_key(layer_ctx->data.attest_key_id,
&layer_ctx->data.attest_pub_key[0],
sizeof(layer_ctx->data.attest_pub_key),
&layer_ctx->data.attest_pub_key_len);
}
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 derive_id_from_public_key(struct layer_context_t *layer_ctx)
{
psa_status_t status;
psa_key_attributes_t derive_key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t base_attr = PSA_KEY_ATTRIBUTES_INIT;
size_t output_id_len;
psa_key_id_t base_key = PSA_KEY_ID_NULL;
psa_key_id_t derived_key_id = PSA_KEY_ID_NULL;
psa_set_key_type(&base_attr, PSA_KEY_TYPE_DERIVE);
psa_set_key_algorithm(&base_attr, PSA_ALG_HKDF(PSA_ALG_SHA_256));
psa_set_key_bits(&base_attr, PSA_BYTES_TO_BITS(layer_ctx->data.attest_pub_key_len));
psa_set_key_usage_flags(&base_attr, PSA_KEY_USAGE_DERIVE);
status = psa_import_key(&base_attr,
&layer_ctx->data.attest_pub_key[0],
layer_ctx->data.attest_pub_key_len,
&base_key);
if (status != PSA_SUCCESS) {
return status;
}
/* Derive Key attributes same as CDI attributes except the label */
psa_set_key_type(&derive_key_attr, PSA_KEY_TYPE_RAW_DATA);
psa_set_key_algorithm(&derive_key_attr, PSA_ALG_HKDF(PSA_ALG_SHA_256));
psa_set_key_bits(&derive_key_attr, PSA_BYTES_TO_BITS(DICE_ID_SIZE));
psa_set_key_usage_flags(&derive_key_attr, PSA_KEY_USAGE_EXPORT);
/* Perform ID derivation */
/* Supply the ID label as an input to the key derivation */
status = perform_derivation(base_key,
&derive_key_attr,
(uint8_t *) &id_label[0],
sizeof(id_label),
id_salt,
sizeof(id_salt),
&derived_key_id);
if (status != PSA_SUCCESS) {
goto err_destroy_base_key;
}
status = psa_export_key(derived_key_id,
&layer_ctx->data.cdi_id[0],
sizeof(layer_ctx->data.cdi_id),
&output_id_len);
(void)psa_destroy_key(derived_key_id);
err_destroy_base_key:
(void)psa_destroy_key(base_key);
return status;
}
psa_status_t derive_cdi_id(psa_key_id_t attest_key_id, uint8_t *cdi_id,
size_t cdi_id_size)
{
psa_status_t status;
psa_key_derivation_operation_t op = PSA_KEY_DERIVATION_OPERATION_INIT;
uint8_t attest_pub_key[DPE_ATTEST_PUB_KEY_SIZE];
size_t attest_pub_key_len;
status = psa_export_public_key(attest_key_id, attest_pub_key,
sizeof(attest_pub_key), &attest_pub_key_len);
if (status != PSA_SUCCESS) {
return status;
}
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,
id_salt, sizeof(id_salt));
if (status != PSA_SUCCESS) {
goto err_abort;
}
status = psa_key_derivation_input_bytes(&op,
PSA_KEY_DERIVATION_INPUT_SECRET,
attest_pub_key, attest_pub_key_len);
if (status != PSA_SUCCESS) {
goto err_abort;
}
status = psa_key_derivation_input_bytes(&op, PSA_KEY_DERIVATION_INPUT_INFO,
(const uint8_t *)id_label,
sizeof(id_label));
if (status != PSA_SUCCESS) {
goto err_abort;
}
status = psa_key_derivation_output_bytes(&op, cdi_id, cdi_id_size);
if (status != PSA_SUCCESS) {
goto err_abort;
}
return psa_key_derivation_abort(&op);
err_abort:
(void)psa_key_derivation_abort(&op);
return status;
}
psa_status_t get_layer_cdi_value(const struct layer_context_t *layer_ctx,
uint8_t *cdi_buf,
size_t cdi_buf_size,
size_t *cdi_actual_size)
{
psa_status_t status;
//TODO: Sealing CDI to be added later
status = psa_export_key(layer_ctx->data.cdi_key_id,
cdi_buf,
sizeof(cdi_buf),
&cdi_actual_size);
if (status != PSA_SUCCESS) {
*cdi_actual_size = 0;
}
return status;
}