Crypto: Add support for persistent keys
Adds support for the PSA Crypto persistent key APIs to the crypto
service by enabling and calling the Mbed Crypto implementations. Mbed
Crypto in turn calls ITS for persistent storage.
Change-Id: I0db6b1ced6030cae41322ae06214114cc9c84cb4
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/secure_fw/services/crypto/crypto_key.c b/secure_fw/services/crypto/crypto_key.c
index c7405ca..e88040d 100644
--- a/secure_fw/services/crypto/crypto_key.c
+++ b/secure_fw/services/crypto/crypto_key.c
@@ -39,6 +39,58 @@
*/
/*!@{*/
+psa_status_t tfm_crypto_key_attributes_from_client(
+ const psa_client_key_attributes_t *client_key_attr,
+ int32_t client_id,
+ psa_key_attributes_t *key_attributes)
+{
+ if (client_key_attr == NULL || key_attributes == NULL) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
+
+ /* Domain parameters are not supported, ignore any passed by the client */
+ key_attributes->domain_parameters = NULL;
+ key_attributes->domain_parameters_size = 0;
+
+ /* Copy core key attributes from the client core key attributes */
+ key_attributes->core.type = client_key_attr->core.type;
+ key_attributes->core.lifetime = client_key_attr->core.lifetime;
+ key_attributes->core.policy = client_key_attr->core.policy;
+ key_attributes->core.bits = client_key_attr->core.bits;
+ key_attributes->core.flags = client_key_attr->core.flags;
+
+ /* Use the client key id as the key_id and its partition id as the owner */
+ key_attributes->core.id.key_id = client_key_attr->core.id;
+ key_attributes->core.id.owner = client_id;
+
+ return PSA_SUCCESS;
+}
+
+psa_status_t tfm_crypto_key_attributes_to_client(
+ const psa_key_attributes_t *key_attributes,
+ psa_client_key_attributes_t *client_key_attr)
+{
+ if (client_key_attr == NULL || key_attributes == NULL) {
+ return PSA_ERROR_PROGRAMMER_ERROR;
+ }
+
+ /* Domain parameters are not supported, avoid passing any to the client */
+ client_key_attr->domain_parameters = NULL;
+ client_key_attr->domain_parameters_size = 0;
+
+ /* Copy core key attributes to the client core key attributes */
+ client_key_attr->core.type = key_attributes->core.type;
+ client_key_attr->core.lifetime = key_attributes->core.lifetime;
+ client_key_attr->core.policy = key_attributes->core.policy;
+ client_key_attr->core.bits = key_attributes->core.bits;
+ client_key_attr->core.flags = key_attributes->core.flags;
+
+ /* Return the key_id as the client key id, do not return the owner */
+ client_key_attr->core.id = key_attributes->core.id.key_id;
+
+ return PSA_SUCCESS;
+}
+
psa_status_t tfm_crypto_check_handle_owner(psa_key_handle_t handle,
uint32_t *index)
{
@@ -151,15 +203,16 @@
}
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (in_vec[1].len != sizeof(psa_key_attributes_t)) ||
+ (in_vec[1].len != sizeof(psa_client_key_attributes_t)) ||
(out_vec[0].len != sizeof(psa_key_handle_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
- const psa_key_attributes_t *key_attributes = in_vec[1].base;
+ const psa_client_key_attributes_t *client_key_attr = in_vec[1].base;
const uint8_t *data = in_vec[2].base;
size_t data_length = in_vec[2].len;
psa_key_handle_t *key_handle = out_vec[0].base;
psa_status_t status;
+ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
uint32_t i = 0;
int32_t partition_id = 0;
bool empty_found = false;
@@ -180,7 +233,14 @@
return status;
}
- status = psa_import_key(key_attributes, data, data_length, key_handle);
+ status = tfm_crypto_key_attributes_from_client(client_key_attr,
+ partition_id,
+ &key_attributes);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ status = psa_import_key(&key_attributes, data, data_length, key_handle);
if (status == PSA_SUCCESS) {
handle_owner[i].owner = partition_id;
@@ -205,12 +265,45 @@
}
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (in_vec[1].len != sizeof(psa_key_id_t)) ||
+ (in_vec[1].len != sizeof(psa_app_key_id_t)) ||
(out_vec[0].len != sizeof(psa_key_handle_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
- return PSA_ERROR_NOT_SUPPORTED;
+ psa_app_key_id_t client_key_id = *((psa_app_key_id_t *)in_vec[1].base);
+ psa_key_handle_t *key_handle = out_vec[0].base;
+ psa_status_t status;
+ psa_key_id_t id;
+ int32_t partition_id;
+ uint32_t i;
+
+ for (i = 0; i < TFM_CRYPTO_MAX_KEY_HANDLES; i++) {
+ if (handle_owner[i].in_use == TFM_CRYPTO_NOT_IN_USE) {
+ break;
+ }
+ }
+
+ if (i == TFM_CRYPTO_MAX_KEY_HANDLES) {
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+
+ status = tfm_crypto_get_caller_id(&partition_id);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ /* Use the client key id as the key_id and its partition id as the owner */
+ id = (psa_key_id_t){ .key_id = client_key_id, .owner = partition_id };
+
+ status = psa_open_key(id, key_handle);
+
+ if (status == PSA_SUCCESS) {
+ handle_owner[i].owner = partition_id;
+ handle_owner[i].handle = *key_handle;
+ handle_owner[i].in_use = TFM_CRYPTO_IN_USE;
+ }
+
+ return status;
#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */
}
@@ -305,15 +398,29 @@
}
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(psa_key_attributes_t))) {
+ (out_vec[0].len != sizeof(psa_client_key_attributes_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_key_handle_t key = iov->key_handle;
- psa_key_attributes_t *key_attributes = out_vec[0].base;
+ psa_client_key_attributes_t *client_key_attr = out_vec[0].base;
+ psa_status_t status;
+ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
- return psa_get_key_attributes(key, key_attributes);
+ status = tfm_crypto_check_handle_owner(key, NULL);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ status = psa_get_key_attributes(key, &key_attributes);
+
+ if (status == PSA_SUCCESS) {
+ status = tfm_crypto_key_attributes_to_client(&key_attributes,
+ client_key_attr);
+ }
+
+ return status;
#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */
}
@@ -330,16 +437,31 @@
}
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (out_vec[0].len != sizeof(psa_key_attributes_t))) {
+ (out_vec[0].len != sizeof(psa_client_key_attributes_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
- psa_key_attributes_t *key_attributes = out_vec[0].base;
+ psa_client_key_attributes_t *client_key_attr = out_vec[0].base;
+ psa_status_t status;
+ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ int32_t partition_id;
- psa_reset_key_attributes(key_attributes);
+ status = tfm_crypto_get_caller_id(&partition_id);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
- /* psa_reset_key_attributes() doesn't report any error */
- return PSA_SUCCESS;
+ status = tfm_crypto_key_attributes_from_client(client_key_attr,
+ partition_id,
+ &key_attributes);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ psa_reset_key_attributes(&key_attributes);
+
+ return tfm_crypto_key_attributes_to_client(&key_attributes,
+ client_key_attr);
#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */
}
@@ -408,15 +530,16 @@
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
(out_vec[0].len != sizeof(psa_key_handle_t)) ||
- (in_vec[1].len != sizeof(psa_key_attributes_t))) {
+ (in_vec[1].len != sizeof(psa_client_key_attributes_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
const struct tfm_crypto_pack_iovec *iov = in_vec[0].base;
psa_key_handle_t source_handle = iov->key_handle;
psa_key_handle_t *target_handle = out_vec[0].base;
- const psa_key_attributes_t *key_attributes = in_vec[1].base;
+ const psa_client_key_attributes_t *client_key_attr = in_vec[1].base;
psa_status_t status;
+ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
uint32_t i = 0;
int32_t partition_id = 0;
bool empty_found = false;
@@ -437,7 +560,14 @@
return status;
}
- status = psa_copy_key(source_handle, key_attributes, target_handle);
+ status = tfm_crypto_key_attributes_from_client(client_key_attr,
+ partition_id,
+ &key_attributes);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ status = psa_copy_key(source_handle, &key_attributes, target_handle);
if (status == PSA_SUCCESS) {
handle_owner[i].owner = partition_id;
@@ -463,13 +593,14 @@
}
if ((in_vec[0].len != sizeof(struct tfm_crypto_pack_iovec)) ||
- (in_vec[1].len != sizeof(psa_key_attributes_t)) ||
+ (in_vec[1].len != sizeof(psa_client_key_attributes_t)) ||
(out_vec[0].len != sizeof(psa_key_handle_t))) {
return PSA_ERROR_CONNECTION_REFUSED;
}
psa_key_handle_t *key_handle = out_vec[0].base;
- const psa_key_attributes_t *key_attributes = in_vec[1].base;
+ const psa_client_key_attributes_t *client_key_attr = in_vec[1].base;
psa_status_t status;
+ psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
uint32_t i = 0;
int32_t partition_id = 0;
bool empty_found = false;
@@ -490,7 +621,14 @@
return status;
}
- status = psa_generate_key(key_attributes, key_handle);
+ status = tfm_crypto_key_attributes_from_client(client_key_attr,
+ partition_id,
+ &key_attributes);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+ status = psa_generate_key(&key_attributes, key_handle);
if (status == PSA_SUCCESS) {
handle_owner[i].owner = partition_id;