From 0ecd2c5da1aa9bd469cf9c302c3bf7fcc9fca695 Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Mon, 4 Feb 2019 15:50:24 +0200 Subject: [PATCH 1/5] crypto service: Crypto access control Implement crypto keys access control in crypto service: - Only the key owner (the partition which created the key) is allowed to manage (import/export/open/close/destroy/etc.) the key. - Only the key owner (the partition which created the key) is allowed to use the key handle for crypto operations which require a key handle. --- .../COMPONENT_SPE/psa_crypto_access_control.c | 80 +++++++++ .../COMPONENT_SPE/psa_crypto_access_control.h | 36 +++++ .../COMPONENT_SPE/psa_crypto_partition.c | 153 +++++++++++++++++- 3 files changed, 263 insertions(+), 6 deletions(-) create mode 100644 components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c create mode 100644 components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c new file mode 100644 index 0000000000..3ebe5eb5b6 --- /dev/null +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "psa_crypto_access_control.h" +#include "psa_crypto_slot_management.h" +#include "spm_panic.h" + +typedef struct psa_crypto_access_control_s { + psa_key_handle_t key_handle; + int32_t partition_id; +} psa_crypto_access_control_t; + +static psa_crypto_access_control_t crypto_access_control_arr[PSA_KEY_SLOT_COUNT]; + +#define PSA_CRYPTO_ACCESS_CONTROL_RESET() (memset(crypto_access_control_arr, 0, sizeof(crypto_access_control_arr))) + +void psa_crypto_access_control_init(void) +{ + PSA_CRYPTO_ACCESS_CONTROL_RESET(); +} + +void psa_crypto_access_control_destroy(void) +{ + PSA_CRYPTO_ACCESS_CONTROL_RESET(); +} + +void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id) +{ + for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) { + if (crypto_access_control_arr[i].key_handle == 0 && + crypto_access_control_arr[i].partition_id == 0) { + crypto_access_control_arr[i].key_handle = key_handle; + crypto_access_control_arr[i].partition_id = partition_id; + return; + } + } + + SPM_PANIC("psa_crypto_access_control_register_handle failed"); +} + +void psa_crypto_access_control_unregister_handle(psa_key_handle_t key_handle) +{ + for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) { + if (crypto_access_control_arr[i].key_handle == key_handle) { + crypto_access_control_arr[i].key_handle = 0; + crypto_access_control_arr[i].partition_id = 0; + return; + } + } + + SPM_PANIC("psa_crypto_access_control_unregister_handle failed"); +} + +uint8_t psa_crypto_access_control_is_handle_permitted(psa_key_handle_t key_handle, int32_t partition_id) +{ + for (size_t i = 0; i < PSA_KEY_SLOT_COUNT; i++) { + if (crypto_access_control_arr[i].key_handle == key_handle && + crypto_access_control_arr[i].partition_id == partition_id) { + return 1; + } + } + + return 0; +} diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h new file mode 100644 index 0000000000..4e654124c9 --- /dev/null +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, Arm Limited and affiliates + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PSA_CRYPTO_ACCESS_CONTROL_H +#define PSA_CRYPTO_ACCESS_CONTROL_H + +#include + +#include "psa_crypto_core.h" +#include "crypto_platform.h" + +void psa_crypto_access_control_init(void); + +void psa_crypto_access_control_destroy(void); + +void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id); + +void psa_crypto_access_control_unregister_handle(psa_key_handle_t key_handle); + +uint8_t psa_crypto_access_control_is_handle_permitted(psa_key_handle_t key_handle, int32_t partition_id); + +#endif /* PSA_CRYPTO_ACCESS_CONTROL_H */ diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c index 8b6dd75b03..2cb1ef0709 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c @@ -15,6 +15,7 @@ #include "crypto_platform_spe.h" #include "psa_crypto_srv_partition.h" #include "mbedtls/entropy.h" +#include "psa_crypto_access_control.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" @@ -121,6 +122,7 @@ static void psa_crypto_init_operation(void) ++psa_spm_init_refence_counter; if (psa_spm_init_refence_counter == 1) { memset(psa_spm_hash_clones, 0, sizeof(psa_spm_hash_clones)); + psa_crypto_access_control_init(); } } @@ -158,6 +160,7 @@ static void psa_crypto_free_operation(void) if (psa_spm_init_refence_counter == 0) { memset(psa_spm_hash_clones, 0, sizeof(psa_spm_hash_clones)); + psa_crypto_access_control_destroy(); mbedtls_psa_crypto_free(); } @@ -207,6 +210,12 @@ static void psa_mac_operation(void) switch (psa_crypto.func) { case PSA_MAC_SIGN_SETUP: { + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_mac_sign_setup(msg.rhandle, psa_crypto.handle, psa_crypto.alg); @@ -214,6 +223,12 @@ static void psa_mac_operation(void) } case PSA_MAC_VERIFY_SETUP: { + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_mac_verify_setup(msg.rhandle, psa_crypto.handle, psa_crypto.alg); @@ -537,6 +552,12 @@ static void psa_asymmetric_operation(void) SPM_PANIC("SPM read length mismatch"); } + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + switch (psa_crypto.func) { case PSA_ASYMMETRIC_SIGN: { uint8_t *signature; @@ -723,6 +744,12 @@ static void psa_aead_operation() SPM_PANIC("SPM read length mismatch"); } + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + switch (psa_crypto.func) { case PSA_AEAD_ENCRYPT: case PSA_AEAD_DECRYPT: { @@ -842,6 +869,12 @@ static void psa_symmetric_operation(void) switch (psa_crypto_ipc.func) { case PSA_CIPHER_ENCRYPT_SETUP: { + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto_ipc.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_cipher_encrypt_setup(msg.rhandle, psa_crypto_ipc.handle, psa_crypto_ipc.alg); @@ -849,6 +882,12 @@ static void psa_symmetric_operation(void) } case PSA_CIPHER_DECRYPT_SETUP: { + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto_ipc.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_cipher_decrypt_setup(msg.rhandle, psa_crypto_ipc.handle, psa_crypto_ipc.alg); @@ -981,6 +1020,7 @@ static void psa_key_management_operation(void) { psa_msg_t msg = { 0 }; psa_status_t status = PSA_SUCCESS; + int32_t partition_id = 0; psa_get(PSA_KEY_MNG, &msg); switch (msg.type) { @@ -1005,11 +1045,19 @@ static void psa_key_management_operation(void) SPM_PANIC("SPM read length mismatch"); } + partition_id = psa_identity(msg.handle); + switch (psa_key_mng.func) { case PSA_GET_KEY_LIFETIME: { size_t lifetime_length = msg.out_size[0]; psa_key_lifetime_t lifetime; + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_get_key_lifetime(psa_key_mng.handle, &lifetime); if (status == PSA_SUCCESS) { @@ -1024,6 +1072,12 @@ static void psa_key_management_operation(void) size_t policy_length = msg.in_size[1]; psa_key_policy_t policy; + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + bytes_read = psa_read(msg.handle, 1, &policy, policy_length); if (bytes_read != policy_length) { @@ -1038,6 +1092,12 @@ static void psa_key_management_operation(void) size_t policy_size = msg.out_size[0]; psa_key_policy_t policy; + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_get_key_policy(psa_key_mng.handle, &policy); if (status == PSA_SUCCESS) { psa_write(msg.handle, 0, &policy, policy_size); @@ -1048,7 +1108,15 @@ static void psa_key_management_operation(void) case PSA_IMPORT_KEY: { size_t key_length = msg.in_size[1]; - uint8_t *key = mbedtls_calloc(1, key_length); + uint8_t *key = NULL; + + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + key = mbedtls_calloc(1, key_length); if (key == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; break; @@ -1067,13 +1135,30 @@ static void psa_key_management_operation(void) } case PSA_DESTROY_KEY: { - status = psa_destroy_key(psa_key_mng.handle); + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + status = psa_destroy_key(psa_key_mng.handle); + if (status == PSA_SUCCESS) { + psa_crypto_access_control_unregister_handle(psa_key_mng.handle); + } + break; } case PSA_GET_KEY_INFORMATION: { psa_key_type_t type; size_t bits; + + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_get_key_information(psa_key_mng.handle, &type, &bits); if (status == PSA_SUCCESS) { @@ -1091,7 +1176,15 @@ static void psa_key_management_operation(void) case PSA_EXPORT_KEY: { size_t key_length = msg.out_size[0]; size_t data_length; - uint8_t *key = mbedtls_calloc(1, key_length); + uint8_t *key = NULL; + + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + key = mbedtls_calloc(1, key_length); if (key == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; break; @@ -1112,7 +1205,15 @@ static void psa_key_management_operation(void) case PSA_EXPORT_PUBLIC_KEY: { size_t key_length = msg.out_size[0]; size_t data_length; - uint8_t *key = mbedtls_calloc(1, key_length); + uint8_t *key = NULL; + + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + key = mbedtls_calloc(1, key_length); if (key == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; break; @@ -1136,6 +1237,12 @@ static void psa_key_management_operation(void) size_t parameter_size = msg.in_size[2]; uint8_t *parameter = NULL; + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + bytes_read = psa_read(msg.handle, 1, &bits, bits_size); if (bytes_read != bits_size) { SPM_PANIC("SPM read length mismatch"); @@ -1166,6 +1273,7 @@ static void psa_key_management_operation(void) case PSA_ALLOCATE_KEY: { status = psa_allocate_key(&psa_key_mng.handle); if (status == PSA_SUCCESS) { + psa_crypto_access_control_register_handle(psa_key_mng.handle, partition_id); psa_write(msg.handle, 0, &psa_key_mng.handle, sizeof(psa_key_mng.handle)); } break; @@ -1186,6 +1294,7 @@ static void psa_key_management_operation(void) status = psa_create_key(psa_key_mng.lifetime, id, &psa_key_mng.handle); if (status == PSA_SUCCESS) { + psa_crypto_access_control_register_handle(psa_key_mng.handle, partition_id); psa_write(msg.handle, 0, &psa_key_mng.handle, sizeof(psa_key_mng.handle)); } break; @@ -1201,13 +1310,24 @@ static void psa_key_management_operation(void) status = psa_open_key(psa_key_mng.lifetime, id, &psa_key_mng.handle); if (status == PSA_SUCCESS) { + psa_crypto_access_control_register_handle(psa_key_mng.handle, partition_id); psa_write(msg.handle, 0, &psa_key_mng.handle, sizeof(psa_key_mng.handle)); } break; } case PSA_CLOSE_KEY: { + if (!psa_crypto_access_control_is_handle_permitted(psa_key_mng.handle, + partition_id)) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + status = psa_close_key(psa_key_mng.handle); + if (status == PSA_SUCCESS) { + psa_crypto_access_control_unregister_handle(psa_key_mng.handle); + } + break; } @@ -1390,6 +1510,12 @@ void psa_crypto_generator_operations(void) psa_key_type_t type; size_t bits; + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto_ipc.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + bytes_read = psa_read(msg.handle, 1, &type, msg.in_size[1]); if (bytes_read != sizeof(type)) { @@ -1413,7 +1539,15 @@ void psa_crypto_generator_operations(void) } case PSA_KEY_DERIVATION: { - uint8_t *salt = mbedtls_calloc(1, msg.in_size[1]); + uint8_t *salt = NULL; + + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto_ipc.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + salt = mbedtls_calloc(1, msg.in_size[1]); if (salt == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; break; @@ -1450,8 +1584,15 @@ void psa_crypto_generator_operations(void) } case PSA_KEY_AGREEMENT: { + uint8_t *private_key = NULL; - uint8_t *private_key = mbedtls_calloc(1, msg.in_size[1]); + if (!psa_crypto_access_control_is_handle_permitted(psa_crypto_ipc.handle, + psa_identity(msg.handle))) { + status = PSA_ERROR_INVALID_HANDLE; + break; + } + + private_key = mbedtls_calloc(1, msg.in_size[1]); if (private_key == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; break; From 99032f6967e8cb780bc6f1066bd77d56929c0c4d Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Sun, 10 Feb 2019 12:58:54 +0200 Subject: [PATCH 2/5] Change PSA_CRYPTO_ACCESS_CONTROL_RESET into static inline function --- .../crypto/COMPONENT_SPE/psa_crypto_access_control.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c index 3ebe5eb5b6..ec7ba0aebe 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c @@ -28,16 +28,19 @@ typedef struct psa_crypto_access_control_s { static psa_crypto_access_control_t crypto_access_control_arr[PSA_KEY_SLOT_COUNT]; -#define PSA_CRYPTO_ACCESS_CONTROL_RESET() (memset(crypto_access_control_arr, 0, sizeof(crypto_access_control_arr))) +static inline void psa_crypto_access_control_reset() +{ + memset(crypto_access_control_arr, 0, sizeof(crypto_access_control_arr)); +} void psa_crypto_access_control_init(void) { - PSA_CRYPTO_ACCESS_CONTROL_RESET(); + psa_crypto_access_control_reset(); } void psa_crypto_access_control_destroy(void) { - PSA_CRYPTO_ACCESS_CONTROL_RESET(); + psa_crypto_access_control_reset(); } void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id) From 672712ca8a99e6978ccd24a522c21b56d43eea64 Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Wed, 20 Feb 2019 15:38:40 +0200 Subject: [PATCH 3/5] Add SPM_PANIC macro for TARGET_TFM --- .../crypto/COMPONENT_SPE/psa_crypto_access_control.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c index ec7ba0aebe..84df52973e 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c @@ -19,7 +19,15 @@ #include "psa_crypto_access_control.h" #include "psa_crypto_slot_management.h" + +#if defined(TARGET_TFM) +#define SPM_PANIC(format, ...) \ +{ \ + while(1){}; \ +} +#else #include "spm_panic.h" +#endif typedef struct psa_crypto_access_control_s { psa_key_handle_t key_handle; From 0c231b0ac9e2798c4ffb4f877932c5a206d005b8 Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Wed, 20 Feb 2019 17:08:56 +0200 Subject: [PATCH 4/5] Move include psa_crypto_core.h to C file --- .../services/crypto/COMPONENT_SPE/psa_crypto_access_control.c | 1 + .../services/crypto/COMPONENT_SPE/psa_crypto_access_control.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c index 84df52973e..579dd3646a 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.c @@ -18,6 +18,7 @@ #include #include "psa_crypto_access_control.h" +#include "psa_crypto_core.h" #include "psa_crypto_slot_management.h" #if defined(TARGET_TFM) diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h index 4e654124c9..06efac42ca 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h @@ -20,7 +20,6 @@ #include -#include "psa_crypto_core.h" #include "crypto_platform.h" void psa_crypto_access_control_init(void); From 37cc25726caaba52cf9d990a46332483f4372973 Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Wed, 20 Feb 2019 17:40:51 +0200 Subject: [PATCH 5/5] Add internal documentation to access control header file This file is for internal use only. --- .../crypto/COMPONENT_SPE/psa_crypto_access_control.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h index 06efac42ca..c588e1423c 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h +++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_access_control.h @@ -22,14 +22,19 @@ #include "crypto_platform.h" +/* initialize the module, resets all tracked information */ void psa_crypto_access_control_init(void); +/* deinitialize the module, resets all tracked information */ void psa_crypto_access_control_destroy(void); +/* tracks and associates the key_handle with partition_id */ void psa_crypto_access_control_register_handle(psa_key_handle_t key_handle, int32_t partition_id); +/* removes tracking of the key_handle */ void psa_crypto_access_control_unregister_handle(psa_key_handle_t key_handle); +/* checks if the key_handle is associated with the partition_id, returns 0 is false otherwise 1 */ uint8_t psa_crypto_access_control_is_handle_permitted(psa_key_handle_t key_handle, int32_t partition_id); #endif /* PSA_CRYPTO_ACCESS_CONTROL_H */