Merge pull request #9638 from itayzafrir/crypto-access-control

Crypto Service - keys access control
pull/9878/head
Martin Kojtal 2019-02-27 14:47:49 +01:00 committed by GitHub
commit 7656891179
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 279 additions and 6 deletions

View File

@ -0,0 +1,92 @@
/*
* 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 <string.h>
#include "psa_crypto_access_control.h"
#include "psa_crypto_core.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;
int32_t partition_id;
} psa_crypto_access_control_t;
static psa_crypto_access_control_t crypto_access_control_arr[PSA_KEY_SLOT_COUNT];
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();
}
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;
}

View File

@ -0,0 +1,40 @@
/*
* 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 <stdint.h>
#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 */

View File

@ -17,6 +17,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"
@ -139,6 +140,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();
}
}
@ -176,6 +178,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();
}
@ -225,6 +228,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);
@ -232,6 +241,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);
@ -587,6 +602,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;
@ -773,6 +794,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: {
@ -892,6 +919,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);
@ -899,6 +932,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);
@ -1031,6 +1070,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) {
@ -1055,11 +1095,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) {
@ -1074,6 +1122,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) {
@ -1088,6 +1142,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);
@ -1098,7 +1158,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;
@ -1117,13 +1185,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 (msg.out_size[0] >= sizeof(psa_key_type_t))
@ -1139,7 +1224,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;
@ -1160,7 +1253,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;
@ -1184,6 +1285,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");
@ -1214,6 +1321,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;
@ -1234,6 +1342,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;
@ -1254,13 +1363,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;
}
@ -1443,6 +1563,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)) {
@ -1466,7 +1592,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;
@ -1503,8 +1637,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;