mirror of https://github.com/ARMmbed/mbed-os.git
psa: Remove S-mode only code
Remove all PSA S-mode only code, as it is unused. Only PSA S targets would use the code, and we've removed those targets in a previous commit. Ensure all tests for S-mode code we are deleting is also removed, even if that code would run in NS-mode. Keep any tests that also test our PSA emulation support (for single v7-M targets). Signed-off-by: Jaeden Amero <jaeden.amero@arm.com>pull/12737/head
parent
6b3a9cb4fa
commit
fcf427ac11
|
@ -1,49 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 __MBED_HAL_SPM_FAULT_FUNCTIONS__
|
||||
#define __MBED_HAL_SPM_FAULT_FUNCTIONS__
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Retruns the value of the LR register
|
||||
// Used to determine which stack the exception happend in
|
||||
__STATIC_FORCEINLINE uint32_t __get_LR(void);
|
||||
|
||||
// This function is required as we need a symbol/address
|
||||
// to jump to from fault handler.
|
||||
void do_nothing(void);
|
||||
|
||||
// Test exception handler
|
||||
static void hard_fault_handler_test();
|
||||
|
||||
// Using naked function as it will not be executed from beginning to the end.
|
||||
// The execution flow expected to be interrupted by exception and we will
|
||||
// return to other function.
|
||||
// compiler will not produce prolog and epilog code for naked function
|
||||
// and thus will preserve stack in un-corrupted state
|
||||
__attribute__((naked)) void call_mem(uint32_t addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MBED_HAL_SPM_FAULT_FUNCTIONS__
|
|
@ -1,162 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if !defined(COMPONENT_PSA_SRV_IPC)
|
||||
#error [NOT_SUPPORTED] Test supported only on PSA targets
|
||||
#else
|
||||
|
||||
#if (defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
|
||||
#error [NOT_SUPPORTED] this test is supported on GCC only
|
||||
#else
|
||||
|
||||
#if DOMAIN_NS == 1
|
||||
#error [NOT_SUPPORTED] Cannot run on M23/M33 core as SecureFault is implemented in secure-side and cant be remapped
|
||||
#else
|
||||
|
||||
#include "utest/utest.h"
|
||||
#include "unity/unity.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "cmsis.h"
|
||||
#include "spm_api.h"
|
||||
#include <stdlib.h>
|
||||
#include "fault_functions.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
||||
#define HARDFAULT_IRQn ((IRQn_Type)-13)
|
||||
#define EXC_RETURN_RETURN_STACK_MSK ((uint32_t)(0x00000004))
|
||||
#define PC_INDEX_IN_STACK_FRAME 6
|
||||
|
||||
volatile uint32_t fault_occurred;
|
||||
uint32_t real_hard_fault_handler;
|
||||
|
||||
__STATIC_FORCEINLINE uint32_t __get_LR(void)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__ASM volatile("MOV %0, lr" : "=r"(result));
|
||||
return (result);
|
||||
}
|
||||
|
||||
void do_nothing(void)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
|
||||
static void hard_fault_handler_test()
|
||||
{
|
||||
fault_occurred++;
|
||||
// LR is set EXC_RETURN
|
||||
// lowest bits identify PSP vs MSP stack used for stacking
|
||||
uint32_t lr = __get_LR();
|
||||
uint32_t sp;
|
||||
|
||||
if (lr & EXC_RETURN_RETURN_STACK_MSK) {
|
||||
sp = __get_PSP();
|
||||
} else {
|
||||
sp = __get_MSP();
|
||||
}
|
||||
|
||||
// Overwrite return address.
|
||||
// Fake return to a our special function since current
|
||||
// instruction under test will always fail due to memory protection
|
||||
((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing;
|
||||
}
|
||||
|
||||
__attribute__((naked)) void call_mem(uint32_t addr)
|
||||
{
|
||||
// Only first instruction will be executed in positive flow,
|
||||
// since exception will be generated for invalid memory access.
|
||||
// Other instructions are for calling do_nothing function according to AAPCS.
|
||||
__ASM(
|
||||
"LDR r3, [r0]\n"
|
||||
"BX lr\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void test_memory(uint32_t addr, uint32_t expected_fatal_count)
|
||||
{
|
||||
call_mem(addr);
|
||||
// Although call_mem is a "naked" function, it is called using AAPCS.
|
||||
// Thus we can assume LR will point to next instruction, and caller save registers are backed up
|
||||
TEST_ASSERT_EQUAL(expected_fatal_count, fault_occurred);
|
||||
}
|
||||
|
||||
static void secure_ram_fault_test(void)
|
||||
{
|
||||
test_memory(PSA_SECURE_RAM_START, 1);
|
||||
}
|
||||
|
||||
static void secure_flash_fault_test(void)
|
||||
{
|
||||
test_memory(PSA_SECURE_ROM_START, 1);
|
||||
}
|
||||
|
||||
static void non_secure_ram_fault_test(void)
|
||||
{
|
||||
test_memory(PSA_NON_SECURE_RAM_START, 0);
|
||||
}
|
||||
|
||||
static void non_secure_flash_fault_test(void)
|
||||
{
|
||||
test_memory(PSA_NON_SECURE_ROM_START, 0);
|
||||
}
|
||||
|
||||
utest::v1::status_t fault_override_setup(const Case *const source, const size_t index_of_case)
|
||||
{
|
||||
// Save old hard fault handler and replace it with a new one
|
||||
// NOTE: only works when VTOR is set to RAM
|
||||
real_hard_fault_handler = NVIC_GetVector(HARDFAULT_IRQn);
|
||||
NVIC_SetVector(HARDFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
|
||||
fault_occurred = 0;
|
||||
|
||||
return greentea_case_setup_handler(source, index_of_case);
|
||||
}
|
||||
|
||||
utest::v1::status_t fault_override_teardown(const Case *const source, const size_t passed, const size_t failed,
|
||||
const failure_t reason)
|
||||
{
|
||||
// Restore real hard fault handler
|
||||
NVIC_SetVector(HARDFAULT_IRQn, real_hard_fault_handler);
|
||||
|
||||
return greentea_case_teardown_handler(source, passed, failed, reason);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("SPM - Access non-secure RAM", fault_override_setup, non_secure_ram_fault_test, fault_override_teardown),
|
||||
Case("SPM - Access non-secure Flash", fault_override_setup, non_secure_flash_fault_test, fault_override_teardown),
|
||||
Case("SPM - Access secure RAM", fault_override_setup, secure_ram_fault_test, fault_override_teardown),
|
||||
Case("SPM - Access secure Flash", fault_override_setup, secure_flash_fault_test, fault_override_teardown)
|
||||
};
|
||||
|
||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||
|
||||
int main()
|
||||
{
|
||||
Harness::run(specification);
|
||||
}
|
||||
|
||||
#endif // DOMAIN_NS == 1
|
||||
#endif // (defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
|
||||
#endif // !defined(COMPONENT_PSA_SRV_IPC)
|
|
@ -1,556 +0,0 @@
|
|||
/*
|
||||
* 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 "psa/crypto.h"
|
||||
|
||||
#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C)) || (!defined(COMPONENT_PSA_SRV_IPC)))
|
||||
#error [NOT_SUPPORTED] These tests can run only on SPM-enabled targets and where Mbed Crypto is ON - skipping.
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "entropy.h"
|
||||
#include "entropy_poll.h"
|
||||
#include "test_partition_proxy.h"
|
||||
#include "psa/lifecycle.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
|
||||
|
||||
#if !defined(MAX)
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \
|
||||
MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
|
||||
|
||||
void inject_entropy()
|
||||
{
|
||||
uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
|
||||
for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
|
||||
seed[i] = i;
|
||||
}
|
||||
mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
|
||||
}
|
||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
|
||||
|
||||
static psa_status_t create_and_generate_key_via_test_partition(
|
||||
const psa_key_attributes_t *attributes,
|
||||
psa_key_handle_t *key_handle,
|
||||
uint8_t close_key)
|
||||
{
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
test_partition_crypto_generate_key(attributes,
|
||||
key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, *key_handle);
|
||||
if (close_key) {
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(*key_handle));
|
||||
}
|
||||
return (PSA_SUCCESS);
|
||||
}
|
||||
|
||||
void test_open_other_partition_key(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
|
||||
static const size_t key_bits = 128;
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* via test partition - close the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
|
||||
|
||||
/* try to open the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, psa_open_key(key_id, &key_handle));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition and keep it open */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_create_key_same_id_different_partitions(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_key_usage_t key_usage_remote = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
|
||||
key_usage_local = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
|
||||
static const size_t key_bits_remote = 128,
|
||||
key_bits_local = 256;
|
||||
psa_key_handle_t key_handle_remote = 0,
|
||||
key_handle_local = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage_remote);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits_remote);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle_remote, 1));
|
||||
psa_reset_key_attributes(&attributes);
|
||||
|
||||
/* create a key, generate key material and close from current partition (i.e. NSPE) */
|
||||
psa_set_key_usage_flags(&attributes, key_usage_local);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits_local);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(&attributes, &key_handle_local));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle_local);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_close_key(key_handle_local));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle_remote = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle_remote));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle_remote);
|
||||
|
||||
/* reopen the key created from the current partition (NSPE) */
|
||||
key_handle_local = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_open_key(key_id, &key_handle_local));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle_local);
|
||||
|
||||
/* via test partition - get key info for the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
test_partition_crypto_get_key_attributes(key_handle_remote,
|
||||
&attributes));
|
||||
TEST_ASSERT_EQUAL(key_type, psa_get_key_type(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_bits_remote, psa_get_key_bits(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_usage_remote, psa_get_key_usage_flags(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_alg, psa_get_key_algorithm(&attributes));
|
||||
|
||||
/* get key attributes for key created by the current partition (NSPE) */
|
||||
attributes = psa_key_attributes_init();
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_attributes(key_handle_local, &attributes));
|
||||
TEST_ASSERT_EQUAL(key_type, psa_get_key_type(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_bits_local, psa_get_key_bits(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_usage_local, psa_get_key_usage_flags(&attributes));
|
||||
TEST_ASSERT_EQUAL(key_alg, psa_get_key_algorithm(&attributes));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle_remote));
|
||||
|
||||
/* destroy the key created by the current partition (NSPE) */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle_local));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_manage_key(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_EXPORT;
|
||||
static const size_t key_bits = 128;
|
||||
static const uint8_t key_data[] = {
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
|
||||
};
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
uint8_t output[sizeof(key_data)] = { 0 };
|
||||
size_t len;
|
||||
|
||||
/* via test partition - generate a persistent key and close the key */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_generate_key(&attributes, &key_handle));
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition and keep it open */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to work with the handle created for a key created by the test partition */
|
||||
attributes = psa_key_attributes_init();
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_get_key_attributes(key_handle, &attributes));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_close_key(key_handle));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_destroy_key(key_handle));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_export_key(key_handle, output, sizeof(output), &len));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_export_public_key(key_handle, output, sizeof(output), &len));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
|
||||
/* via test partition - import key data for the key created by the test partition */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
test_partition_crypto_import_key(
|
||||
&attributes, key_data, sizeof(key_data), &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_mac(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
|
||||
static const size_t key_bits = 128;
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_mac_operation_t operation;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to setup mac sign operation using the key that was created by the test partition */
|
||||
operation = psa_mac_operation_init();
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_mac_sign_setup(&operation, key_handle, key_alg));
|
||||
|
||||
/* try to setup mac verify operation using the key that was created by the test partition */
|
||||
operation = psa_mac_operation_init();
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_mac_verify_setup(&operation, key_handle, key_alg));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_cipher(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_CBC_NO_PADDING;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
|
||||
static const size_t key_bits = 128;
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_cipher_operation_t operation;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to setup cipher encrypt operation using the key that was created by the test partition */
|
||||
operation = psa_cipher_operation_init();
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_cipher_encrypt_setup(&operation, key_handle, key_alg));
|
||||
|
||||
/* try to setup cipher decrypt operation using the key that was created by the test partition */
|
||||
operation = psa_cipher_operation_init();
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_cipher_decrypt_setup(&operation, key_handle, key_alg));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_aead(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_AES;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_GCM;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
|
||||
static const size_t key_bits = 128;
|
||||
static const uint8_t nonce[16] = { 0 };
|
||||
uint8_t plain_text[] = "encrypt me!";
|
||||
uint8_t cipher_text[PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_alg, sizeof(plain_text))] = { 0 };
|
||||
psa_key_handle_t key_handle = 0;
|
||||
size_t len;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to aead encrypt using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_aead_encrypt(key_handle, key_alg, nonce, sizeof(nonce), NULL, 0,
|
||||
plain_text, sizeof(plain_text),
|
||||
cipher_text, sizeof(cipher_text), &len));
|
||||
|
||||
/* try to aead decrypt using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_aead_decrypt(key_handle, key_alg, nonce, sizeof(nonce), NULL, 0,
|
||||
cipher_text, sizeof(cipher_text),
|
||||
plain_text, sizeof(plain_text), &len));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_asymmetric_sign_verify(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1);
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
|
||||
static const size_t key_bits = 256;
|
||||
static const uint8_t input[] = "hello world!";
|
||||
uint8_t signature[PSA_ECDSA_SIGNATURE_SIZE(key_bits)] = { 0 };
|
||||
psa_key_handle_t key_handle = 0;
|
||||
size_t len;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - create a key, generate key material and close */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
create_and_generate_key_via_test_partition(&attributes, &key_handle, 1));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to asymmetric sign using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_sign_hash(key_handle, key_alg, input, sizeof(input),
|
||||
signature, sizeof(signature), &len));
|
||||
|
||||
/* try to asymmetric verify using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_verify_hash(key_handle, key_alg, input, sizeof(input),
|
||||
signature, sizeof(signature)));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_asymmetric_encrypt_decrypt(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
|
||||
static const uint8_t input[] = "encrypt me!";
|
||||
static const uint8_t key_data[] = {
|
||||
0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xee, 0x2b,
|
||||
0x13, 0x1d, 0x6b, 0x18, 0x18, 0xa9, 0x4c, 0xa8, 0xe9, 0x1c, 0x42, 0x38,
|
||||
0x7e, 0xb1, 0x5a, 0x7c, 0x27, 0x1f, 0x57, 0xb8, 0x9e, 0x73, 0x36, 0xb1,
|
||||
0x44, 0xd4, 0x53, 0x5b, 0x16, 0xc8, 0x30, 0x97, 0xec, 0xde, 0xfb, 0xbb,
|
||||
0x92, 0xd1, 0xb5, 0x31, 0x3b, 0x5a, 0x37, 0x21, 0x4d, 0x0e, 0x8f, 0x25,
|
||||
0x92, 0x2d, 0xca, 0x77, 0x8b, 0x42, 0x4b, 0x25, 0x29, 0x5f, 0xc8, 0xa1,
|
||||
0xa7, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x41, 0x00, 0x97, 0x8a,
|
||||
0xc8, 0xea, 0xdb, 0x0d, 0xc6, 0x03, 0x53, 0x47, 0xd6, 0xab, 0xa8, 0x67,
|
||||
0x12, 0x15, 0xff, 0x21, 0x28, 0x33, 0x85, 0x39, 0x6f, 0x78, 0x97, 0xc0,
|
||||
0x4b, 0xaf, 0x5e, 0x2a, 0x83, 0x5f, 0x3b, 0x53, 0xef, 0x80, 0xa8, 0x2e,
|
||||
0xd3, 0x6a, 0xe6, 0x87, 0xa9, 0x25, 0x38, 0x0b, 0x55, 0xa0, 0xc7, 0x3e,
|
||||
0xb8, 0x56, 0x56, 0xe9, 0x89, 0xdc, 0xf0, 0xed, 0x7f, 0xb4, 0x88, 0x70,
|
||||
0x24, 0xe1, 0x02, 0x21, 0x00, 0xfd, 0xad, 0x8e, 0x1c, 0x68, 0x53, 0x56,
|
||||
0x3f, 0x8b, 0x92, 0x1d, 0x2d, 0x11, 0x24, 0x62, 0xae, 0x7d, 0x6b, 0x17,
|
||||
0x60, 0x82, 0xd2, 0xba, 0x43, 0xe8, 0x7e, 0x1a, 0x37, 0xfc, 0x1a, 0x8b,
|
||||
0x33, 0x02, 0x21, 0x00, 0xf0, 0x59, 0x2c, 0xf4, 0xc5, 0x5b, 0xa4, 0x43,
|
||||
0x07, 0xb1, 0x89, 0x81, 0xbc, 0xdb, 0xda, 0x37, 0x6c, 0x51, 0xe5, 0x90,
|
||||
0xff, 0xa5, 0x34, 0x5b, 0xa8, 0x66, 0xf6, 0x96, 0x2d, 0xca, 0x94, 0xdd,
|
||||
0x02, 0x20, 0x19, 0x95, 0xf1, 0xa9, 0x67, 0xd4, 0x4f, 0xf4, 0xa4, 0xcd,
|
||||
0x1d, 0xe8, 0x37, 0xbc, 0x65, 0xbf, 0x97, 0xa2, 0xbf, 0x7e, 0xda, 0x73,
|
||||
0x0a, 0x9a, 0x62, 0xce, 0xa5, 0x32, 0x54, 0x59, 0x11, 0x05, 0x02, 0x20,
|
||||
0x27, 0xf9, 0x6c, 0xf4, 0xb8, 0xee, 0x68, 0xff, 0x8d, 0x04, 0x06, 0x2e,
|
||||
0xc1, 0xce, 0x7f, 0x18, 0xc0, 0xb7, 0x4e, 0x4b, 0x33, 0x79, 0xb2, 0x9f,
|
||||
0x9b, 0xfe, 0xa3, 0xfc, 0x8e, 0x59, 0x27, 0x31, 0x02, 0x21, 0x00, 0xce,
|
||||
0xfa, 0x6d, 0x22, 0x04, 0x96, 0xb4, 0x3f, 0xeb, 0x83, 0x19, 0x42, 0x55,
|
||||
0xd8, 0xfb, 0x93, 0x0a, 0xfc, 0xf4, 0x6f, 0x36, 0x60, 0x6e, 0x3a, 0xa0,
|
||||
0xeb, 0x7a, 0x93, 0xad, 0x88, 0xc1, 0x0c
|
||||
};
|
||||
uint8_t encrypted[64] = { 0 };
|
||||
uint8_t decrypted[sizeof(input)] = { 0 };
|
||||
psa_key_handle_t key_handle = 0;
|
||||
size_t len;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - import key data for the key created by the test partition */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, 512);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
test_partition_crypto_import_key(
|
||||
&attributes, key_data, sizeof(key_data), &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* via test partition - close the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_close_key(key_handle));
|
||||
|
||||
/* via test partition - reopen the key created by the test partition and keep it open */
|
||||
key_handle = 0;
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_open_key(key_id, &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to asymmetric encrypt using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_encrypt(key_handle, key_alg, input, sizeof(input),
|
||||
NULL, 0, encrypted, sizeof(encrypted), &len));
|
||||
|
||||
/* try to asymmetric decrypt using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_decrypt(key_handle, key_alg,
|
||||
encrypted, sizeof(encrypted), NULL, 0,
|
||||
decrypted, sizeof(decrypted), &len));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
void test_use_other_partition_key_derivation_setup(void)
|
||||
{
|
||||
static const psa_key_id_t key_id = 999;
|
||||
static const psa_algorithm_t key_alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
|
||||
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_DERIVE;
|
||||
static const psa_key_type_t key_type = PSA_KEY_TYPE_DERIVE;
|
||||
static const uint8_t key_data[] = {
|
||||
0x30, 0x82, 0x01, 0x3b, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xee, 0x2b,
|
||||
0x13, 0x1d, 0x6b, 0x18, 0x18, 0xa9, 0x4c, 0xa8, 0xe9, 0x1c, 0x42, 0x38
|
||||
};
|
||||
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
|
||||
size_t bits = 192;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
/* via test partition - import key data for the key created by the test partition */
|
||||
psa_set_key_usage_flags(&attributes, key_usage);
|
||||
psa_set_key_algorithm(&attributes, key_alg);
|
||||
psa_set_key_bits(&attributes, bits);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_id(&attributes, key_id);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS,
|
||||
test_partition_crypto_import_key(
|
||||
&attributes, key_data, sizeof(key_data), &key_handle));
|
||||
TEST_ASSERT_NOT_EQUAL(0, key_handle);
|
||||
|
||||
/* try to setup key derivation using the key that was created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_key_derivation_setup(&operation, key_alg));
|
||||
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE,
|
||||
psa_key_derivation_input_key(
|
||||
&operation, PSA_KEY_DERIVATION_INPUT_SECRET, key_handle));
|
||||
|
||||
/* via test partition - destroy the key created by the test partition */
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
|
||||
}
|
||||
|
||||
utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case)
|
||||
{
|
||||
psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
status = psa_crypto_init();
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
|
||||
if (status == PSA_ERROR_INSUFFICIENT_ENTROPY) {
|
||||
inject_entropy();
|
||||
status = psa_crypto_init();
|
||||
}
|
||||
#endif
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
return greentea_case_setup_handler(source, index_of_case);
|
||||
}
|
||||
|
||||
utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed,
|
||||
const size_t failed, const failure_t failure)
|
||||
{
|
||||
psa_status_t status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
mbedtls_psa_crypto_free();
|
||||
return greentea_case_teardown_handler(source, passed, failed, failure);
|
||||
}
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(120, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("open other partition's key",
|
||||
case_setup_handler, test_open_other_partition_key, case_teardown_handler),
|
||||
Case("create key with same id different partitions",
|
||||
case_setup_handler, test_create_key_same_id_different_partitions, case_teardown_handler),
|
||||
Case("use other partition's key - key manage",
|
||||
case_setup_handler, test_use_other_partition_key_manage_key, case_teardown_handler),
|
||||
Case("use other partition's key - mac",
|
||||
case_setup_handler, test_use_other_partition_key_mac, case_teardown_handler),
|
||||
Case("use other partition's key - cipher",
|
||||
case_setup_handler, test_use_other_partition_key_cipher, case_teardown_handler),
|
||||
Case("use other partition's key - aead",
|
||||
case_setup_handler, test_use_other_partition_key_aead, case_teardown_handler),
|
||||
Case("use other partition's key - asymmetric sign verify",
|
||||
case_setup_handler, test_use_other_partition_key_asymmetric_sign_verify, case_teardown_handler),
|
||||
Case("use other partition's key - asymmetric encrypt decrypt",
|
||||
case_setup_handler, test_use_other_partition_key_asymmetric_encrypt_decrypt, case_teardown_handler),
|
||||
Case("use other partition's key - key derivation setup",
|
||||
case_setup_handler, test_use_other_partition_key_derivation_setup, case_teardown_handler),
|
||||
};
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return !Harness::run(specification);
|
||||
}
|
||||
|
||||
#endif // ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C)) || (!defined(COMPONENT_PSA_SRV_IPC)))
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* 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 "psa/client.h"
|
||||
#include "psa_manifest/sid.h"
|
||||
#include "test_partition_proxy.h"
|
||||
|
||||
#define MINOR_VER 1
|
||||
|
||||
static psa_status_t invoke_ipc_call(uint32_t sid, psa_invec *in_vec, size_t in_vec_size,
|
||||
psa_outvec *out_vec, size_t out_vec_size)
|
||||
{
|
||||
psa_status_t status;
|
||||
|
||||
psa_handle_t handle = psa_connect(sid, MINOR_VER);
|
||||
if (handle <= 0) {
|
||||
return (PSA_ERROR_COMMUNICATION_FAILURE);
|
||||
}
|
||||
|
||||
status = psa_call(handle, in_vec, in_vec_size, out_vec, out_vec_size);
|
||||
psa_close(handle);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_get_key_attributes(
|
||||
psa_key_handle_t key_handle, psa_key_attributes_t *attributes)
|
||||
{
|
||||
psa_invec in_vec = { &key_handle, sizeof(key_handle) };
|
||||
psa_outvec out_vec[1] = {
|
||||
{ attributes, sizeof(*attributes) }
|
||||
};
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_GET_KEY_ATTRIBUTES, &in_vec, 1, out_vec, 1);
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_generate_key(
|
||||
const psa_key_attributes_t *attributes, psa_key_handle_t *key_handle)
|
||||
{
|
||||
psa_invec in_vec[] = {
|
||||
{ attributes, sizeof(*attributes) },
|
||||
};
|
||||
psa_outvec out_vec[] = {
|
||||
{ key_handle, sizeof(*key_handle) },
|
||||
};
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_GENERATE_KEY, in_vec, 1, out_vec, 1);
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_open_key(psa_key_id_t key_id, psa_key_handle_t *key_handle)
|
||||
{
|
||||
psa_invec in_vec = { &key_id, sizeof(key_id) };
|
||||
psa_outvec out_vec = { key_handle, sizeof(*key_handle) };
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_OPEN_KEY, &in_vec, 1, &out_vec, 1);
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_close_key(psa_key_handle_t key_handle)
|
||||
{
|
||||
psa_invec in_vec = { &key_handle, sizeof(key_handle) };
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_CLOSE_KEY, &in_vec, 1, NULL, 0);
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_destroy_key(psa_key_handle_t key_handle)
|
||||
{
|
||||
psa_invec in_vec = { &key_handle, sizeof(key_handle) };
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_DESTROY_KEY, &in_vec, 1, NULL, 0);
|
||||
return (status);
|
||||
}
|
||||
|
||||
psa_status_t test_partition_crypto_import_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_data,
|
||||
size_t key_data_size,
|
||||
psa_key_handle_t *key_handle)
|
||||
{
|
||||
psa_invec in_vec[] = {
|
||||
{ attributes, sizeof(*attributes) },
|
||||
{ key_data, key_data_size },
|
||||
};
|
||||
psa_outvec out_vec[] = {
|
||||
{ key_handle, sizeof(*key_handle) },
|
||||
};
|
||||
psa_status_t status = invoke_ipc_call(CRYPTO_IMPORT_KEY, in_vec, 2, out_vec, 1);
|
||||
return (status);
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* 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 TEST_PARTITION_PROXY_H
|
||||
#define TEST_PARTITION_PROXY_H
|
||||
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
psa_status_t test_partition_crypto_get_key_attributes(
|
||||
psa_key_handle_t key_handle, psa_key_attributes_t *attributes);
|
||||
|
||||
psa_status_t test_partition_crypto_generate_key(
|
||||
const psa_key_attributes_t *attributes, psa_key_handle_t *key_handle);
|
||||
|
||||
psa_status_t test_partition_crypto_open_key(
|
||||
psa_key_id_t key_id, psa_key_handle_t *key_handle);
|
||||
|
||||
psa_status_t test_partition_crypto_close_key(psa_key_handle_t key_handle);
|
||||
|
||||
psa_status_t test_partition_crypto_destroy_key(psa_key_handle_t key_handle);
|
||||
|
||||
psa_status_t test_partition_crypto_import_key(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_data,
|
||||
size_t key_data_size,
|
||||
psa_key_handle_t *key_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_PARTITION_PROXY_H */
|
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include "mbed_spm_partitions.h"
|
||||
#include "psa/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
|
||||
|
||||
static void read_input_param_from_message(psa_msg_t *msg, uint8_t param_index, void *param_ptr)
|
||||
{
|
||||
size_t bytes_read = psa_read(msg->handle, param_index, param_ptr, msg->in_size[param_index]);
|
||||
if (bytes_read != msg->in_size[param_index]) {
|
||||
SPM_PANIC("SPM read length mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
static psa_status_t crypto_generate_key(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle = 0;
|
||||
psa_key_type_t key_type = 0;
|
||||
size_t key_bits = 0;
|
||||
psa_key_attributes_t attributes;
|
||||
|
||||
read_input_param_from_message(msg, 0, &attributes);
|
||||
|
||||
status = psa_generate_key(&attributes, &key_handle);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
static psa_status_t crypto_open_key(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_id_t key_id;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
read_input_param_from_message(msg, 0, &key_id);
|
||||
|
||||
status = psa_open_key(key_id, &key_handle);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
static psa_status_t crypto_close_key(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
read_input_param_from_message(msg, 0, &key_handle);
|
||||
|
||||
status = psa_close_key(key_handle);
|
||||
return (status);
|
||||
}
|
||||
|
||||
static psa_status_t crypto_destroy_key(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
|
||||
read_input_param_from_message(msg, 0, &key_handle);
|
||||
|
||||
status = psa_destroy_key(key_handle);
|
||||
return (status);
|
||||
}
|
||||
|
||||
static psa_status_t crypto_get_key_attributes(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
psa_key_attributes_t attributes;
|
||||
|
||||
read_input_param_from_message(msg, 0, &key_handle);
|
||||
|
||||
status = psa_get_key_attributes(key_handle, &attributes);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &attributes, sizeof(attributes));
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
static psa_status_t crypto_import_key(psa_msg_t *msg)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_handle_t key_handle;
|
||||
psa_key_attributes_t attributes;
|
||||
uint8_t *key_data;
|
||||
size_t key_data_size = msg->in_size[1];
|
||||
|
||||
read_input_param_from_message(msg, 0, &attributes);
|
||||
|
||||
key_data = calloc(1, key_data_size);
|
||||
if (key_data == NULL) {
|
||||
return (PSA_ERROR_INSUFFICIENT_MEMORY);
|
||||
}
|
||||
read_input_param_from_message(msg, 1, key_data);
|
||||
|
||||
status = psa_import_key(&attributes, key_data, key_data_size, &key_handle);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &key_handle, sizeof(key_handle));
|
||||
}
|
||||
free(key_data);
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
|
||||
{
|
||||
psa_status_t status = 0;
|
||||
|
||||
switch (msg->type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
status = handler(msg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %d!", (int)(msg->type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
psa_reply(msg->handle, status);
|
||||
}
|
||||
|
||||
void test_partition_main(void)
|
||||
{
|
||||
psa_signal_t signal;
|
||||
psa_msg_t msg = {0};
|
||||
while (1) {
|
||||
signal = psa_wait(CRYPTO_ACL_TEST_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
if (signal & CRYPTO_GENERATE_KEY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_GENERATE_KEY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_generate_key);
|
||||
}
|
||||
if (signal & CRYPTO_OPEN_KEY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_OPEN_KEY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_open_key);
|
||||
}
|
||||
if (signal & CRYPTO_CLOSE_KEY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_CLOSE_KEY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_close_key);
|
||||
}
|
||||
if (signal & CRYPTO_DESTROY_KEY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_DESTROY_KEY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_destroy_key);
|
||||
}
|
||||
if (signal & CRYPTO_GET_KEY_ATTRIBUTES_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_GET_KEY_ATTRIBUTES_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_get_key_attributes);
|
||||
}
|
||||
if (signal & CRYPTO_IMPORT_KEY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(CRYPTO_IMPORT_KEY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, crypto_import_key);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
{
|
||||
"name": "CRYPTO_ACL_TEST",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000080",
|
||||
"entry_point": "test_partition_main",
|
||||
"stack_size": "0x200",
|
||||
"heap_size": "0x400",
|
||||
"services": [
|
||||
{
|
||||
"name": "CRYPTO_GENERATE_KEY",
|
||||
"identifier": "0x00000201",
|
||||
"signal": "CRYPTO_GENERATE_KEY_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CRYPTO_OPEN_KEY",
|
||||
"identifier": "0x00000202",
|
||||
"signal": "CRYPTO_OPEN_KEY_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CRYPTO_CLOSE_KEY",
|
||||
"identifier": "0x00000203",
|
||||
"signal": "CRYPTO_CLOSE_KEY_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CRYPTO_DESTROY_KEY",
|
||||
"identifier": "0x00000205",
|
||||
"signal": "CRYPTO_DESTROY_KEY_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CRYPTO_GET_KEY_ATTRIBUTES",
|
||||
"identifier": "0x00000206",
|
||||
"signal": "CRYPTO_GET_KEY_ATTRIBUTES_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CRYPTO_IMPORT_KEY",
|
||||
"identifier": "0x00000208",
|
||||
"signal": "CRYPTO_IMPORT_KEY_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
}
|
||||
],
|
||||
"extern_sids": [
|
||||
"PSA_KEY_MNG_ID"
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/test_partition.c"
|
||||
]
|
||||
}
|
|
@ -1,487 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 COMPONENT_PSA_SRV_IPC
|
||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
|
||||
#else
|
||||
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "psa/client.h"
|
||||
#include "psa_manifest/sid.h"
|
||||
|
||||
#if defined(TARGET_TFM)
|
||||
#define MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS TFM_CONN_HANDLE_MAX_NUM
|
||||
#define PSA_MAX_IOVEC 4
|
||||
#endif
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define MINOR_VER 0
|
||||
#define DROP_CONN_MINOR_VER 5
|
||||
#define CLIENT_RSP_BUF_SIZE 128
|
||||
#define OFFSET_POS 1
|
||||
#define INVALID_SID 0x00001A020
|
||||
|
||||
|
||||
typedef struct th_struct {
|
||||
psa_handle_t handle;
|
||||
psa_invec *iovec_temp;
|
||||
uint8_t *expected;
|
||||
uint8_t expected_size;
|
||||
} th_struct_t;
|
||||
|
||||
/* ------------------------------------- Functions ----------------------------------- */
|
||||
|
||||
static psa_handle_t client_ipc_tests_connect(uint32_t sid, uint32_t minor_version)
|
||||
{
|
||||
psa_handle_t handle = psa_connect(sid, minor_version);
|
||||
|
||||
TEST_ASSERT_TRUE(handle > 0);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void client_ipc_tests_call(
|
||||
psa_handle_t handle,
|
||||
psa_invec *iovec_temp,
|
||||
size_t tx_len,
|
||||
size_t rx_len,
|
||||
uint8_t *expected,
|
||||
uint8_t expected_size
|
||||
)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
uint8_t *response_buf = (uint8_t *)malloc(CLIENT_RSP_BUF_SIZE * sizeof(uint8_t));
|
||||
memset(response_buf, 0, CLIENT_RSP_BUF_SIZE);
|
||||
psa_outvec resp = {NULL, rx_len};
|
||||
|
||||
if (rx_len > 0) {
|
||||
resp.base = response_buf;
|
||||
}
|
||||
|
||||
status = psa_call(handle,
|
||||
(tx_len ? iovec_temp : NULL),
|
||||
tx_len,
|
||||
(rx_len ? &resp : NULL),
|
||||
(rx_len ? 1 : 0)
|
||||
);
|
||||
|
||||
if (expected) {
|
||||
TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, response_buf, expected_size);
|
||||
}
|
||||
free(response_buf);
|
||||
TEST_ASSERT_EQUAL_INT(PSA_SUCCESS, status);
|
||||
}
|
||||
|
||||
static void client_ipc_tests_close(psa_handle_t handle)
|
||||
{
|
||||
psa_close(handle);
|
||||
}
|
||||
|
||||
//Testing iovec 0 sent as NULL
|
||||
void iovec_0_NULL()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
uint8_t expect_size = 5;
|
||||
uint8_t off = 2;
|
||||
|
||||
uint8_t meta_iovec[2] = {expect_size, off};
|
||||
uint8_t buff1[] = {1, 2, 3, 4, 5};
|
||||
uint8_t expected_buff[] = {1, 2, 3, 4, 5};
|
||||
|
||||
psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {
|
||||
{NULL, 0},
|
||||
{meta_iovec, sizeof(meta_iovec)},
|
||||
{buff1, sizeof(buff1)}
|
||||
};
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing iovec 1 sent as NULL
|
||||
void iovec_1_NULL()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
uint8_t expect_size = 2;
|
||||
uint8_t off = 3;
|
||||
|
||||
uint8_t meta_iovec[2] = {expect_size, off};
|
||||
uint8_t buff1[] = {1, 2, 3, 4, 5};
|
||||
uint8_t expected_buff[] = {2, 3};
|
||||
|
||||
psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
|
||||
{NULL, 0},
|
||||
{buff1, sizeof(buff1)}
|
||||
};
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing iovec 2 sent as NULL
|
||||
void iovec_2_NULL()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
uint8_t expect_size = 2;
|
||||
uint8_t off = 3;
|
||||
|
||||
uint8_t meta_iovec[2] = {expect_size, off};
|
||||
uint8_t buff1[] = {1, 2, 3, 4, 5};
|
||||
uint8_t expected_buff[] = {2, 3};
|
||||
|
||||
psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
// Testing in_vec[i] sent with size 0 and base not NULL
|
||||
void in_vec_base_not_NULL_size_0()
|
||||
{
|
||||
uint8_t dummy_buff[] = {1, 2, 3, 4, 5};
|
||||
psa_invec iovec_temp[1] = { {dummy_buff, 0} };
|
||||
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, 1, 0, NULL, 0);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
// Testing in_len is 0 but in_vec is not NULL
|
||||
void in_len_0_in_vec_not_NULL()
|
||||
{
|
||||
uint8_t dummy_buff[] = {1, 2, 3, 4, 5};
|
||||
psa_invec iovec_temp[1] = { {dummy_buff, sizeof(dummy_buff)} };
|
||||
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, 0, 0, NULL, 0);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
// Testing out_len is 0 but out_vec is not NULL
|
||||
void out_len_0_outvec_not_NULL()
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
|
||||
uint8_t dummy_res[10] = {0};
|
||||
psa_outvec outvec_temp[1] = {{dummy_res, sizeof(dummy_res)}};
|
||||
|
||||
uint8_t dummy_buff[] = {1, 2, 3, 4, 5};
|
||||
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
psa_invec in_vec_temp[2] = { {dummy_buff, sizeof(dummy_buff)},
|
||||
{dummy_buff, sizeof(dummy_buff)}
|
||||
};
|
||||
|
||||
status = psa_call(handle, in_vec_temp, 2, outvec_temp, 0);
|
||||
|
||||
TEST_ASSERT_EQUAL_INT32(PSA_SUCCESS, status);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing rx_buff sent as NULL and rx_len as 0
|
||||
void rx_buff_null()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
uint8_t expect_size = 0, off = 2;
|
||||
|
||||
uint8_t meta_iovec[2] = {expect_size, off};
|
||||
uint8_t buff1[] = {1, 2, 3, 4, 5}, buff2[] = {6};
|
||||
|
||||
psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{buff2, sizeof(buff2)}
|
||||
};
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, 0, NULL, 0);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing tx_buff sent as NULL and tx_len as 0
|
||||
void tx_buff_null()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
client_ipc_tests_call(handle, NULL, 0, CLIENT_RSP_BUF_SIZE, NULL, 0);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing rx_buff and tx_null sent as NULL and rx_len and tx_len as 0
|
||||
void rx_tx_null()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
client_ipc_tests_call(handle, NULL, 0, 0, NULL, 0);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing multiple subsequent calls to the same SID
|
||||
void multiple_call()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
uint8_t expect_size = 2, off = 2;
|
||||
|
||||
uint8_t meta_iovec[2] = {expect_size, off};
|
||||
uint8_t buff1[] = {1, 2, 3};
|
||||
uint8_t buff2[] = {4, 5, 6};
|
||||
uint8_t expected_buff[] = {1, 2};
|
||||
|
||||
psa_invec iovec_temp[PSA_MAX_IOVEC - 1] = {{meta_iovec, sizeof(meta_iovec)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{buff2, sizeof(buff2)}
|
||||
};
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
meta_iovec[1] = 3; //off
|
||||
iovec_temp[0].base = meta_iovec;
|
||||
expected_buff[0] = 2;
|
||||
expected_buff[1] = 3;
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
meta_iovec[1] = 4; //off
|
||||
iovec_temp[0].base = meta_iovec;
|
||||
expected_buff[0] = 3;
|
||||
expected_buff[1] = 4;
|
||||
|
||||
client_ipc_tests_call(handle, iovec_temp, PSA_MAX_IOVEC - 1, CLIENT_RSP_BUF_SIZE, expected_buff, sizeof(expected_buff));
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
static void set_struct(th_struct_t *thr_attr, psa_handle_t handle, psa_invec *iovec_temp, uint8_t *expect, uint8_t expected_size)
|
||||
{
|
||||
thr_attr->handle = handle;
|
||||
thr_attr->iovec_temp = iovec_temp;
|
||||
thr_attr->expected = expect;
|
||||
thr_attr->expected_size = expected_size;
|
||||
}
|
||||
|
||||
static void call_diff_handle(th_struct_t *thr_attr)
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
|
||||
client_ipc_tests_call(handle,
|
||||
thr_attr->iovec_temp,
|
||||
PSA_MAX_IOVEC - 1,
|
||||
CLIENT_RSP_BUF_SIZE,
|
||||
thr_attr->expected,
|
||||
thr_attr->expected_size);
|
||||
|
||||
osDelay(10);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
//Testing multiple parallel calls to the same SID with different handles
|
||||
void multi_thread_diff_handles()
|
||||
{
|
||||
Thread T1(osPriorityNormal, 512);
|
||||
Thread T2(osPriorityNormal, 512);
|
||||
Thread T3(osPriorityNormal, 512);
|
||||
|
||||
th_struct_t thr_attr[] = {{0}, {0}, {0}};
|
||||
|
||||
uint8_t meta_iovec_1[] = { 2, //expect_size
|
||||
2 //off
|
||||
};
|
||||
uint8_t buff1[] = {1, 2, 3};
|
||||
uint8_t buff2[] = {4, 5, 6};
|
||||
uint8_t expected_buff_1[] = {1, 2};
|
||||
|
||||
psa_invec iovec_temp_1[PSA_MAX_IOVEC - 1] = {{meta_iovec_1, sizeof(meta_iovec_1)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{buff2, sizeof(buff2)}
|
||||
};
|
||||
|
||||
set_struct(&thr_attr[0], 0, iovec_temp_1, expected_buff_1, sizeof(expected_buff_1));
|
||||
osStatus err = T1.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[0]));
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("creating thread failed!");
|
||||
}
|
||||
|
||||
uint8_t meta_iovec_2[] = { 2, //expect_size
|
||||
3 //off
|
||||
};
|
||||
uint8_t expected_buff_2[] = {2, 3};
|
||||
|
||||
psa_invec iovec_temp_2[PSA_MAX_IOVEC - 1] = {{meta_iovec_2, sizeof(meta_iovec_2)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{buff2, sizeof(buff2)}
|
||||
};
|
||||
set_struct(&thr_attr[1], 0, iovec_temp_2, expected_buff_2, sizeof(expected_buff_2));
|
||||
err = T2.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[1]));
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("creating thread failed!");
|
||||
}
|
||||
|
||||
uint8_t meta_iovec_3[] = { 2, //expect_size
|
||||
4 //off
|
||||
};
|
||||
uint8_t expected_buff_3[] = {3, 4};
|
||||
|
||||
psa_invec iovec_temp_3[PSA_MAX_IOVEC - 1] = {{meta_iovec_3, sizeof(meta_iovec_3)},
|
||||
{buff1, sizeof(buff1)},
|
||||
{buff2, sizeof(buff2)}
|
||||
};
|
||||
|
||||
set_struct(&thr_attr[2], 0, iovec_temp_3, expected_buff_3, sizeof(expected_buff_3));
|
||||
err = T3.start(callback(call_diff_handle, (th_struct_t *)&thr_attr[2]));
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("creating thread failed!");
|
||||
}
|
||||
|
||||
err = T1.join();
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("joining thread failed!");
|
||||
}
|
||||
err = T2.join();
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("joining thread failed!");
|
||||
}
|
||||
err = T3.join();
|
||||
if (err) {
|
||||
TEST_FAIL_MESSAGE("joining thread failed!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//Testing exceeding num of max channels allowed by psa_connect
|
||||
void exceed_num_of_max_channels()
|
||||
{
|
||||
int i = 0;
|
||||
psa_handle_t handle[MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS + 1] = {0};
|
||||
|
||||
for (i = 0; i < MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS + 1; i++) {
|
||||
if (i != MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS) {
|
||||
handle[i] = client_ipc_tests_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
} else {
|
||||
handle[i] = psa_connect(CLIENT_TESTS_PART1_ROT_SRV1, MINOR_VER);
|
||||
TEST_ASSERT_EQUAL_INT32(PSA_CONNECTION_REFUSED, handle[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MBED_CONF_SPM_IPC_MAX_NUM_OF_CHANNELS; i++) {
|
||||
client_ipc_tests_close(handle[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void client_close_null_handle()
|
||||
{
|
||||
client_ipc_tests_close(PSA_NULL_HANDLE);
|
||||
}
|
||||
|
||||
void drop_connection()
|
||||
{
|
||||
psa_handle_t handle = client_ipc_tests_connect(CLIENT_TESTS_PART1_DROP_CONN, DROP_CONN_MINOR_VER);
|
||||
psa_status_t status = psa_call(handle, NULL, 0, NULL, 0);
|
||||
TEST_ASSERT_EQUAL_INT(PSA_DROP_CONNECTION, status);
|
||||
|
||||
status = PSA_SUCCESS;
|
||||
status = psa_call(handle, NULL, 0, NULL, 0);
|
||||
TEST_ASSERT_EQUAL_INT(PSA_DROP_CONNECTION, status);
|
||||
|
||||
client_ipc_tests_close(handle);
|
||||
}
|
||||
|
||||
void verify_psa_framework_version()
|
||||
{
|
||||
uint32_t ff_version = psa_framework_version();
|
||||
TEST_ASSERT_EQUAL_INT(PSA_FRAMEWORK_VERSION, ff_version);
|
||||
}
|
||||
|
||||
void psa_version_existing()
|
||||
{
|
||||
uint32_t rot_version = psa_version(CLIENT_TESTS_PART1_DROP_CONN);
|
||||
TEST_ASSERT_EQUAL_INT(DROP_CONN_MINOR_VER, rot_version);
|
||||
}
|
||||
|
||||
void psa_version_non_existing()
|
||||
{
|
||||
uint32_t rot_version = psa_version(INVALID_SID);
|
||||
TEST_ASSERT_EQUAL_INT(PSA_VERSION_NONE, rot_version);
|
||||
}
|
||||
|
||||
void psa_version_secure_access_only()
|
||||
{
|
||||
uint32_t rot_version = psa_version(CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY);
|
||||
TEST_ASSERT_EQUAL_INT(PSA_VERSION_NONE, rot_version);
|
||||
}
|
||||
|
||||
|
||||
// Test cases
|
||||
Case cases[] = {
|
||||
Case("Testing client iovec_0_NULL", iovec_0_NULL),
|
||||
Case("Testing client iovec_1_NULL", iovec_1_NULL),
|
||||
Case("Testing client iovec_2_NULL", iovec_2_NULL),
|
||||
Case("Testing client in_vec 0 base not NULL size 0", in_vec_base_not_NULL_size_0),
|
||||
Case("Testing client in_len 0 in_vec not NULL", in_len_0_in_vec_not_NULL),
|
||||
Case("Testing client out_len is 0 but out_vec is not NULL", out_len_0_outvec_not_NULL),
|
||||
Case("Testing client rx_buff_null", rx_buff_null),
|
||||
Case("Testing client tx_buff_null", tx_buff_null),
|
||||
Case("Testing client rx_tx_null", rx_tx_null),
|
||||
Case("Testing client multiple_call from a single thread", multiple_call),
|
||||
Case("Testing client close on NULL handle", client_close_null_handle),
|
||||
Case("Testing DROP_CONNECTION State", drop_connection),
|
||||
Case("Testing client psa_framework_version() API", verify_psa_framework_version),
|
||||
Case("Testing client psa_version() API on existing SID", psa_version_existing),
|
||||
Case("Testing client psa_version() API on non-existing SID", psa_version_non_existing),
|
||||
Case("Testing client psa_version() API to a service that is not NSPE callable", psa_version_secure_access_only),
|
||||
Case("Testing client multiple calls on different channels to the same SID", multi_thread_diff_handles),
|
||||
};
|
||||
|
||||
utest::v1::status_t test_setup(const size_t number_of_cases)
|
||||
{
|
||||
// Setup Greentea using a reasonable timeout in seconds
|
||||
GREENTEA_SETUP(60, "default_auto");
|
||||
return verbose_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Specification specification(test_setup, cases);
|
||||
|
||||
int main()
|
||||
{
|
||||
Harness::run(specification);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // COMPONENT_PSA_SRV_IPC
|
|
@ -1,97 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
|
||||
#define MSG_BUF_SIZE 128
|
||||
uint8_t data[MSG_BUF_SIZE] = {0};
|
||||
|
||||
void client_part_main(void *ptr)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
while (1) {
|
||||
signals = psa_wait(CLIENT_TESTS_PART1_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
if (signals & PART1_ROT_SRV1_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(PART1_ROT_SRV1_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
break;
|
||||
case PSA_IPC_CALL: {
|
||||
memset(data, 0, sizeof(data));
|
||||
if (msg.in_size[0] + msg.in_size[1] + msg.in_size[2] > 1) {
|
||||
size_t offset = psa_read(msg.handle, 0, (void *)data, msg.in_size[0]);
|
||||
offset += psa_read(msg.handle, 1, (void *)(data + offset), msg.in_size[1]);
|
||||
psa_read(msg.handle, 2, (void *)(data + offset), msg.in_size[2]);
|
||||
}
|
||||
|
||||
if (msg.out_size[0] > 0) {
|
||||
uint8_t resp_size = data[0];
|
||||
uint8_t resp_offset = data[1];
|
||||
psa_write(msg.handle, 0, (const void *)(data + resp_offset), resp_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
SPM_PANIC("Invalid msg type");
|
||||
}
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
} else if (signals & DROP_CONN_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(DROP_CONN_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
break;
|
||||
case PSA_IPC_CALL:
|
||||
psa_reply(msg.handle, PSA_DROP_CONNECTION);
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Invalid msg type");
|
||||
}
|
||||
} else if (signals & SECURE_CLIENTS_ONLY_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(SECURE_CLIENTS_ONLY_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
case PSA_IPC_CALL:
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Invalid msg type");
|
||||
}
|
||||
} else {
|
||||
SPM_PANIC("Received invalid signal %lu", signals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
{
|
||||
"name": "CLIENT_TESTS_PART1",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000001",
|
||||
"entry_point": "client_part_main",
|
||||
"stack_size": "0x400",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "CLIENT_TESTS_PART1_ROT_SRV1",
|
||||
"identifier": "0x00001A05",
|
||||
"signal": "PART1_ROT_SRV1_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CLIENT_TESTS_PART1_DROP_CONN",
|
||||
"identifier": "0x00001A06",
|
||||
"signal": "DROP_CONN_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY",
|
||||
"identifier": "0x00001A07",
|
||||
"signal": "SECURE_CLIENTS_ONLY_MSK",
|
||||
"non_secure_clients": false,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "RELAXED"
|
||||
}
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/client_tests_partition.c"
|
||||
]
|
||||
}
|
|
@ -1,276 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 COMPONENT_PSA_SRV_IPC
|
||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
|
||||
#else
|
||||
|
||||
#include "mbed.h"
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "psa/client.h"
|
||||
#include "server_tests.h"
|
||||
#include "psa_manifest/sid.h"
|
||||
|
||||
#if defined(TARGET_TFM)
|
||||
#define PSA_MAX_IOVEC 4
|
||||
#endif
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
#define TEST_ROT_SRV_MINOR 12
|
||||
#define OUT_BUFFER_SIZE 60
|
||||
|
||||
psa_handle_t control_handle = 0;
|
||||
char test_str[] = "abcdefghijklmnopqrstuvwxyz";
|
||||
char cross_part_buf[] = "Hello and welcome SPM";
|
||||
|
||||
|
||||
PSA_TEST_CLIENT(identity_during_connect)
|
||||
{
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
|
||||
PSA_TEST_CLIENT(identity_during_call)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, NULL, 0, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(msg_size_assertion)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data[PSA_MAX_IOVEC] = {
|
||||
{test_str, 4},
|
||||
{test_str + 5, 6},
|
||||
{test_str + 13, 1},
|
||||
{NULL, 0}
|
||||
};
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, data, PSA_MAX_IOVEC, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(reject_connection)
|
||||
{
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT_EQUAL(PSA_CONNECTION_REFUSED, test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(read_at_outofboud_offset)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data = { test_str, sizeof(test_str) };
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, &data, 1, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(msg_read_truncation)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data[3] = {
|
||||
{test_str, 4},
|
||||
{test_str + 5, 6},
|
||||
{test_str + 13, 1}
|
||||
};
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, data, 3, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(skip_zero)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data = { test_str, sizeof(test_str) };
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, &data, 1, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(skip_some)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data = { test_str, sizeof(test_str) };
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, &data, 1, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(skip_more_than_left)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_invec data = { test_str, 8 };
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
status = psa_call(test_handle, &data, 1, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(rhandle_factorial)
|
||||
{
|
||||
uint32_t secure_value = 0;
|
||||
uint32_t value = 1;
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_outvec resp = { &secure_value, sizeof(secure_value) };
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT(test_handle > 0);
|
||||
|
||||
for (uint32_t i = 1; i <= 5; i++) {
|
||||
value *= i;
|
||||
status = psa_call(test_handle, NULL, 0, &resp, 1);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(value, secure_value);
|
||||
}
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
PSA_TEST_CLIENT(cross_partition_call)
|
||||
{
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
size_t in_len = strlen(cross_part_buf);
|
||||
TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
|
||||
|
||||
psa_invec iovec = { cross_part_buf, in_len };
|
||||
uint8_t *response_buf = (uint8_t *)malloc(sizeof(uint8_t) * OUT_BUFFER_SIZE);
|
||||
memset(response_buf, 0, OUT_BUFFER_SIZE);
|
||||
psa_outvec resp = { response_buf, OUT_BUFFER_SIZE };
|
||||
|
||||
psa_status_t status = psa_call(test_handle, &iovec, 1, &resp, 1);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL_STRING_LEN("MPS emoclew dna olleHMPS emoclew dna olleH", response_buf, in_len * 2);
|
||||
free(response_buf);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
// Test a common DOORBELL scenario
|
||||
PSA_TEST_CLIENT(doorbell_test)
|
||||
{
|
||||
psa_handle_t test_handle = psa_connect(SERVER_TESTS_PART1_TEST, TEST_ROT_SRV_MINOR);
|
||||
TEST_ASSERT_MESSAGE(test_handle > 0, "psa_connect() failed");
|
||||
|
||||
psa_status_t status = psa_call(test_handle, NULL, 0, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
|
||||
psa_close(test_handle);
|
||||
}
|
||||
|
||||
|
||||
utest::v1::status_t spm_setup(const size_t number_of_cases)
|
||||
{
|
||||
control_handle = psa_connect(SERVER_TESTS_PART1_CONTROL, 0);
|
||||
if (control_handle < 0) {
|
||||
error("Could not open a connection with SERVER_TESTS_PART1_CONTROL ROT_SRV");
|
||||
}
|
||||
|
||||
GREENTEA_SETUP(60, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
void spm_teardown(const size_t passed, const size_t failed, const failure_t failure)
|
||||
{
|
||||
psa_close(control_handle);
|
||||
greentea_test_teardown_handler(passed, failed, failure);
|
||||
}
|
||||
|
||||
utest::v1::status_t spm_case_setup(const Case *const source, const size_t index_of_case)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
test_action_t action = START_TEST;
|
||||
psa_invec data = {&action, sizeof(action)};
|
||||
|
||||
status = psa_call(control_handle, &data, 1, NULL, 0);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
return greentea_case_setup_handler(source, index_of_case);
|
||||
}
|
||||
|
||||
utest::v1::status_t spm_case_teardown(const Case *const source, const size_t passed, const size_t failed, const failure_t reason)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
test_action_t action = GET_TEST_RESULT;
|
||||
psa_invec data = {&action, sizeof(action)};
|
||||
psa_outvec resp = {&test_status, sizeof(test_status)};
|
||||
|
||||
status = psa_call(control_handle, &data, 1, &resp, 1);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_status);
|
||||
return greentea_case_teardown_handler(source, passed, failed, reason);
|
||||
}
|
||||
|
||||
#define SPM_UTEST_CASE(desc, test) Case(desc, spm_case_setup, PSA_TEST_CLIENT_NAME(test), spm_case_teardown)
|
||||
|
||||
Case cases[] = {
|
||||
SPM_UTEST_CASE("Get identity during connect", identity_during_connect),
|
||||
SPM_UTEST_CASE("Get identity during call", identity_during_call),
|
||||
SPM_UTEST_CASE("Assert msg size", msg_size_assertion),
|
||||
SPM_UTEST_CASE("Reject on connect", reject_connection),
|
||||
SPM_UTEST_CASE("Read at an out of bound offset", read_at_outofboud_offset),
|
||||
SPM_UTEST_CASE("Read msg with size bigger than message", msg_read_truncation),
|
||||
SPM_UTEST_CASE("Make sure skip with 0 byte number skips nothing", skip_zero),
|
||||
SPM_UTEST_CASE("Skip a few bytes while reading a message", skip_some),
|
||||
SPM_UTEST_CASE("Try to skip more bytes than left while reading", skip_more_than_left),
|
||||
SPM_UTEST_CASE("Test rhandle implementation by calculating the factorial function", rhandle_factorial),
|
||||
SPM_UTEST_CASE("Test a call flow between 2 secure partitions", cross_partition_call),
|
||||
};
|
||||
|
||||
//Declare your test specification with a custom setup handler
|
||||
Specification specification(spm_setup, cases, spm_teardown);
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
Harness::run(specification);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // COMPONENT_PSA_SRV_IPC
|
|
@ -1,57 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 __SERVER_TESTS_H__
|
||||
#define __SERVER_TESTS_H__
|
||||
|
||||
typedef enum {
|
||||
START_TEST = 1,
|
||||
GET_TEST_RESULT = 2
|
||||
} test_action_t;
|
||||
|
||||
typedef struct factorial_data {
|
||||
uint32_t count;
|
||||
uint32_t val;
|
||||
} factorial_data_t;
|
||||
|
||||
typedef psa_status_t (*psa_test_server_side_func)(psa_status_t *);
|
||||
#define PSA_TEST_ERROR (-1L)
|
||||
#define PSA_TEST_CLIENT_NAME(name) psa_test_client_side_ ## name
|
||||
#define PSA_TEST_SERVER_NAME(name) psa_test_server_side_ ## name
|
||||
|
||||
#define PSA_TEST_CLIENT(name) void PSA_TEST_CLIENT_NAME(name) (void)
|
||||
#define PSA_TEST_SERVER(name) psa_status_t PSA_TEST_SERVER_NAME(name) (psa_status_t *status_ptr)
|
||||
|
||||
#define PSA_TEST(name) \
|
||||
PSA_TEST_CLIENT(name); \
|
||||
PSA_TEST_SERVER(name); \
|
||||
|
||||
|
||||
PSA_TEST(identity_during_connect)
|
||||
PSA_TEST(identity_during_call)
|
||||
PSA_TEST(get_msg_twice)
|
||||
PSA_TEST(msg_size_assertion)
|
||||
PSA_TEST(reject_connection)
|
||||
PSA_TEST(read_at_outofboud_offset)
|
||||
PSA_TEST(msg_read_truncation)
|
||||
PSA_TEST(skip_zero)
|
||||
PSA_TEST(skip_some)
|
||||
PSA_TEST(skip_more_than_left)
|
||||
PSA_TEST(rhandle_factorial)
|
||||
PSA_TEST(cross_partition_call)
|
||||
PSA_TEST(doorbell_test)
|
||||
#endif /* __SERVER_TESTS_H__ */
|
|
@ -1,93 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
#include "server_tests.h"
|
||||
|
||||
extern psa_test_server_side_func test_list[];
|
||||
static size_t num_of_tests = 0;
|
||||
static void init_num_of_tests()
|
||||
{
|
||||
size_t i = 0;
|
||||
while (test_list[i] != NULL) {
|
||||
i++;
|
||||
}
|
||||
|
||||
num_of_tests = i;
|
||||
}
|
||||
|
||||
void server_part1_main(void *ptr)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
psa_status_t test_status = PSA_SUCCESS; // status of the api calls during the test
|
||||
psa_status_t test_result = PSA_SUCCESS; // result of the critical section of the test
|
||||
test_action_t action;
|
||||
uint32_t test_idx = 0;
|
||||
|
||||
|
||||
init_num_of_tests();
|
||||
while (1) {
|
||||
signals = psa_wait(CONTROL_MSK, PSA_BLOCK);
|
||||
if (0 == (signals & CONTROL_MSK)) {
|
||||
SPM_PANIC("returned from psa_wait without CONTROL_ROT_SRV bit on signals=(0x%08x)\n", signals);
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(CONTROL_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CALL:
|
||||
if (msg.in_size[0] == 0) {
|
||||
SPM_PANIC("got a zero message size to SERVER_TESTS_PART1_CONTROL ROT_SRV\n");
|
||||
}
|
||||
|
||||
if (psa_read(msg.handle, 0, &action, sizeof(action)) != sizeof(action)) {
|
||||
SPM_PANIC("could not read the entire test payload structure\n");
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case START_TEST:
|
||||
if ((test_idx >= num_of_tests) || (test_list[test_idx] == NULL)) {
|
||||
SPM_PANIC("Invalid test ID was sent!\n");
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
test_status = test_list[test_idx](&test_result);
|
||||
break;
|
||||
case GET_TEST_RESULT:
|
||||
test_idx++;
|
||||
psa_write(msg.handle, 0, &test_result, sizeof(test_result));
|
||||
psa_reply(msg.handle, test_status);
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Got illegal Value in test action");
|
||||
}
|
||||
|
||||
break;
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Unexpected message type %lu!", msg.type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "psa/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
|
||||
void server_part2_main(void *ptr)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
size_t len = 0;
|
||||
char *str = NULL;
|
||||
psa_msg_t msg = {0};
|
||||
|
||||
while (1) {
|
||||
signals = psa_wait(SERVER_TESTS_PART2_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
if (0 == (signals & SERVER_TESTS_PART2_WAIT_ANY_SID_MSK)) {
|
||||
SPM_PANIC("returned from psa_wait without ROT_SRV_REVERSE_MSK or ROT_SRV_DB_TST_MSK bit on\n");
|
||||
}
|
||||
|
||||
if (signals & ROT_SRV_REVERSE_MSK) {
|
||||
if (PSA_SUCCESS != psa_get(ROT_SRV_REVERSE_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CALL: {
|
||||
if ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) == 0) {
|
||||
SPM_PANIC("got a zero message size to REVERSE ROT_SRV\n");
|
||||
}
|
||||
|
||||
len = msg.in_size[0];
|
||||
str = (char *)malloc(sizeof(char) * len);
|
||||
if (NULL == str) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
psa_read(msg.handle, 0, str, len);
|
||||
for (size_t i = 0; i < len / 2; i ++) {
|
||||
char a = str[i];
|
||||
str[i] = str[len - i - 1];
|
||||
str[len - i - 1] = a;
|
||||
}
|
||||
|
||||
psa_write(msg.handle, 0, str, len);
|
||||
free(str);
|
||||
str = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Unexpected message type %lu!", msg.type);
|
||||
break;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
} else { // -- Doorbell test
|
||||
if (PSA_SUCCESS != psa_get(ROT_SRV_DB_TST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CALL: {
|
||||
int32_t caller_part_id = msg.client_id;
|
||||
// Doorbell contract is valid only between secure partitions
|
||||
if (caller_part_id < 0) {
|
||||
SPM_PANIC("Caller partition is non secure\n");
|
||||
}
|
||||
// In doorbell scenario the server first calls psa_reply()
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
// After work is done, ring the doorbell
|
||||
psa_notify(caller_part_id);
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT:
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Unexpected message type %lu!", msg.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,702 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
#include "server_tests.h"
|
||||
#include "psa_manifest/sid.h"
|
||||
|
||||
/**
|
||||
* Process a generic connect message to SERVER_TESTS_PART1_TEST ROT_SRV.
|
||||
* @return PSA_SUCCESS or negative error code if failed.
|
||||
*/
|
||||
static psa_status_t process_connect_request(void)
|
||||
{
|
||||
psa_status_t res = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
res = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CONNECT) {
|
||||
res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a generic disconnect message to SERVER_TESTS_PART1_TEST ROT_SRV.
|
||||
* @return PSA_SUCCESS or negative error code if failed.
|
||||
*/
|
||||
static psa_status_t process_disconnect_request(void)
|
||||
{
|
||||
psa_status_t res = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
res = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_DISCONNECT) {
|
||||
res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(identity_during_connect)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
int32_t identity = 0;
|
||||
|
||||
psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CONNECT) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
identity = msg.client_id;
|
||||
*status_ptr = (identity == -1) ? PSA_SUCCESS : PSA_TEST_ERROR;
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
|
||||
disconnect_status = process_disconnect_request();
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(identity_during_call)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
int32_t identity = 0;
|
||||
psa_signal_t signals = 0;
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
identity = msg.client_id;
|
||||
*status_ptr = (identity == -1) ? PSA_SUCCESS : PSA_TEST_ERROR;
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
|
||||
disconnect_status = process_disconnect_request();
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(msg_size_assertion)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = 0;
|
||||
size_t read_size = 0;
|
||||
|
||||
char *buff = malloc(sizeof(char) * 11);
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
memset(buff, 0, 11);
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
for (size_t i = 0; i < PSA_MAX_IOVEC; i++) {
|
||||
read_size += psa_read(msg.handle, i, buff + read_size, msg.in_size[i]);
|
||||
}
|
||||
|
||||
if (((msg.in_size[0] + msg.in_size[1] + msg.in_size[2] + msg.in_size[3]) != 11) ||
|
||||
(read_size != 11) ||
|
||||
(strncmp(buff, "abcdfghijkn", 11) != 0)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
free(buff);
|
||||
disconnect_status = process_disconnect_request();
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(reject_connection)
|
||||
{
|
||||
psa_status_t res = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
res = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CONNECT) {
|
||||
res = ((res != PSA_SUCCESS) ? res : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_CONNECTION_REFUSED);
|
||||
*status_ptr = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(read_at_outofboud_offset)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
uint32_t buff = 52;
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
size_t read_size = psa_read(msg.handle, 1, &buff, sizeof(buff));
|
||||
if ((0 != read_size) || (52 != buff)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
|
||||
PSA_TEST_SERVER(msg_read_truncation)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = 0;
|
||||
size_t read_size = 0;
|
||||
char *buff = malloc(sizeof(char) * 11);
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
memset(buff, 0, 11);
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
read_size = psa_read(msg.handle, 1, buff, 11);
|
||||
if ((msg.in_size[1] != read_size) ||
|
||||
((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) != 11) ||
|
||||
(buff[6] != 0) ||
|
||||
(strncmp(buff, "fghijk", 6) != 0)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
free(buff);
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(skip_zero)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = 0;
|
||||
size_t read_size = 0;
|
||||
size_t skip_size = 0;
|
||||
char *buff = malloc(sizeof(char) * 11);
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
skip_size = psa_skip(msg.handle, 0, 0);
|
||||
read_size = psa_read(msg.handle, 0, buff, 11);
|
||||
if ((skip_size != 0) ||
|
||||
(read_size != 11) ||
|
||||
(strncmp(buff, "abcdefghijk", 11)) != 0) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
free(buff);
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(skip_some)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = 0;
|
||||
size_t read_size1 = 0;
|
||||
size_t read_size2 = 0;
|
||||
size_t skip_size = 0;
|
||||
char *buff = malloc(sizeof(char) * 11);
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
read_size1 = psa_read(msg.handle, 0, buff, 3);
|
||||
skip_size = psa_skip(msg.handle, 0, 5);
|
||||
read_size2 = psa_read(msg.handle, 0, buff + 3, 8);
|
||||
if ((read_size1 != 3) ||
|
||||
(skip_size != 5) ||
|
||||
(read_size2 != 8) ||
|
||||
(strncmp(buff, "abcijklmnop", 11) != 0)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
free(buff);
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(skip_more_than_left)
|
||||
{
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_msg_t msg = {0};
|
||||
psa_signal_t signals = 0;
|
||||
size_t read_size1 = 0;
|
||||
size_t read_size2 = 0;
|
||||
size_t skip_size = 0;
|
||||
char *buff = malloc(sizeof(char) * 8);
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (msg.type != PSA_IPC_CALL) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
read_size1 = psa_read(msg.handle, 0, buff, 5);
|
||||
skip_size = psa_skip(msg.handle, 0, 4);
|
||||
read_size2 = psa_read(msg.handle, 0, buff + 5, 2);
|
||||
if ((read_size1 != 5) ||
|
||||
(skip_size != 3) ||
|
||||
(read_size2 != 0) ||
|
||||
(strncmp(buff, "abcde", 5) != 0)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, test_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
free(buff);
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(rhandle_factorial)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
factorial_data_t *num = NULL;
|
||||
factorial_data_t *asserted_ptr = NULL;
|
||||
uint32_t connect_count = 0;
|
||||
uint32_t call_count = 0;
|
||||
uint32_t disconnect_count = 0;
|
||||
|
||||
while (1) {
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if (0 == (signals & TEST_MSK)) {
|
||||
SPM_PANIC("returned from psa_wait without TEST_MSK bit on\n");
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
if (NULL != msg.rhandle) {
|
||||
SPM_PANIC("got rhandle on connect message\n");
|
||||
}
|
||||
|
||||
num = (factorial_data_t *)malloc(sizeof(factorial_data_t));
|
||||
if (NULL == num) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
num->count = 0;
|
||||
num->val = 1;
|
||||
psa_set_rhandle(msg.handle, num);
|
||||
asserted_ptr = num;
|
||||
connect_count++;
|
||||
break;
|
||||
case PSA_IPC_CALL:
|
||||
if (msg.in_size[0] + msg.in_size[1] + msg.in_size[2] > 0) {
|
||||
SPM_PANIC("ROT_SRV_FACTORIAL ROT_SRV should not get any params\n");
|
||||
}
|
||||
|
||||
if (NULL == msg.rhandle) {
|
||||
SPM_PANIC("got NULL rhandle on call message\n");
|
||||
}
|
||||
|
||||
if (asserted_ptr != msg.rhandle) {
|
||||
SPM_PANIC("rhandle value changed between calls\n");
|
||||
}
|
||||
|
||||
num = (factorial_data_t *)msg.rhandle;
|
||||
num->count++;
|
||||
num->val *= num->count;
|
||||
psa_write(msg.handle, 0, &(num->val), sizeof(num->val));
|
||||
call_count++;
|
||||
break;
|
||||
case PSA_IPC_DISCONNECT:
|
||||
if (NULL == msg.rhandle) {
|
||||
SPM_PANIC("got NULL rhandle on disconnect message\n");
|
||||
}
|
||||
|
||||
if (asserted_ptr != msg.rhandle) {
|
||||
SPM_PANIC("rhandle value changed between calls\n");
|
||||
}
|
||||
|
||||
// Setting rhandle during disconnection should have no effect
|
||||
uint8_t my_rhandle = 10;
|
||||
psa_set_rhandle(msg.handle, &my_rhandle);
|
||||
|
||||
free(msg.rhandle);
|
||||
disconnect_count++;
|
||||
break;
|
||||
default:
|
||||
SPM_PANIC("Unexpected message type %lu!", msg.type);
|
||||
}
|
||||
|
||||
num = NULL;
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
if (disconnect_count > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((connect_count != 1) ||
|
||||
(call_count != 5) ||
|
||||
(disconnect_count != 1)) {
|
||||
*status_ptr = PSA_TEST_ERROR;
|
||||
} else {
|
||||
*status_ptr = PSA_SUCCESS;
|
||||
}
|
||||
|
||||
return *status_ptr;
|
||||
}
|
||||
|
||||
PSA_TEST_SERVER(cross_partition_call)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_status_t partition_call_status = PSA_SUCCESS;
|
||||
uint32_t data_read = 0;
|
||||
uint32_t str_len = 0;
|
||||
char *buff = malloc(sizeof(char) * 60);
|
||||
|
||||
if (NULL == buff) {
|
||||
SPM_PANIC("memory allocation failure\n");
|
||||
}
|
||||
|
||||
memset(buff, 0, 60);
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
free(buff);
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if ((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) == 0) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
str_len = msg.in_size[0];
|
||||
data_read = psa_read(msg.handle, 0, buff, str_len);
|
||||
if (data_read != 21) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
memcpy(buff + str_len, buff, str_len);
|
||||
data_read *= 2;
|
||||
|
||||
psa_invec data = { buff, data_read };
|
||||
|
||||
psa_outvec resp = { buff, data_read };
|
||||
psa_handle_t conn_handle = psa_connect(SERVER_TESTS_PART2_ROT_SRV_REVERSE, 5);
|
||||
if (conn_handle <= 0) {
|
||||
partition_call_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (partition_call_status == PSA_SUCCESS) {
|
||||
partition_call_status = psa_call(conn_handle, &data, 1, &resp, 1);
|
||||
}
|
||||
|
||||
*status_ptr = partition_call_status;
|
||||
if (partition_call_status == PSA_SUCCESS) {
|
||||
psa_close(conn_handle);
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS == partition_call_status) {
|
||||
psa_write(msg.handle, 0, buff, data_read);
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, partition_call_status);
|
||||
free(buff);
|
||||
disconnect_status = process_disconnect_request();
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
return test_status;
|
||||
}
|
||||
|
||||
// Test a common DOORBELL scenario
|
||||
PSA_TEST_SERVER(doorbell_test)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
psa_status_t test_status = PSA_SUCCESS;
|
||||
psa_status_t disconnect_status = PSA_SUCCESS;
|
||||
psa_status_t partition_call_status = PSA_SUCCESS;
|
||||
|
||||
|
||||
test_status = process_connect_request();
|
||||
if (test_status != PSA_SUCCESS) {
|
||||
return test_status;
|
||||
}
|
||||
|
||||
signals = psa_wait(TEST_MSK, PSA_BLOCK);
|
||||
if ((signals & TEST_MSK) == 0) {
|
||||
test_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(TEST_MSK, &msg)) {
|
||||
SPM_PANIC("psa_get() failed\n");
|
||||
}
|
||||
|
||||
if (((msg.in_size[0] + msg.in_size[1] + msg.in_size[2]) != 0) || (msg.out_size[0] != 0)) {
|
||||
test_status = ((test_status != PSA_SUCCESS) ? test_status : PSA_TEST_ERROR);
|
||||
}
|
||||
|
||||
// -- Connection with partition2 - START
|
||||
psa_handle_t conn_handle = psa_connect(SERVER_TESTS_PART2_ROT_SRV_DB_TST, 5);
|
||||
if (conn_handle <= 0) {
|
||||
partition_call_status = PSA_TEST_ERROR;
|
||||
}
|
||||
|
||||
if (partition_call_status == PSA_SUCCESS) {
|
||||
partition_call_status = psa_call(conn_handle, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
if (partition_call_status == PSA_SUCCESS) {
|
||||
// Wait for doorball notification - Only after that call psa_reply() for the client called you
|
||||
signals = psa_wait(PSA_DOORBELL, PSA_BLOCK);
|
||||
if ((signals & PSA_DOORBELL) == 0) {
|
||||
partition_call_status = PSA_TEST_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (partition_call_status == PSA_SUCCESS) {
|
||||
psa_clear();
|
||||
psa_close(conn_handle);
|
||||
}
|
||||
// -- Connection with partition2 - END
|
||||
|
||||
*status_ptr = partition_call_status;
|
||||
|
||||
psa_reply(msg.handle, partition_call_status);
|
||||
disconnect_status = process_disconnect_request();
|
||||
|
||||
test_status = (test_status != PSA_SUCCESS) ? test_status : disconnect_status;
|
||||
|
||||
return test_status;
|
||||
}
|
||||
|
||||
|
||||
psa_test_server_side_func test_list[] = {
|
||||
PSA_TEST_SERVER_NAME(identity_during_connect),
|
||||
PSA_TEST_SERVER_NAME(identity_during_call),
|
||||
PSA_TEST_SERVER_NAME(msg_size_assertion),
|
||||
PSA_TEST_SERVER_NAME(reject_connection),
|
||||
PSA_TEST_SERVER_NAME(read_at_outofboud_offset),
|
||||
PSA_TEST_SERVER_NAME(msg_read_truncation),
|
||||
PSA_TEST_SERVER_NAME(skip_zero),
|
||||
PSA_TEST_SERVER_NAME(skip_some),
|
||||
PSA_TEST_SERVER_NAME(skip_more_than_left),
|
||||
PSA_TEST_SERVER_NAME(rhandle_factorial),
|
||||
PSA_TEST_SERVER_NAME(cross_partition_call),
|
||||
NULL
|
||||
};
|
|
@ -1,57 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 __UVISOR_MBED_SPM_SERVER_TESTS_H__
|
||||
#define __UVISOR_MBED_SPM_SERVER_TESTS_H__
|
||||
|
||||
typedef enum {
|
||||
START_TEST = 1,
|
||||
GET_TEST_RESULT = 2
|
||||
} test_action_t;
|
||||
|
||||
typedef struct factorial_data {
|
||||
uint32_t count;
|
||||
uint32_t val;
|
||||
} factorial_data_t;
|
||||
|
||||
typedef psa_status_t (*psa_test_server_side_func)(psa_status_t *);
|
||||
#define PSA_TEST_ERROR (-1L)
|
||||
#define PSA_TEST_CLIENT_NAME(name) psa_test_client_side_ ## name
|
||||
#define PSA_TEST_SERVER_NAME(name) psa_test_server_side_ ## name
|
||||
|
||||
#define PSA_TEST_CLIENT(name) void PSA_TEST_CLIENT_NAME(name) (void)
|
||||
#define PSA_TEST_SERVER(name) psa_status_t PSA_TEST_SERVER_NAME(name) (psa_status_t *status_ptr)
|
||||
|
||||
#define PSA_TEST(name) \
|
||||
PSA_TEST_CLIENT(name); \
|
||||
PSA_TEST_SERVER(name); \
|
||||
|
||||
|
||||
PSA_TEST(identity_during_connect)
|
||||
PSA_TEST(identity_during_call)
|
||||
PSA_TEST(get_msg_twice)
|
||||
PSA_TEST(msg_size_assertion)
|
||||
PSA_TEST(reject_connection)
|
||||
PSA_TEST(read_at_outofboud_offset)
|
||||
PSA_TEST(msg_read_truncation)
|
||||
PSA_TEST(skip_zero)
|
||||
PSA_TEST(skip_some)
|
||||
PSA_TEST(skip_more_than_left)
|
||||
PSA_TEST(rhandle_factorial)
|
||||
PSA_TEST(cross_partition_call)
|
||||
PSA_TEST(doorbell_test)
|
||||
#endif /* __UVISOR_MBED_SPM_SERVER_TESTS_H__ */
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"name": "SERVER_TESTS_PART1",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000002",
|
||||
"entry_point": "server_part1_main",
|
||||
"stack_size": "0x400",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "SERVER_TESTS_PART1_CONTROL",
|
||||
"identifier": "0x00001A01",
|
||||
"signal": "CONTROL_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "SERVER_TESTS_PART1_TEST",
|
||||
"identifier": "0x00001A02",
|
||||
"signal": "TEST_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 12,
|
||||
"minor_policy": "STRICT"
|
||||
}
|
||||
],
|
||||
"extern_sids": [
|
||||
"SERVER_TESTS_PART2_ROT_SRV_REVERSE",
|
||||
"SERVER_TESTS_PART2_ROT_SRV_DB_TST"
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/server_tests_partition1.c",
|
||||
"COMPONENT_SPE/tests.c"
|
||||
]
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"name": "SERVER_TESTS_PART2",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000003",
|
||||
"entry_point": "server_part2_main",
|
||||
"stack_size": "0x400",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "SERVER_TESTS_PART2_ROT_SRV_REVERSE",
|
||||
"identifier": "0x00001A03",
|
||||
"signal": "ROT_SRV_REVERSE_MSK",
|
||||
"non_secure_clients": false,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "SERVER_TESTS_PART2_ROT_SRV_DB_TST",
|
||||
"identifier": "0x00001A04",
|
||||
"signal": "ROT_SRV_DB_TST_MSK",
|
||||
"non_secure_clients": false,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "STRICT"
|
||||
}
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/server_tests_partition2.c",
|
||||
"COMPONENT_SPE/tests.c"
|
||||
]
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 COMPONENT_PSA_SRV_IPC
|
||||
#error [NOT_SUPPORTED] SPM tests can run only on SPM-enabled targets
|
||||
#else
|
||||
|
||||
/* -------------------------------------- Includes ----------------------------------- */
|
||||
|
||||
#include "greentea-client/test_env.h"
|
||||
#include "unity.h"
|
||||
#include "utest.h"
|
||||
#include "psa/client.h"
|
||||
#include "psa_manifest/sid.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(TARGET_TFM)
|
||||
#define PSA_MAX_IOVEC 4
|
||||
#endif
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
/* ------------------------------------ Definitions ---------------------------------- */
|
||||
|
||||
#define CLIENT_MINOR_VERSION 0
|
||||
#define CLIENT_RSP_BUF_SIZE 20
|
||||
|
||||
#define CLIENT_TX_MSG "Hello and welcome SPM"
|
||||
#define CLIENT_EXPECTED_RESPONSE "Response1"
|
||||
|
||||
/* ------------------------------------ Client Code ---------------------------------- */
|
||||
|
||||
char msg_buf[] = CLIENT_TX_MSG;
|
||||
|
||||
void example_main(void)
|
||||
{
|
||||
psa_handle_t conn_handle = psa_connect(SMOKE_TESTS_PART1_ROT_SRV1, CLIENT_MINOR_VERSION);
|
||||
TEST_ASSERT_MESSAGE(conn_handle > 0, "psa_connect() failed");
|
||||
|
||||
|
||||
psa_invec iovec[PSA_MAX_IOVEC - 1] = {
|
||||
{ msg_buf, 6 },
|
||||
{ msg_buf + 6, 12 },
|
||||
{ msg_buf + 18, 4 }
|
||||
};
|
||||
|
||||
uint8_t *response_buf = (uint8_t *)malloc(sizeof(uint8_t) * CLIENT_RSP_BUF_SIZE);
|
||||
memset(response_buf, 0, CLIENT_RSP_BUF_SIZE);
|
||||
psa_outvec outvec = {response_buf, CLIENT_RSP_BUF_SIZE};
|
||||
|
||||
psa_status_t status = psa_call(conn_handle, iovec, PSA_MAX_IOVEC - 1, &outvec, 1);
|
||||
TEST_ASSERT_MESSAGE(PSA_SUCCESS == status, "psa_call() failed");
|
||||
TEST_ASSERT_EQUAL_STRING(CLIENT_EXPECTED_RESPONSE, response_buf);
|
||||
|
||||
free(response_buf);
|
||||
psa_close(conn_handle);
|
||||
}
|
||||
|
||||
// --------------------------------- Test Framework ---------------------------------- */
|
||||
|
||||
utest::v1::status_t greentea_setup(const size_t number_of_cases)
|
||||
{
|
||||
GREENTEA_SETUP(20, "default_auto");
|
||||
return greentea_test_setup_handler(number_of_cases);
|
||||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("example", example_main)
|
||||
};
|
||||
|
||||
// Declare your test specification with a custom setup handler
|
||||
Specification specification(greentea_setup, cases);
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
// Run the test specification
|
||||
Harness::run(specification);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // COMPONENT_PSA_SRV_IPC
|
|
@ -1,122 +0,0 @@
|
|||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// -------------------------------------- Includes -----------------------------------
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "psa/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
|
||||
// ------------------------------------ Definitions ----------------------------------
|
||||
|
||||
#define SERVER_READ_MSG_BUF_SIZE 30
|
||||
#define SERVER_RSP_BUF_SIZE 20
|
||||
#define ACTUAL_MSG_SIZE 22
|
||||
|
||||
// ---------------------------------- Global Variables -------------------------------
|
||||
|
||||
const char SERVER_EXPECTED_READ_MSG[] = "Hello and welcome SPM";
|
||||
const char WRITE_MSG_BUF[] = "Response1";
|
||||
|
||||
// ------------------------------ Partition's Main Thread ----------------------------
|
||||
|
||||
void smoke_part_main(void *ptr)
|
||||
{
|
||||
uint32_t signals = 0;
|
||||
int32_t client_id = 0;
|
||||
psa_msg_t msg = {0};
|
||||
|
||||
while (1) {
|
||||
|
||||
signals = psa_wait(ROT_SRV1_MSK, PSA_BLOCK);
|
||||
if ((signals & ROT_SRV1_MSK) != ROT_SRV1_MSK) {
|
||||
SPM_PANIC("Received unknown signal (0x%08lx)\n", signals);
|
||||
}
|
||||
|
||||
if (PSA_SUCCESS != psa_get(ROT_SRV1_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg.handle != PSA_NULL_HANDLE) {
|
||||
client_id = msg.client_id;
|
||||
if (client_id != -1) {
|
||||
SPM_PANIC("Received message from unexpected source (0x%08lx)\n", client_id);
|
||||
}
|
||||
}
|
||||
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CALL: {
|
||||
if (
|
||||
((msg.in_size[0] + msg.in_size[1] + msg.in_size[2] + msg.in_size[3]) != ACTUAL_MSG_SIZE) ||
|
||||
(msg.out_size[0] != SERVER_RSP_BUF_SIZE)
|
||||
) {
|
||||
SPM_PANIC("Received message does not comply with message convention");
|
||||
}
|
||||
|
||||
|
||||
char *read_msg_buf = malloc(sizeof(char) * SERVER_READ_MSG_BUF_SIZE);
|
||||
if (NULL == read_msg_buf) {
|
||||
SPM_PANIC("Failed to allocate Memory");
|
||||
}
|
||||
memset(read_msg_buf, 0, SERVER_READ_MSG_BUF_SIZE);
|
||||
char *read_ptr = read_msg_buf;
|
||||
|
||||
for (size_t i = 0; i < PSA_MAX_IOVEC - 1; i++) {
|
||||
uint32_t bytes_read = psa_read(msg.handle, i, read_ptr, msg.in_size[i]);
|
||||
if (bytes_read != msg.in_size[i]) {
|
||||
SPM_PANIC("Expected to read %zu, got %lu", msg.in_size[i], bytes_read);
|
||||
}
|
||||
|
||||
read_ptr += bytes_read;
|
||||
}
|
||||
|
||||
int cmp_res = strcmp(SERVER_EXPECTED_READ_MSG, read_msg_buf);
|
||||
if (cmp_res != 0) {
|
||||
SPM_PANIC("psa_read() - Bad reading!!");
|
||||
}
|
||||
|
||||
psa_write(msg.handle, 0, WRITE_MSG_BUF, strlen(WRITE_MSG_BUF) + 1);
|
||||
free(read_msg_buf);
|
||||
read_msg_buf = NULL;
|
||||
read_ptr = NULL;
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_DISCONNECT:
|
||||
// Fallthrough
|
||||
case PSA_IPC_CONNECT: {
|
||||
if (
|
||||
(msg.out_size[0] != 0) || (msg.out_size[1] != 0) ||
|
||||
(msg.out_size[2] != 0) || (msg.out_size[3] != 0) ||
|
||||
(msg.in_size[0] != 0) || (msg.in_size[1] != 0) ||
|
||||
(msg.in_size[2] != 0) || (msg.in_size[3] != 0)
|
||||
) {
|
||||
SPM_PANIC("Should not receive iovecs in PSA_IPC_CONNECT or PSA_IPC_DISCONNECT");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SPM_PANIC("Unexpected message type %lu!", msg.type);
|
||||
break;
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, PSA_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"name": "SMOKE_TESTS_PART1",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000004",
|
||||
"entry_point": "smoke_part_main",
|
||||
"stack_size": "0x200",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "SMOKE_TESTS_PART1_ROT_SRV1",
|
||||
"identifier": "0x00001A00",
|
||||
"signal": "ROT_SRV1_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 5,
|
||||
"minor_policy": "RELAXED"
|
||||
}
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/smoke_tests_partition.c"
|
||||
]
|
||||
}
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_BOOT_STATUS_H__
|
||||
#define __TFM_BOOT_STATUS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Major numbers (4 bit) to identify
|
||||
* the consumer of shared data in runtime SW
|
||||
*/
|
||||
#define TLV_MAJOR_CORE 0x0
|
||||
#define TLV_MAJOR_IAS 0x1
|
||||
|
||||
/**
|
||||
* The shared data between boot loader and runtime SW is TLV encoded. The
|
||||
* shared data is stored in a well known location in secure memory and this is
|
||||
* a contract between boot loader and runtime SW.
|
||||
*
|
||||
* The structure of shared data must be the following:
|
||||
* - At the beginning there must be a header: struct shared_data_tlv_header
|
||||
* This contains a magic number and a size field which covers the entire
|
||||
* size of the shared data area including this header.
|
||||
* - After the header there come the entries which are composed from an entry
|
||||
* header structure: struct shared_data_tlv_entry and the data. In the entry
|
||||
* header is a type field (tly_type) which identify the consumer of the
|
||||
* entry in the runtime SW and specify the subtype of that data item. There
|
||||
* is a size field (tlv_len) which covers the size of the entry header and
|
||||
* the data. After this structure comes the actual data.
|
||||
* - Arbitrary number and size of data entry can be in the shared memory area.
|
||||
*
|
||||
* This table gives of overview about the tlv_type field in the entry header.
|
||||
* The tlv_type always composed from a major and minor number. Major number
|
||||
* identifies the addressee in runtime SW, who should process the data entry.
|
||||
* Minor number used to encode more info about the data entry. The actual
|
||||
* definition of minor number could change per major number. In case of boot
|
||||
* status data, which is going to be processed by initial attestation service
|
||||
* the minor number is split further to two part: sw_module and claim. The
|
||||
* sw_module identifies the SW component in the system which the data item
|
||||
* belongs to and the claim part identifies the exact type of the data.
|
||||
*
|
||||
* |---------------------------------------|
|
||||
* | tlv_type (16) |
|
||||
* |---------------------------------------|
|
||||
* | tlv_major(4)| tlv_minor(12) |
|
||||
* |---------------------------------------|
|
||||
* | MAJOR_IAS | sw_module(6) | claim(6) |
|
||||
* |---------------------------------------|
|
||||
* | MAJOR_CORE | TBD |
|
||||
* |---------------------------------------|
|
||||
*/
|
||||
|
||||
/* Initial attestation: SW components / SW modules
|
||||
* This list is intended to be adjusted per device. It contains more SW
|
||||
* components than currently available in TF-M project. It serves as an example,
|
||||
* what kind of SW components might be available.
|
||||
*/
|
||||
#define SW_GENERAL 0x00
|
||||
#define SW_BL2 0x01
|
||||
#define SW_PROT 0x02
|
||||
#define SW_AROT 0x03
|
||||
#define SW_SPE 0x04
|
||||
#define SW_NSPE 0x05
|
||||
#define SW_S_NS 0x06
|
||||
#define SW_MAX 0x07
|
||||
|
||||
/* Initial attestation: Claim per SW components / SW modules */
|
||||
/* Bits: 0-2 */
|
||||
#define SW_VERSION 0x00
|
||||
#define SW_SIGNER_ID 0x01
|
||||
#define SW_EPOCH 0x02
|
||||
#define SW_TYPE 0x03
|
||||
/* Bits: 3-5 */
|
||||
#define SW_MEASURE_VALUE 0x08
|
||||
#define SW_MEASURE_TYPE 0x09
|
||||
|
||||
/* Initial attestation: General claim does not belong any particular SW
|
||||
* component. But they might be part of the boot status.
|
||||
*/
|
||||
#define BOOT_SEED 0x00
|
||||
#define HW_VERSION 0x01
|
||||
#define SECURITY_LIFECYCLE 0x02
|
||||
|
||||
/* Minor numbers (12 bit) to identify attestation service related data */
|
||||
#define TLV_MINOR_IAS_BOOT_SEED ((SW_GENERAL << 6) | BOOT_SEED)
|
||||
#define TLV_MINOR_IAS_HW_VERSION ((SW_GENERAL << 6) | HW_VERSION)
|
||||
#define TLV_MINOR_IAS_SLC ((SW_GENERAL << 6) | SECURITY_LIFECYCLE)
|
||||
|
||||
/* Bootloader - It can be more stage */
|
||||
#define TLV_MINOR_IAS_BL2_MEASURE_VALUE ((SW_BL2 << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_BL2_MEASURE_TYPE ((SW_BL2 << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_BL2_VERSION ((SW_BL2 << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_BL2_SIGNER_ID ((SW_BL2 << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_BL2_EPOCH ((SW_BL2 << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_BL2_TYPE ((SW_BL2 << 6) | SW_TYPE)
|
||||
|
||||
/* PROT: PSA Root of Trust */
|
||||
#define TLV_MINOR_IAS_PROT_MEASURE_VALUE ((SW_PROT << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_PROT_MEASURE_TYPE ((SW_PROT << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_PROT_VERSION ((SW_PROT << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_PROT_SIGNER_ID ((SW_PROT << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_PROT_EPOCH ((SW_PROT << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_PROT_TYPE ((SW_PROT << 6) | SW_TYPE)
|
||||
|
||||
/* AROT: Application Root of Trust */
|
||||
#define TLV_MINOR_IAS_AROT_MEASURE_VALUE ((SW_AROT << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_AROT_MEASURE_TYPE ((SW_AROT << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_AROT_VERSION ((SW_AROT << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_AROT_SIGNER_ID ((SW_AROT << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_AROT_EPOCH ((SW_AROT << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_AROT_TYPE ((SW_AROT << 6) | SW_TYPE)
|
||||
|
||||
/* Non-secure processing environment - single non-secure image */
|
||||
#define TLV_MINOR_IAS_NSPE_MEASURE_VALUE ((SW_NSPE << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_NSPE_MEASURE_TYPE ((SW_NSPE << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_NSPE_VERSION ((SW_NSPE << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_NSPE_SIGNER_ID ((SW_NSPE << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_NSPE_EPOCH ((SW_NSPE << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_NSPE_TYPE ((SW_NSPE << 6) | SW_TYPE)
|
||||
|
||||
/* Secure processing environment (ARoT + PRoT) - single secure image */
|
||||
#define TLV_MINOR_IAS_SPE_MEASURE_VALUE ((SW_SPE << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_SPE_MEASURE_TYPE ((SW_SPE << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_SPE_VERSION ((SW_SPE << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_SPE_SIGNER_ID ((SW_SPE << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_SPE_EPOCH ((SW_SPE << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_SPE_TYPE ((SW_SPE << 6) | SW_TYPE)
|
||||
|
||||
/* SPE + NSPE - combined secure and non-secure image */
|
||||
#define TLV_MINOR_IAS_S_NS_MEASURE_VALUE ((SW_S_NS << 6) | SW_MEASURE_VALUE)
|
||||
#define TLV_MINOR_IAS_S_NS_MEASURE_TYPE ((SW_S_NS << 6) | SW_MEASURE_TYPE)
|
||||
#define TLV_MINOR_IAS_S_NS_VERSION ((SW_S_NS << 6) | SW_VERSION)
|
||||
#define TLV_MINOR_IAS_S_NS_SIGNER_ID ((SW_S_NS << 6) | SW_SIGNER_ID)
|
||||
#define TLV_MINOR_IAS_S_NS_EPOCH ((SW_S_NS << 6) | SW_EPOCH)
|
||||
#define TLV_MINOR_IAS_S_NS_TYPE ((SW_S_NS << 6) | SW_TYPE)
|
||||
|
||||
/* General macros to handle TLV type */
|
||||
#define MAJOR_MASK 0xF /* 4 bit */
|
||||
#define MAJOR_POS 12 /* 12 bit */
|
||||
#define MINOR_MASK 0xFFF /* 12 bit */
|
||||
|
||||
#define SET_TLV_TYPE(major, minor) \
|
||||
((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK))
|
||||
#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS)
|
||||
#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK)
|
||||
|
||||
/* Initial attestation specific macros */
|
||||
#define MODULE_POS 6 /* 6 bit */
|
||||
#define CLAIM_MASK 0x3F /* 6 bit */
|
||||
#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */
|
||||
|
||||
#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS)
|
||||
#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK)
|
||||
#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim))
|
||||
|
||||
#define GET_IAS_MEASUREMENT_CLAIM(ias_claim) ((ias_claim) >> \
|
||||
MEASUREMENT_CLAIM_POS)
|
||||
|
||||
/* Magic value which marks the beginning of shared data area in memory */
|
||||
#define SHARED_DATA_TLV_INFO_MAGIC 0x2016
|
||||
|
||||
/**
|
||||
* Shared data TLV header. All fields in little endian.
|
||||
*
|
||||
* -----------------------------------
|
||||
* | tlv_magic(16) | tlv_tot_len(16) |
|
||||
* -----------------------------------
|
||||
*/
|
||||
struct shared_data_tlv_header {
|
||||
uint16_t tlv_magic;
|
||||
uint16_t tlv_tot_len; /* size of whole TLV area (including this header) */
|
||||
};
|
||||
|
||||
#define SHARED_DATA_HEADER_SIZE sizeof(struct shared_data_tlv_header)
|
||||
|
||||
/**
|
||||
* Shared data TLV entry header format. All fields in little endian.
|
||||
*
|
||||
* -------------------------------
|
||||
* | tlv_type(16) | tlv_len(16) |
|
||||
* -------------------------------
|
||||
* | Raw data |
|
||||
* -------------------------------
|
||||
*/
|
||||
struct shared_data_tlv_entry {
|
||||
uint16_t tlv_type;
|
||||
uint16_t tlv_len; /* size of single TLV entry (including this header). */
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct tfm_boot_data
|
||||
*
|
||||
* \brief Store the data for the runtime SW
|
||||
*/
|
||||
struct tfm_boot_data {
|
||||
struct shared_data_tlv_header header;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
#define SHARED_DATA_ENTRY_HEADER_SIZE sizeof(struct shared_data_tlv_entry)
|
||||
#define SHARED_DATA_ENTRY_SIZE(size) (size + SHARED_DATA_ENTRY_HEADER_SIZE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TFM_BOOT_STATUS_H__ */
|
|
@ -1,68 +0,0 @@
|
|||
/* Copyright (c) 2017-2019 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* Template Version 1.0
|
||||
* Generated by tools/psa/generate_partition_code.py Version 1.1
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TFM_PARTITION_DEFS_INC__
|
||||
#define __TFM_PARTITION_DEFS_INC__
|
||||
|
||||
/*************************** Service Partitions *******************************/
|
||||
|
||||
#define ATTEST_SRV_ID (TFM_SP_BASE + 0)
|
||||
#define CRYPTO_SRV_ID (TFM_SP_BASE + 1)
|
||||
#define PLATFORM_ID (TFM_SP_BASE + 2)
|
||||
#define ITS_ID (TFM_SP_BASE + 3)
|
||||
|
||||
/*************************** Test Partitions **********************************/
|
||||
|
||||
#ifdef USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#ifdef USE_CRYPTO_ACL_TEST
|
||||
#define CRYPTO_ACL_TEST_ID (TFM_SP_BASE + 4 + 0)
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLIENT_TESTS_PART1
|
||||
#define CLIENT_TESTS_PART1_ID (TFM_SP_BASE + 4 + 1)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART1
|
||||
#define SERVER_TESTS_PART1_ID (TFM_SP_BASE + 4 + 2)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART2
|
||||
#define SERVER_TESTS_PART2_ID (TFM_SP_BASE + 4 + 3)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SMOKE_TESTS_PART1
|
||||
#define SMOKE_TESTS_PART1_ID (TFM_SP_BASE + 4 + 4)
|
||||
#endif
|
||||
|
||||
#endif // USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#ifdef USE_PSA_TEST_PARTITIONS
|
||||
#define TFM_MAX_USER_PARTITIONS (4 + 5)
|
||||
#else
|
||||
#define TFM_MAX_USER_PARTITIONS (4)
|
||||
#endif
|
||||
|
||||
#endif // __TFM_PARTITION_DEFS_INC__
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* Template Version 1.0
|
||||
* Generated by tools/psa/generate_partition_code.py Version 1.1
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TFM_PARTITION_LIST_INC__
|
||||
#define __TFM_PARTITION_LIST_INC__
|
||||
|
||||
/*************************** Service Partitions *******************************/
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ATTEST_SRV
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(ATTEST_SRV, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 37, NORMAL, 8192);
|
||||
PARTITION_ADD_INIT_FUNC(ATTEST_SRV, attest_main);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_SRV
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(CRYPTO_SRV, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 35, NORMAL, 16384);
|
||||
PARTITION_ADD_INIT_FUNC(CRYPTO_SRV, crypto_main);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* PLATFORM
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(PLATFORM, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 8, NORMAL, 1024);
|
||||
PARTITION_ADD_INIT_FUNC(PLATFORM, platform_partition_entry);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ITS
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(ITS, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 10, NORMAL, 2048);
|
||||
PARTITION_ADD_INIT_FUNC(ITS, its_entry);
|
||||
|
||||
/*************************** Test Partitions **********************************/
|
||||
#ifdef USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#ifdef USE_CRYPTO_ACL_TEST
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_ACL_TEST
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(CRYPTO_ACL_TEST, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 128, NORMAL, 512);
|
||||
PARTITION_ADD_INIT_FUNC(CRYPTO_ACL_TEST, test_partition_main);
|
||||
#endif // USE_CRYPTO_ACL_TEST
|
||||
|
||||
#ifdef USE_CLIENT_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CLIENT_TESTS_PART1
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(CLIENT_TESTS_PART1, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 1, NORMAL, 1024);
|
||||
PARTITION_ADD_INIT_FUNC(CLIENT_TESTS_PART1, client_part_main);
|
||||
#endif // USE_CLIENT_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART1
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(SERVER_TESTS_PART1, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 2, NORMAL, 1024);
|
||||
PARTITION_ADD_INIT_FUNC(SERVER_TESTS_PART1, server_part1_main);
|
||||
#endif // USE_SERVER_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART2
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART2
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(SERVER_TESTS_PART2, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 3, NORMAL, 1024);
|
||||
PARTITION_ADD_INIT_FUNC(SERVER_TESTS_PART2, server_part2_main);
|
||||
#endif // USE_SERVER_TESTS_PART2
|
||||
|
||||
#ifdef USE_SMOKE_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SMOKE_TESTS_PART1
|
||||
* -------------------------------------------------------------------------- */
|
||||
PARTITION_DECLARE(SMOKE_TESTS_PART1, 0
|
||||
| SPM_PART_FLAG_IPC
|
||||
, "APPLICATION-ROT", 4, NORMAL, 512);
|
||||
PARTITION_ADD_INIT_FUNC(SMOKE_TESTS_PART1, smoke_part_main);
|
||||
#endif // USE_SMOKE_TESTS_PART1
|
||||
|
||||
#endif // USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#endif // __TFM_PARTITION_LIST_INC__
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* Template Version 1.0
|
||||
* Generated by tools/psa/generate_partition_code.py Version 1.1
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TFM_SERVICE_LIST_INC__
|
||||
#define __TFM_SERVICE_LIST_INC__
|
||||
|
||||
/*************************** Service Partitions *******************************/
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ATTEST_SRV Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"PSA_ATTEST_GET_TOKEN_ID", ATTEST_SRV_ID, PSA_ATTEST_GET_TOKEN, 0x00000F10, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_ATTEST_GET_TOKEN_SIZE_ID", ATTEST_SRV_ID, PSA_ATTEST_GET_TOKEN_SIZE, 0x00000F11, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_ATTEST_INJECT_KEY_ID", ATTEST_SRV_ID, PSA_ATTEST_INJECT_KEY, 0x00000F12, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_SRV Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"PSA_CRYPTO_INIT_ID", CRYPTO_SRV_ID, PSA_CRYPTO_INIT, 0x00000F00, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_MAC_ID", CRYPTO_SRV_ID, PSA_MAC, 0x00000F01, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_HASH_ID", CRYPTO_SRV_ID, PSA_HASH, 0x00000F02, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_ASYMMETRIC_ID", CRYPTO_SRV_ID, PSA_ASYMMETRIC, 0x00000F03, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_SYMMETRIC_ID", CRYPTO_SRV_ID, PSA_SYMMETRIC, 0x00000F04, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_AEAD_ID", CRYPTO_SRV_ID, PSA_AEAD, 0x00000F05, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_KEY_MNG_ID", CRYPTO_SRV_ID, PSA_KEY_MNG, 0x00000F06, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_RNG_ID", CRYPTO_SRV_ID, PSA_RNG, 0x00000F07, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_CRYPTO_FREE_ID", CRYPTO_SRV_ID, PSA_CRYPTO_FREE, 0x00000F08, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_KEY_DERIVATION_ID", CRYPTO_SRV_ID, PSA_KEY_DERIVATION, 0x00000F09, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
{"PSA_ENTROPY_ID", CRYPTO_SRV_ID, PSA_ENTROPY_INJECT, 0x00000F0A, true, 1, TFM_VERSION_POLICY_STRICT},
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* PLATFORM Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"PSA_PLATFORM_LC_GET", PLATFORM_ID, PSA_PLATFORM_LC_GET_MSK, 0x00011000, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_PLATFORM_LC_SET", PLATFORM_ID, PSA_PLATFORM_LC_SET_MSK, 0x00011001, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_PLATFORM_SYSTEM_RESET", PLATFORM_ID, PSA_PLATFORM_SYSTEM_RESET_MSK, 0x00011002, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_PLATFORM_IOCTL", PLATFORM_ID, PSA_PLATFORM_IOCTL_MSK, 0x00011003, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ITS Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"PSA_ITS_GET", ITS_ID, PSA_ITS_GET_MSK, 0x00011A00, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_ITS_SET", ITS_ID, PSA_ITS_SET_MSK, 0x00011A01, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_ITS_INFO", ITS_ID, PSA_ITS_INFO_MSK, 0x00011A02, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_ITS_REMOVE", ITS_ID, PSA_ITS_REMOVE_MSK, 0x00011A03, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"PSA_ITS_RESET", ITS_ID, PSA_ITS_RESET_MSK, 0x00011A04, false, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
|
||||
/*************************** Test Partitions **********************************/
|
||||
#ifdef USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#ifdef USE_CRYPTO_ACL_TEST
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_ACL_TEST Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"CRYPTO_GENERATE_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_GENERATE_KEY_MSK, 0x00000201, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CRYPTO_OPEN_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_OPEN_KEY_MSK, 0x00000202, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CRYPTO_CLOSE_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_CLOSE_KEY_MSK, 0x00000203, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CRYPTO_DESTROY_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_DESTROY_KEY_MSK, 0x00000205, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CRYPTO_GET_KEY_ATTRIBUTES", CRYPTO_ACL_TEST_ID, CRYPTO_GET_KEY_ATTRIBUTES_MSK, 0x00000206, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CRYPTO_IMPORT_KEY", CRYPTO_ACL_TEST_ID, CRYPTO_IMPORT_KEY_MSK, 0x00000208, true, 1, TFM_VERSION_POLICY_RELAXED},
|
||||
#endif // USE_CRYPTO_ACL_TEST
|
||||
|
||||
#ifdef USE_CLIENT_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CLIENT_TESTS_PART1 Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"CLIENT_TESTS_PART1_ROT_SRV1", CLIENT_TESTS_PART1_ID, PART1_ROT_SRV1_MSK, 0x00001A05, true, 5, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CLIENT_TESTS_PART1_DROP_CONN", CLIENT_TESTS_PART1_ID, DROP_CONN_MSK, 0x00001A06, true, 5, TFM_VERSION_POLICY_RELAXED},
|
||||
{"CLIENT_TESTS_PART1_SECURE_CLIENTS_ONLY", CLIENT_TESTS_PART1_ID, SECURE_CLIENTS_ONLY_MSK, 0x00001A07, false, 5, TFM_VERSION_POLICY_RELAXED},
|
||||
#endif // USE_CLIENT_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART1 Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"SERVER_TESTS_PART1_CONTROL", SERVER_TESTS_PART1_ID, CONTROL_MSK, 0x00001A01, true, 5, TFM_VERSION_POLICY_RELAXED},
|
||||
{"SERVER_TESTS_PART1_TEST", SERVER_TESTS_PART1_ID, TEST_MSK, 0x00001A02, true, 12, TFM_VERSION_POLICY_STRICT},
|
||||
#endif // USE_SERVER_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART2
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART2 Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"SERVER_TESTS_PART2_ROT_SRV_REVERSE", SERVER_TESTS_PART2_ID, ROT_SRV_REVERSE_MSK, 0x00001A03, false, 5, TFM_VERSION_POLICY_STRICT},
|
||||
{"SERVER_TESTS_PART2_ROT_SRV_DB_TST", SERVER_TESTS_PART2_ID, ROT_SRV_DB_TST_MSK, 0x00001A04, false, 5, TFM_VERSION_POLICY_STRICT},
|
||||
#endif // USE_SERVER_TESTS_PART2
|
||||
|
||||
#ifdef USE_SMOKE_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SMOKE_TESTS_PART1 Services
|
||||
* -------------------------------------------------------------------------- */
|
||||
{"SMOKE_TESTS_PART1_ROT_SRV1", SMOKE_TESTS_PART1_ID, ROT_SRV1_MSK, 0x00001A00, true, 5, TFM_VERSION_POLICY_RELAXED},
|
||||
#endif // USE_SMOKE_TESTS_PART1
|
||||
|
||||
#endif // USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#endif // __TFM_SERVICE_LIST_INC__
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* Template Version 1.0
|
||||
* Generated by tools/psa/generate_partition_code.py Version 1.1
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __TFM_SPM_SIGNAL_DEFS_H__
|
||||
#define __TFM_SPM_SIGNAL_DEFS_H__
|
||||
|
||||
/*************************** Service Partitions *******************************/
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ATTEST_SRV Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define PSA_ATTEST_GET_TOKEN_POS (4UL)
|
||||
#define PSA_ATTEST_GET_TOKEN (1UL << PSA_ATTEST_GET_TOKEN_POS)
|
||||
#define PSA_ATTEST_GET_TOKEN_SIZE_POS (5UL)
|
||||
#define PSA_ATTEST_GET_TOKEN_SIZE (1UL << PSA_ATTEST_GET_TOKEN_SIZE_POS)
|
||||
#define PSA_ATTEST_INJECT_KEY_POS (6UL)
|
||||
#define PSA_ATTEST_INJECT_KEY (1UL << PSA_ATTEST_INJECT_KEY_POS)
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_SRV Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define PSA_CRYPTO_INIT_POS (4UL)
|
||||
#define PSA_CRYPTO_INIT (1UL << PSA_CRYPTO_INIT_POS)
|
||||
#define PSA_MAC_POS (5UL)
|
||||
#define PSA_MAC (1UL << PSA_MAC_POS)
|
||||
#define PSA_HASH_POS (6UL)
|
||||
#define PSA_HASH (1UL << PSA_HASH_POS)
|
||||
#define PSA_ASYMMETRIC_POS (7UL)
|
||||
#define PSA_ASYMMETRIC (1UL << PSA_ASYMMETRIC_POS)
|
||||
#define PSA_SYMMETRIC_POS (8UL)
|
||||
#define PSA_SYMMETRIC (1UL << PSA_SYMMETRIC_POS)
|
||||
#define PSA_AEAD_POS (9UL)
|
||||
#define PSA_AEAD (1UL << PSA_AEAD_POS)
|
||||
#define PSA_KEY_MNG_POS (10UL)
|
||||
#define PSA_KEY_MNG (1UL << PSA_KEY_MNG_POS)
|
||||
#define PSA_RNG_POS (11UL)
|
||||
#define PSA_RNG (1UL << PSA_RNG_POS)
|
||||
#define PSA_CRYPTO_FREE_POS (12UL)
|
||||
#define PSA_CRYPTO_FREE (1UL << PSA_CRYPTO_FREE_POS)
|
||||
#define PSA_KEY_DERIVATION_POS (13UL)
|
||||
#define PSA_KEY_DERIVATION (1UL << PSA_KEY_DERIVATION_POS)
|
||||
#define PSA_ENTROPY_INJECT_POS (14UL)
|
||||
#define PSA_ENTROPY_INJECT (1UL << PSA_ENTROPY_INJECT_POS)
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* PLATFORM Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define PSA_PLATFORM_LC_GET_MSK_POS (4UL)
|
||||
#define PSA_PLATFORM_LC_GET_MSK (1UL << PSA_PLATFORM_LC_GET_MSK_POS)
|
||||
#define PSA_PLATFORM_LC_SET_MSK_POS (5UL)
|
||||
#define PSA_PLATFORM_LC_SET_MSK (1UL << PSA_PLATFORM_LC_SET_MSK_POS)
|
||||
#define PSA_PLATFORM_SYSTEM_RESET_MSK_POS (6UL)
|
||||
#define PSA_PLATFORM_SYSTEM_RESET_MSK (1UL << PSA_PLATFORM_SYSTEM_RESET_MSK_POS)
|
||||
#define PSA_PLATFORM_IOCTL_MSK_POS (7UL)
|
||||
#define PSA_PLATFORM_IOCTL_MSK (1UL << PSA_PLATFORM_IOCTL_MSK_POS)
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* ITS Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define PSA_ITS_GET_MSK_POS (4UL)
|
||||
#define PSA_ITS_GET_MSK (1UL << PSA_ITS_GET_MSK_POS)
|
||||
#define PSA_ITS_SET_MSK_POS (5UL)
|
||||
#define PSA_ITS_SET_MSK (1UL << PSA_ITS_SET_MSK_POS)
|
||||
#define PSA_ITS_INFO_MSK_POS (6UL)
|
||||
#define PSA_ITS_INFO_MSK (1UL << PSA_ITS_INFO_MSK_POS)
|
||||
#define PSA_ITS_REMOVE_MSK_POS (7UL)
|
||||
#define PSA_ITS_REMOVE_MSK (1UL << PSA_ITS_REMOVE_MSK_POS)
|
||||
#define PSA_ITS_RESET_MSK_POS (8UL)
|
||||
#define PSA_ITS_RESET_MSK (1UL << PSA_ITS_RESET_MSK_POS)
|
||||
|
||||
/*************************** Test Partitions **********************************/
|
||||
#ifdef USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#ifdef USE_CRYPTO_ACL_TEST
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRYPTO_ACL_TEST Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define CRYPTO_GENERATE_KEY_MSK_POS (4UL)
|
||||
#define CRYPTO_GENERATE_KEY_MSK (1UL << CRYPTO_GENERATE_KEY_MSK_POS)
|
||||
#define CRYPTO_OPEN_KEY_MSK_POS (5UL)
|
||||
#define CRYPTO_OPEN_KEY_MSK (1UL << CRYPTO_OPEN_KEY_MSK_POS)
|
||||
#define CRYPTO_CLOSE_KEY_MSK_POS (6UL)
|
||||
#define CRYPTO_CLOSE_KEY_MSK (1UL << CRYPTO_CLOSE_KEY_MSK_POS)
|
||||
#define CRYPTO_DESTROY_KEY_MSK_POS (7UL)
|
||||
#define CRYPTO_DESTROY_KEY_MSK (1UL << CRYPTO_DESTROY_KEY_MSK_POS)
|
||||
#define CRYPTO_GET_KEY_ATTRIBUTES_MSK_POS (8UL)
|
||||
#define CRYPTO_GET_KEY_ATTRIBUTES_MSK (1UL << CRYPTO_GET_KEY_ATTRIBUTES_MSK_POS)
|
||||
#define CRYPTO_IMPORT_KEY_MSK_POS (9UL)
|
||||
#define CRYPTO_IMPORT_KEY_MSK (1UL << CRYPTO_IMPORT_KEY_MSK_POS)
|
||||
#endif // USE_CRYPTO_ACL_TEST
|
||||
|
||||
#ifdef USE_CLIENT_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CLIENT_TESTS_PART1 Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define PART1_ROT_SRV1_MSK_POS (4UL)
|
||||
#define PART1_ROT_SRV1_MSK (1UL << PART1_ROT_SRV1_MSK_POS)
|
||||
#define DROP_CONN_MSK_POS (5UL)
|
||||
#define DROP_CONN_MSK (1UL << DROP_CONN_MSK_POS)
|
||||
#define SECURE_CLIENTS_ONLY_MSK_POS (6UL)
|
||||
#define SECURE_CLIENTS_ONLY_MSK (1UL << SECURE_CLIENTS_ONLY_MSK_POS)
|
||||
#endif // USE_CLIENT_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART1 Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define CONTROL_MSK_POS (4UL)
|
||||
#define CONTROL_MSK (1UL << CONTROL_MSK_POS)
|
||||
#define TEST_MSK_POS (5UL)
|
||||
#define TEST_MSK (1UL << TEST_MSK_POS)
|
||||
#endif // USE_SERVER_TESTS_PART1
|
||||
|
||||
#ifdef USE_SERVER_TESTS_PART2
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SERVER_TESTS_PART2 Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define ROT_SRV_REVERSE_MSK_POS (4UL)
|
||||
#define ROT_SRV_REVERSE_MSK (1UL << ROT_SRV_REVERSE_MSK_POS)
|
||||
#define ROT_SRV_DB_TST_MSK_POS (5UL)
|
||||
#define ROT_SRV_DB_TST_MSK (1UL << ROT_SRV_DB_TST_MSK_POS)
|
||||
#endif // USE_SERVER_TESTS_PART2
|
||||
|
||||
#ifdef USE_SMOKE_TESTS_PART1
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SMOKE_TESTS_PART1 Signals
|
||||
* -------------------------------------------------------------------------- */
|
||||
#define ROT_SRV1_MSK_POS (4UL)
|
||||
#define ROT_SRV1_MSK (1UL << ROT_SRV1_MSK_POS)
|
||||
#endif // USE_SMOKE_TESTS_PART1
|
||||
|
||||
#endif // USE_PSA_TEST_PARTITIONS
|
||||
|
||||
#endif // __TFM_SPM_SIGNAL_DEFS_H__
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"name": "tfm-s",
|
||||
"macros": ["MBED_FAULT_HANDLER_DISABLED"],
|
||||
"config": {
|
||||
"max_ns_thread_count": {
|
||||
"help": "maximum allowed number of non-secure threads",
|
||||
"macro_name": "TFM_MAX_NS_THREAD_COUNT",
|
||||
"value": 10
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_SPM_HAL_H__
|
||||
#define __TFM_SPM_HAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "tfm_secure_api.h"
|
||||
#include "spm_api.h"
|
||||
|
||||
/**
|
||||
* \brief Holds peripheral specific data fields required to manage the
|
||||
* peripherals isolation
|
||||
*
|
||||
* This structure has to be defined in the platform directory, and may have
|
||||
* different definition for each platform. The structure should contain fields
|
||||
* that describe the peripheral for the functions that are prototyped in this
|
||||
* file and are responsible for configuring the isolation of the peripherals.
|
||||
*
|
||||
* Pointers to structures of this type are managed by the SPM, and passed to the
|
||||
* necessary function on isolation request. The pointers are also defined by the
|
||||
* platform in the header file tfm_peripherals_def.h. For details on this, see
|
||||
* the documentation of that file.
|
||||
*/
|
||||
struct tfm_spm_partition_platform_data_t;
|
||||
|
||||
#if defined (TFM_PSA_API) || (TFM_LVL != 1)
|
||||
/**
|
||||
* \brief Holds SPM db fields that define the memory regions used by a
|
||||
* partition.
|
||||
*/
|
||||
struct tfm_spm_partition_memory_data_t
|
||||
{
|
||||
uint32_t code_start; /*!< Start of the code memory of this partition. */
|
||||
uint32_t code_limit; /*!< Address of the byte beyond the end of the code
|
||||
* memory of this partition.
|
||||
*/
|
||||
uint32_t ro_start; /*!< Start of the read only memory of this
|
||||
* partition.
|
||||
*/
|
||||
uint32_t ro_limit; /*!< Address of the byte beyond the end of the read
|
||||
* only memory of this partition.
|
||||
*/
|
||||
uint32_t rw_start; /*!< Start of the data region of this partition. */
|
||||
uint32_t rw_limit; /*!< Address of the byte beyond the end of the data
|
||||
* region of this partition.
|
||||
*/
|
||||
uint32_t zi_start; /*!< Start of the zero initialised data region of
|
||||
* this partition.
|
||||
*/
|
||||
uint32_t zi_limit; /*!< Address of the byte beyond the end of the zero
|
||||
* initialised region of this partition.
|
||||
*/
|
||||
uint32_t stack_bottom; /*!< The bottom of the stack for the partition. */
|
||||
uint32_t stack_top; /*!< The top of the stack for the partition. */
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief This function initialises the HW used for isolation, and sets the
|
||||
* default configuration for them.
|
||||
*
|
||||
* This function is called during TF-M core early startup, before DB init
|
||||
*/
|
||||
void tfm_spm_hal_init_isolation_hw(void);
|
||||
|
||||
/**
|
||||
* \brief This function initialises the HW used for isolation, and sets the
|
||||
* default configuration for them.
|
||||
* This function is called during TF-M core early startup, after DB init
|
||||
*/
|
||||
void tfm_spm_hal_setup_isolation_hw(void);
|
||||
|
||||
/**
|
||||
* \brief Configure peripherals for a partition based on the platfotm data from
|
||||
* the DB
|
||||
*
|
||||
* This function is called during partition initialisation (before calling the
|
||||
* init function for the partition)
|
||||
*
|
||||
* \param[in] platform_data The platform fields of the partition DB record to
|
||||
* be used for configuration. Can be NULL.
|
||||
*/
|
||||
void tfm_spm_hal_configure_default_isolation(
|
||||
const struct tfm_spm_partition_platform_data_t *platform_data);
|
||||
/**
|
||||
* \brief Configures the system debug properties.
|
||||
* The default configuration of this function should disable secure debug
|
||||
* when either DAUTH_NONE or DAUTH_NS_ONLY define is set. It is up to the
|
||||
* platform owner to decide if secure debug can be turned on in their
|
||||
* system, if DAUTH_FULL define is present.
|
||||
* The DAUTH_CHIP_DEFAULT define should not be considered a safe default
|
||||
* option unless explicitly noted by the chip vendor.
|
||||
* The implementation has to expect that one of those defines is going to
|
||||
* be set. Otherwise, a compile error needs to be triggered.
|
||||
*/
|
||||
void tfm_spm_hal_init_debug(void);
|
||||
|
||||
/**
|
||||
* \brief Enables the fault handlers
|
||||
*/
|
||||
void enable_fault_handlers(void);
|
||||
|
||||
/**
|
||||
* \brief Configures the system reset request properties
|
||||
*/
|
||||
void system_reset_cfg(void);
|
||||
|
||||
/**
|
||||
* \brief Configures all external interrupts to target the
|
||||
* NS state, apart for the ones associated to secure
|
||||
* peripherals (plus MPC and PPC)
|
||||
*/
|
||||
void nvic_interrupt_target_state_cfg(void);
|
||||
|
||||
/**
|
||||
* \brief This function enable the interrupts associated
|
||||
* to the secure peripherals (plus the isolation boundary violation
|
||||
* interrupts)
|
||||
*/
|
||||
void nvic_interrupt_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Get the VTOR value of non-secure image
|
||||
*
|
||||
* \return Returns the address where the vector table of the non-secure image
|
||||
* is located
|
||||
*/
|
||||
uint32_t tfm_spm_hal_get_ns_VTOR(void);
|
||||
|
||||
/**
|
||||
* \brief Get the initial address of non-secure image main stack
|
||||
*
|
||||
* \return Returns the initial non-secure MSP
|
||||
*/
|
||||
uint32_t tfm_spm_hal_get_ns_MSP(void);
|
||||
|
||||
/**
|
||||
* \brief Get the entry point of the non-secure image
|
||||
*
|
||||
* \return Returns the address of the non-secure image entry point
|
||||
*/
|
||||
uint32_t tfm_spm_hal_get_ns_entry_point(void);
|
||||
|
||||
|
||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
|
||||
/**
|
||||
* \brief Configure the sandbox for a partition.
|
||||
*
|
||||
* \param[in] memory_data The memory ranges from the partition DB for this
|
||||
* partition
|
||||
* \param[in] platform_data The platform fields of the partition DB record
|
||||
* for this partition. Can be NULL.
|
||||
*
|
||||
* \return Returns the result operation as per \ref spm_err_t
|
||||
*/
|
||||
enum spm_err_t tfm_spm_hal_partition_sandbox_config(
|
||||
const struct tfm_spm_partition_memory_data_t *memory_data,
|
||||
const struct tfm_spm_partition_platform_data_t *platform_data);
|
||||
|
||||
/**
|
||||
* \brief Deconfigure the sandbox for a partition.
|
||||
*
|
||||
* \param[in] memory_data The memory ranges from the partition DB for this
|
||||
* partition
|
||||
* \param[in] platform_data The platform fields of the partition DB record
|
||||
* for this partition. Can be NULL.
|
||||
*
|
||||
* \return Returns the result operation as per \ref spm_err_t
|
||||
*/
|
||||
enum spm_err_t tfm_spm_hal_partition_sandbox_deconfig(
|
||||
const struct tfm_spm_partition_memory_data_t *memory_data,
|
||||
const struct tfm_spm_partition_platform_data_t *platform_data);
|
||||
|
||||
/**
|
||||
* \brief Set the share region mode
|
||||
*
|
||||
* \param[in] share The mode to set
|
||||
*
|
||||
* \return Returns the result operation as per \ref spm_err_t
|
||||
*/
|
||||
enum spm_err_t tfm_spm_hal_set_share_region(
|
||||
enum tfm_buffer_share_region_e share);
|
||||
#endif
|
||||
|
||||
#endif /* __TFM_SPM_HAL_H__ */
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
//This file holds description for the current directory. This documentation
|
||||
//will be included in the Doxygen output.
|
||||
|
||||
/*!
|
||||
\dir
|
||||
\brief Source code for the TF-M core.
|
||||
\details This directory holds the source code of the "TF-M core" module.
|
||||
|
||||
*/
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_ARCH_V8M_H__
|
||||
#define __TFM_ARCH_V8M_H__
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
#define XPSR_T32 0x01000000
|
||||
#define LR_UNPRIVILEGED 0xfffffffd
|
||||
|
||||
/* This header file collects the ARCH related operations. */
|
||||
struct tfm_state_context_base {
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t ra_lr;
|
||||
uint32_t ra;
|
||||
uint32_t xpsr;
|
||||
};
|
||||
|
||||
struct tfm_state_context_ext {
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t sp;
|
||||
uint32_t sp_limit;
|
||||
uint32_t dummy;
|
||||
uint32_t lr;
|
||||
};
|
||||
|
||||
struct tfm_state_context {
|
||||
struct tfm_state_context_ext ctxb;
|
||||
};
|
||||
|
||||
#define TFM_STATE_1ST_ARG(ctx) \
|
||||
(((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
|
||||
#define TFM_STATE_2ND_ARG(ctx) \
|
||||
(((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r1)
|
||||
#define TFM_STATE_3RD_ARG(ctx) \
|
||||
(((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r2)
|
||||
#define TFM_STATE_4TH_ARG(ctx) \
|
||||
(((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r3)
|
||||
#define TFM_STATE_RET_VAL(ctx) \
|
||||
(((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
|
||||
|
||||
__STATIC_INLINE void tfm_trigger_pendsv(void)
|
||||
{
|
||||
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
|
||||
}
|
||||
|
||||
void tfm_initialize_context(struct tfm_state_context *ctx,
|
||||
uint32_t r0, uint32_t ra,
|
||||
uint32_t sp, uint32_t sp_limit);
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_INTERNAL_DEFINES_H__
|
||||
#define __TFM_INTERNAL_DEFINES_H__
|
||||
|
||||
/* IPC internal return status */
|
||||
#define IPC_SUCCESS 0
|
||||
#define IPC_ERROR_BAD_PARAMETERS (INT32_MIN)
|
||||
#define IPC_ERROR_SHORT_BUFFER (INT32_MIN + 1)
|
||||
#define IPC_ERROR_VERSION (INT32_MIN + 2)
|
||||
#define IPC_ERROR_MEMORY_CHECK (INT32_MIN + 3)
|
||||
#define IPC_ERROR_GENERIC (INT32_MIN + 0x1F)
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_LIST_H__
|
||||
#define __TFM_LIST_H__
|
||||
|
||||
/* List structure */
|
||||
struct tfm_list_node_t {
|
||||
struct tfm_list_node_t *prev;
|
||||
struct tfm_list_node_t *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initialize list head.
|
||||
*
|
||||
* \param[in] head List head need to be initialized.
|
||||
*/
|
||||
__STATIC_INLINE void tfm_list_init(struct tfm_list_node_t *head)
|
||||
{
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add one node to list tail.
|
||||
*
|
||||
* \param[in] head List head initialized by \ref tfm_list_init.
|
||||
* \param[in] node List node want to be added.
|
||||
*/
|
||||
__STATIC_INLINE void
|
||||
tfm_list_add_tail(struct tfm_list_node_t *head, struct tfm_list_node_t *node)
|
||||
{
|
||||
head->prev->next = node;
|
||||
node->prev = head->prev;
|
||||
head->prev = node;
|
||||
node->next = head;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if a list is empty.
|
||||
*
|
||||
* \param[in] head List head initialized by \ref tfm_list_init.
|
||||
*
|
||||
* \returns returns 1 for empty, or 0 for not.
|
||||
*/
|
||||
__STATIC_INLINE int32_t tfm_list_is_empty(struct tfm_list_node_t *head)
|
||||
{
|
||||
return (head->next == head);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Insert one node to list head.
|
||||
*
|
||||
* \param[in] head List head initialized by \ref tfm_list_init.
|
||||
* \param[in] node List node want to be inserted.
|
||||
*/
|
||||
__STATIC_INLINE void
|
||||
tfm_list_insert_first(struct tfm_list_node_t *head,
|
||||
struct tfm_list_node_t *node)
|
||||
{
|
||||
node->next = head->next;
|
||||
node->prev = head;
|
||||
head->next->prev = node;
|
||||
head->next = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieve the fist node from list.
|
||||
*
|
||||
* \param[in] head List head initialized by \ref tfm_list_init.
|
||||
*
|
||||
* \returns Returns the pointer to first list node.
|
||||
*/
|
||||
__STATIC_INLINE
|
||||
struct tfm_list_node_t *tfm_list_first_node(struct tfm_list_node_t *head)
|
||||
{
|
||||
return head->next;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Delete one node from list.
|
||||
*
|
||||
* \param[in] node List node want to be deleted.
|
||||
*/
|
||||
__STATIC_INLINE void tfm_list_del_node(struct tfm_list_node_t *node)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
|
||||
/* Go through each node of a list */
|
||||
#define TFM_LIST_FOR_EACH(node, head) \
|
||||
for (node = (head)->next; node != head; node = node->next)
|
||||
|
||||
#endif
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_MESSAGE_QUEUE_H__
|
||||
#define __TFM_MESSAGE_QUEUE_H__
|
||||
|
||||
#ifndef TFM_MSG_QUEUE_MAX_MSG_NUM
|
||||
#define TFM_MSG_QUEUE_MAX_MSG_NUM 128
|
||||
#endif
|
||||
#define TFM_MSG_MAGIC 0x15154343
|
||||
/* Message struct to collect parameter from client */
|
||||
struct tfm_msg_body_t {
|
||||
int32_t magic;
|
||||
struct tfm_spm_service_t *service; /* RoT service pointer */
|
||||
psa_handle_t handle; /* Connected Service handle */
|
||||
struct tfm_event_t ack_evnt; /* Event for ack reponse */
|
||||
psa_msg_t msg; /* PSA message body */
|
||||
psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
|
||||
psa_outvec outvec[PSA_MAX_IOVEC];
|
||||
psa_outvec *caller_outvec; /*
|
||||
* Save caller outvec pointer for
|
||||
* write length update
|
||||
*/
|
||||
struct tfm_msg_body_t *next; /* List operators */
|
||||
};
|
||||
|
||||
struct tfm_msg_queue_t {
|
||||
struct tfm_msg_body_t *head; /* Queue head */
|
||||
struct tfm_msg_body_t *tail; /* Queue tail */
|
||||
uint32_t size; /* Number of the queue member */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enqueue a message into message queue.
|
||||
*
|
||||
* \param[in] queue Message queue, it will be initialized
|
||||
* if has not been initialized.
|
||||
* \param[in] node Message queue node want to be enqueue.
|
||||
*
|
||||
* \retval IPC_SUCCESS Success.
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
|
||||
*/
|
||||
int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
|
||||
struct tfm_msg_body_t *node);
|
||||
|
||||
/**
|
||||
* \brief Dequeue a message from message queue.
|
||||
*
|
||||
* \param[in] queue Message queue.
|
||||
*
|
||||
* \retval node pointer Success.
|
||||
* \retval NULL Queue is NULL or size is zero.
|
||||
*/
|
||||
struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue);
|
||||
|
||||
/**
|
||||
* \brief Check if a message queue is empty.
|
||||
*
|
||||
* \param[in] queue Message queue.
|
||||
*
|
||||
* \returns Returns 1 for empty, or 0 for not.
|
||||
*/
|
||||
int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue);
|
||||
|
||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_POOLS_H__
|
||||
#define __TFM_POOLS_H__
|
||||
|
||||
/*
|
||||
* Resource pool - few known size resources allocation/free is required,
|
||||
* so pool is more applicable than heap.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Pool Instance:
|
||||
* [ Pool Instance ] + N * [ Pool Chunks ]
|
||||
*/
|
||||
struct tfm_pool_chunk_t {
|
||||
struct tfm_list_node_t list; /* Chunk list */
|
||||
void *pool; /* Point to the parent pool */
|
||||
uint8_t data[0]; /* Data indicator */
|
||||
};
|
||||
|
||||
struct tfm_pool_instance_t {
|
||||
size_t chunksz; /* Chunks size of pool member */
|
||||
struct tfm_list_node_t chunks_list; /* Chunk list head in pool */
|
||||
struct tfm_pool_chunk_t chunks[0]; /* Data indicator */
|
||||
};
|
||||
|
||||
/*
|
||||
* This will declares a static memory pool variable with chunk memory.
|
||||
* Parameters:
|
||||
* name - Variable name, will be used when register
|
||||
* chunksz - chunk size in bytes
|
||||
* num - Number of chunks
|
||||
*/
|
||||
#define TFM_POOL_DECLARE(name, chunksz, num) \
|
||||
static uint8_t name##_pool_buf[((chunksz) + \
|
||||
sizeof(struct tfm_pool_chunk_t)) * (num) \
|
||||
+ sizeof(struct tfm_pool_instance_t)] \
|
||||
__attribute__((aligned(4))); \
|
||||
static struct tfm_pool_instance_t *name = \
|
||||
(struct tfm_pool_instance_t *)name##_pool_buf
|
||||
|
||||
/* Get the head size of memory pool */
|
||||
#define POOL_HEAD_SIZE (sizeof(struct tfm_pool_instance_t) + \
|
||||
sizeof(struct tfm_pool_chunk_t))
|
||||
|
||||
/* Get the whole size of memory pool */
|
||||
#define POOL_BUFFER_SIZE(name) sizeof(name##_pool_buf)
|
||||
|
||||
/**
|
||||
* \brief Register a memory pool.
|
||||
*
|
||||
* \param[in] pool Pointer to memory pool declared by
|
||||
* \ref TFM_POOL_DECLARE
|
||||
* \param[in] poolsz Size of the pool buffer.
|
||||
* \param[in] chunksz Size of chunks.
|
||||
* \param[in] num Number of chunks.
|
||||
*
|
||||
* \retval IPC_SUCCESS Success.
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
|
||||
*/
|
||||
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
|
||||
size_t chunksz, size_t num);
|
||||
|
||||
/**
|
||||
* \brief Allocate a memory from pool.
|
||||
*
|
||||
* \param[in] pool pool pointer decleared by \ref TFM_POOL_DECLARE
|
||||
*
|
||||
* \retval buffer pointer Success.
|
||||
* \retval NULL Failed.
|
||||
*/
|
||||
void *tfm_pool_alloc(struct tfm_pool_instance_t *pool);
|
||||
|
||||
/**
|
||||
* \brief Free the allocated memory.
|
||||
*
|
||||
* \param[in] ptr Buffer pointer want to free.
|
||||
*/
|
||||
void tfm_pool_free(void *ptr);
|
||||
|
||||
#endif
|
|
@ -1,326 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_SPM_H__
|
||||
#define __TFM_SPM_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "tfm_list.h"
|
||||
#include "tfm_secure_api.h"
|
||||
|
||||
#ifndef TFM_SPM_MAX_ROT_SERV_NUM
|
||||
#define TFM_SPM_MAX_ROT_SERV_NUM 28
|
||||
#endif
|
||||
#define TFM_VERSION_POLICY_RELAXED 0
|
||||
#define TFM_VERSION_POLICY_STRICT 1
|
||||
|
||||
#ifndef TFM_CONN_HANDLE_MAX_NUM
|
||||
#define TFM_CONN_HANDLE_MAX_NUM 32
|
||||
#endif
|
||||
|
||||
/* RoT connection handle list */
|
||||
struct tfm_conn_handle_t {
|
||||
psa_handle_t handle; /* Handle value */
|
||||
void *rhandle; /* Reverse handle value */
|
||||
struct tfm_list_node_t list; /* list node */
|
||||
};
|
||||
|
||||
/* Service database defined by manifest */
|
||||
struct tfm_spm_service_db_t {
|
||||
char *name; /* Service name */
|
||||
uint32_t partition_id; /* Partition ID which service belong to */
|
||||
psa_signal_t signal; /* Service signal */
|
||||
uint32_t sid; /* Service identifier */
|
||||
bool non_secure_client; /* If can be called by non secure client */
|
||||
uint32_t minor_version; /* Minor version */
|
||||
uint32_t minor_policy; /* Minor version policy */
|
||||
};
|
||||
|
||||
/* RoT Service data */
|
||||
struct tfm_spm_service_t {
|
||||
struct tfm_spm_service_db_t *service_db; /* Service database pointer */
|
||||
struct tfm_spm_ipc_partition_t *partition; /*
|
||||
* Point to secure partition
|
||||
* data
|
||||
*/
|
||||
struct tfm_list_node_t handle_list; /* Service handle list */
|
||||
struct tfm_msg_queue_t msg_queue; /* Message queue */
|
||||
struct tfm_list_node_t list; /* For list operation */
|
||||
};
|
||||
|
||||
/*
|
||||
* FixMe: This structure is for IPC partition which is different with library
|
||||
* mode partition. There needs to be an alignment for IPC partition database
|
||||
* and library mode database.
|
||||
*/
|
||||
/* Secure Partition data */
|
||||
struct tfm_spm_ipc_partition_t {
|
||||
int32_t index; /* Partition index */
|
||||
int32_t id; /* Secure partition ID */
|
||||
struct tfm_event_t signal_evnt; /* Event signal */
|
||||
uint32_t signals; /* Service signals had been triggered*/
|
||||
uint32_t signal_mask; /* Service signal mask passed by psa_wait() */
|
||||
struct tfm_list_node_t service_list;/* Service list */
|
||||
};
|
||||
|
||||
/*************************** Extended SPM functions **************************/
|
||||
|
||||
/**
|
||||
* \brief Get the running partition ID.
|
||||
*
|
||||
* \return Returns the partition ID
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_running_partition_id_ext(void);
|
||||
|
||||
/**
|
||||
* \brief Get the current partition mode.
|
||||
*
|
||||
* \param[in] partition_idx Index of current partition
|
||||
*
|
||||
* \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode
|
||||
* \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx);
|
||||
|
||||
/******************** Service handle management functions ********************/
|
||||
|
||||
/**
|
||||
* \brief Create connection handle for client connect
|
||||
*
|
||||
* \param[in] service Target service context pointer
|
||||
*
|
||||
* \retval PSA_NULL_HANDLE Create failed \ref PSA_NULL_HANDLE
|
||||
* \retval >0 Service handle created, \ref psa_handle_t
|
||||
*/
|
||||
psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service);
|
||||
|
||||
/**
|
||||
* \brief Free connection handle which not used anymore.
|
||||
*
|
||||
* \param[in] service Target service context pointer
|
||||
* \param[in] conn_handle Connection handle created by
|
||||
* tfm_spm_create_conn_handle(), \ref psa_handle_t
|
||||
*
|
||||
* \retval IPC_SUCCESS Success
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
|
||||
* \retval "Does not return" Panic for not find service by handle
|
||||
*/
|
||||
int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle);
|
||||
|
||||
/**
|
||||
* \brief Set reverse handle value for connection.
|
||||
*
|
||||
* \param[in] service Target service context pointer
|
||||
* \param[in] conn_handle Connection handle created by
|
||||
* tfm_spm_create_conn_handle(), \ref psa_handle_t
|
||||
* \param[in] rhandle rhandle need to save
|
||||
*
|
||||
* \retval IPC_SUCCESS Success
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
|
||||
* \retval "Does not return" Panic for not find handle node
|
||||
*/
|
||||
int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle,
|
||||
void *rhandle);
|
||||
|
||||
/**
|
||||
* \brief Get reverse handle value from connection hanlde.
|
||||
*
|
||||
* \param[in] service Target service context pointer
|
||||
* \param[in] conn_handle Connection handle created by
|
||||
* tfm_spm_create_conn_handle(), \ref psa_handle_t
|
||||
*
|
||||
* \retval void * Success
|
||||
* \retval "Does not return" Panic for those:
|
||||
* service pointer are NULL
|
||||
* hanlde is \ref PSA_NULL_HANDLE
|
||||
* handle node does not be found
|
||||
*/
|
||||
void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle);
|
||||
|
||||
/******************** Partition management functions *************************/
|
||||
|
||||
/**
|
||||
* \brief Get current running partition context.
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" Return the parttion context pointer
|
||||
* \ref spm_partition_t structures
|
||||
*/
|
||||
struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void);
|
||||
|
||||
/**
|
||||
* \brief Get the service context by signal.
|
||||
*
|
||||
* \param[in] partition Partition context pointer
|
||||
* \ref spm_partition_t structures
|
||||
* \param[in] signal Signal associated with inputs to the Secure
|
||||
* Partition, \ref psa_signal_t
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" Target service context pointer,
|
||||
* \ref spm_service_t structures
|
||||
*/
|
||||
struct tfm_spm_service_t *
|
||||
tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
|
||||
psa_signal_t signal);
|
||||
|
||||
/**
|
||||
* \brief Get the service context by service ID.
|
||||
*
|
||||
* \param[in] sid RoT Service identity
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" Target service context pointer,
|
||||
* \ref spm_service_t structures
|
||||
*/
|
||||
struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
|
||||
|
||||
/**
|
||||
* \brief Get the service context by connection handle.
|
||||
*
|
||||
* \param[in] conn_handle Connection handle created by
|
||||
* tfm_spm_create_conn_handle()
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" Target service context pointer,
|
||||
* \ref spm_service_t structures
|
||||
*/
|
||||
struct tfm_spm_service_t *
|
||||
tfm_spm_get_service_by_handle(psa_handle_t conn_handle);
|
||||
|
||||
/**
|
||||
* \brief Get the partition context by partition ID.
|
||||
*
|
||||
* \param[in] partition_id Partition identity
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" Target partition context pointer,
|
||||
* \ref spm_partition_t structures
|
||||
*/
|
||||
struct tfm_spm_ipc_partition_t *
|
||||
tfm_spm_get_partition_by_id(int32_t partition_id);
|
||||
|
||||
/************************ Message functions **********************************/
|
||||
|
||||
/**
|
||||
* \brief Get message context by message handle.
|
||||
*
|
||||
* \param[in] msg_handle Message handle which is a reference generated
|
||||
* by the SPM to a specific message.
|
||||
*
|
||||
* \return The message body context pointer
|
||||
* \ref msg_body_t structures
|
||||
*/
|
||||
struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle);
|
||||
|
||||
/**
|
||||
* \brief Create a message for PSA client call.
|
||||
*
|
||||
* \param[in] service Target service context pointer, which can be
|
||||
* obtained by partition management functions
|
||||
* \prarm[in] handle Connect handle return by psa_connect(). Should
|
||||
* be \ref PSA_NULL_HANDLE in psa_connect().
|
||||
* \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
|
||||
* PSA_IPC_DISCONNECT
|
||||
* \param[in] ns_caller Whether from NS caller
|
||||
* \param[in] invec Array of input \ref psa_invec structures
|
||||
* \param[in] in_len Number of input \ref psa_invec structures
|
||||
* \param[in] outvec Array of output \ref psa_outvec structures
|
||||
* \param[in] out_len Number of output \ref psa_outvec structures
|
||||
* \param[in] caller_outvec Array of caller output \ref psa_outvec structures
|
||||
*
|
||||
* \retval NULL Failed
|
||||
* \retval "Not NULL" New message body pointer \ref msg_body_t structures
|
||||
*/
|
||||
struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
|
||||
psa_handle_t handle,
|
||||
uint32_t type, int32_t ns_caller,
|
||||
psa_invec *invec, size_t in_len,
|
||||
psa_outvec *outvec, size_t out_len,
|
||||
psa_outvec *caller_outvec);
|
||||
|
||||
/**
|
||||
* \brief Free message which unused anymore
|
||||
*
|
||||
* \param[in] msg Message pointer which want to free
|
||||
* \ref msg_body_t structures
|
||||
*
|
||||
* \retval void Success
|
||||
* \retval "Does not return" Failed
|
||||
*/
|
||||
void tfm_spm_free_msg(struct tfm_msg_body_t *msg);
|
||||
|
||||
/**
|
||||
* \brief Send message and wake up the SP who is waiting on
|
||||
* message queue, block the current thread and
|
||||
* scheduler triggered
|
||||
*
|
||||
* \param[in] service Target service context pointer, which can be
|
||||
* obtained by partition management functions
|
||||
* \param[in] msg message created by spm_create_msg()
|
||||
* \ref msg_body_t structures
|
||||
*
|
||||
* \retval IPC_SUCCESS Success
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
|
||||
* \retval IPC_ERROR_GENERIC Failed to enqueue message to service message queue
|
||||
*/
|
||||
int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
|
||||
struct tfm_msg_body_t *msg);
|
||||
|
||||
/**
|
||||
* \brief Check the client minor version according to
|
||||
* version policy
|
||||
*
|
||||
* \param[in] service Target service context pointer, which can be get
|
||||
* by partition management functions
|
||||
* \param[in] minor_version Client support minor version
|
||||
*
|
||||
* \retval IPC_SUCCESS Success
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
|
||||
* \retval IPC_ERROR_VERSION Check failed
|
||||
*/
|
||||
int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
|
||||
uint32_t minor_version);
|
||||
|
||||
/**
|
||||
* \brief Check the memory reference is valid.
|
||||
*
|
||||
* \param[in] buffer Pointer of memory reference
|
||||
* \param[in] len Length of memory reference in bytes
|
||||
* \param[in] ns_caller From non-secure caller
|
||||
* \param[in] access Type of access specified by the
|
||||
* \ref tfm_memory_access_e
|
||||
* \param[in] privileged Privileged mode or unprivileged mode:
|
||||
* \ref TFM_PARTITION_UNPRIVILEGED_MODE
|
||||
* \ref TFM_PARTITION_PRIVILEGED_MODE
|
||||
*
|
||||
* \retval IPC_SUCCESS Success
|
||||
* \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
|
||||
* \retval IPC_ERROR_MEMORY_CHECK Check failed
|
||||
*/
|
||||
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
|
||||
enum tfm_memory_access_e access,
|
||||
uint32_t privileged);
|
||||
|
||||
/* This function should be called before schedule function */
|
||||
void tfm_spm_init(void);
|
||||
|
||||
/*
|
||||
* PendSV specified function.
|
||||
*
|
||||
* Parameters :
|
||||
* ctxb - State context storage pointer
|
||||
*
|
||||
* Notes:
|
||||
* This is a staging API. Scheduler should be called in SPM finally and
|
||||
* this function will be obsoleted later.
|
||||
*/
|
||||
void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb);
|
||||
|
||||
#endif
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_SVCALLS_H__
|
||||
#define __TFM_SVCALLS_H__
|
||||
|
||||
/* Svcall for PSA Client APIs */
|
||||
|
||||
/**
|
||||
* \brief SVC handler for \ref psa_framework_version.
|
||||
*
|
||||
* \return version The version of the PSA Framework implementation
|
||||
* that is providing the runtime services to the
|
||||
* caller.
|
||||
*/
|
||||
uint32_t tfm_svcall_psa_framework_version(void);
|
||||
|
||||
/**
|
||||
* \brief SVC handler for \ref psa_version.
|
||||
*
|
||||
* \param[in] args Include all input arguments: sid.
|
||||
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
||||
* Or from secure client.
|
||||
*
|
||||
* \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
|
||||
* caller is not permitted to access the service.
|
||||
* \retval > 0 The minor version of the implemented RoT
|
||||
* Service.
|
||||
*/
|
||||
uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller);
|
||||
|
||||
/**
|
||||
* \brief SVC handler for \ref psa_connect.
|
||||
*
|
||||
* \param[in] args Include all input arguments:
|
||||
* sid, minor_version.
|
||||
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
||||
* Or from secure client.
|
||||
*
|
||||
* \retval > 0 A handle for the connection.
|
||||
* \retval PSA_CONNECTION_REFUSED The SPM or RoT Service has refused the
|
||||
* connection.
|
||||
* \retval PSA_CONNECTION_BUSY The SPM or RoT Service cannot make the
|
||||
* connection at the moment.
|
||||
* \retval "Does not return" The RoT Service ID and version are not
|
||||
* supported, or the caller is not permitted to
|
||||
* access the service.
|
||||
*/
|
||||
psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller);
|
||||
|
||||
/**
|
||||
* \brief SVC handler for \ref psa_call.
|
||||
*
|
||||
* \param[in] args Include all input arguments:
|
||||
* handle, in_vec, in_len, out_vec, out_len.
|
||||
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
||||
* Or from secure client.
|
||||
* \param[in] lr EXC_RETURN value of the SVC.
|
||||
*
|
||||
* \retval >=0 RoT Service-specific status value.
|
||||
* \retval <0 RoT Service-specific error code.
|
||||
* \retval PSA_DROP_CONNECTION The connection has been dropped by the RoT
|
||||
* Service. This indicates that either this or
|
||||
* a previous message was invalid.
|
||||
* \retval "Does not return" The call is invalid, one or more of the
|
||||
* following are true:
|
||||
* \arg An invalid handle was passed.
|
||||
* \arg The connection is already handling a request.
|
||||
* \arg An invalid memory reference was provided.
|
||||
* \arg in_len + out_len > PSA_MAX_IOVEC.
|
||||
* \arg The message is unrecognized by the RoT
|
||||
* Service or incorrectly formatted.
|
||||
*/
|
||||
psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller,
|
||||
uint32_t lr);
|
||||
|
||||
/**
|
||||
* \brief SVC handler for \ref psa_close.
|
||||
*
|
||||
* \param[in] args Include all input arguments: handle.
|
||||
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
||||
* Or from secure client.
|
||||
*
|
||||
* \retval void Success.
|
||||
* \retval "Does not return" The call is invalid, one or more of the
|
||||
* following are true:
|
||||
* \arg An invalid handle was provided that is not
|
||||
* the null handle.
|
||||
* \arg The connection is handling a request.
|
||||
*/
|
||||
void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller);
|
||||
|
||||
/**
|
||||
* \brief SVC handler for IPC functions
|
||||
*
|
||||
* \param[in] svc_num SVC number
|
||||
* \param[in] ctx Argument context
|
||||
* \param[in] lr EXC_RETURN value of the SVC.
|
||||
*
|
||||
* \returns Return values from those who has,
|
||||
* or PSA_SUCCESS.
|
||||
*/
|
||||
int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx, uint32_t lr);
|
||||
|
||||
#endif
|
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_THREAD_H__
|
||||
#define __TFM_THREAD_H__
|
||||
|
||||
#include "tfm_arch_v8m.h"
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
/* Status code */
|
||||
#define THRD_STAT_CREATING 0
|
||||
#define THRD_STAT_RUNNING 1
|
||||
#define THRD_STAT_BLOCK 2
|
||||
#define THRD_STAT_DETACH 3
|
||||
#define THRD_STAT_INVALID 4
|
||||
|
||||
/* Security attribute - default as security */
|
||||
#define THRD_ATTR_SECURE_OFFSET 16
|
||||
#define THRD_ATTR_SECURE (0)
|
||||
#define THRD_ATTR_NON_SECURE (1 << THRD_ATTR_SECURE_OFFSET)
|
||||
|
||||
/* Lower value has higher priority */
|
||||
#define THRD_PRIOR_MASK 0xFF
|
||||
#define THRD_PRIOR_HIGHEST 0x0
|
||||
#define THRD_PRIOR_MEDIUM 0x7F
|
||||
#define THRD_PRIOR_LOWEST 0xFF
|
||||
|
||||
/* Error code */
|
||||
#define THRD_SUCCESS 0
|
||||
#define THRD_ERR_INVALID_PARAM 1
|
||||
|
||||
/* Thread entry function type */
|
||||
typedef void *(*tfm_thrd_func_t)(void *);
|
||||
|
||||
/* Thread context */
|
||||
struct tfm_thrd_ctx {
|
||||
tfm_thrd_func_t pfn; /* entry function */
|
||||
void *param; /* entry parameter */
|
||||
uint8_t *sp_base; /* stack bottom */
|
||||
uint8_t *sp_top; /* stack top */
|
||||
uint32_t prior; /* priority */
|
||||
uint32_t status; /* status */
|
||||
|
||||
struct tfm_state_context state_ctx; /* State context */
|
||||
struct tfm_thrd_ctx *next; /* next thread in list */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a thread context with the necessary info.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of caller provided thread context
|
||||
* pfn - thread entry function
|
||||
* param - thread entry function parameter
|
||||
* sp_base - stack pointer base (higher address)
|
||||
* sp_top - stack pointer top (lower address)
|
||||
*
|
||||
* Notes :
|
||||
* Thread contex rely on caller allocated memory; initialize members in
|
||||
* context. This function does not insert thread into schedulable list.
|
||||
*/
|
||||
void tfm_thrd_init(struct tfm_thrd_ctx *pth,
|
||||
tfm_thrd_func_t pfn, void *param,
|
||||
uint8_t *sp_base, uint8_t *sp_top);
|
||||
|
||||
/* Set thread priority.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
* prior - priority value (0~255)
|
||||
*
|
||||
* Notes :
|
||||
* Set thread priority. Priority is set to THRD_PRIOR_MEDIUM in
|
||||
* tfm_thrd_init().
|
||||
*/
|
||||
void __STATIC_INLINE tfm_thrd_priority(struct tfm_thrd_ctx *pth,
|
||||
uint32_t prior)
|
||||
{
|
||||
pth->prior &= ~THRD_PRIOR_MASK;
|
||||
pth->prior |= prior & THRD_PRIOR_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set thread security attribute.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
* attr_secure - THRD_ATTR_SECURE or THRD_ATTR_NON_SECURE
|
||||
*
|
||||
* Notes
|
||||
* Reuse prior of thread context to shift down non-secure thread priority.
|
||||
*/
|
||||
void __STATIC_INLINE tfm_thrd_secure(struct tfm_thrd_ctx *pth,
|
||||
uint32_t attr_secure)
|
||||
{
|
||||
pth->prior &= ~THRD_ATTR_NON_SECURE;
|
||||
pth->prior |= attr_secure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set thread status.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
* new_status - new status of thread
|
||||
*
|
||||
* Return :
|
||||
* None
|
||||
*
|
||||
* Notes :
|
||||
* Thread status is not changed if invalid status value inputed.
|
||||
*/
|
||||
void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status);
|
||||
|
||||
/*
|
||||
* Get thread status.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
*
|
||||
* Return :
|
||||
* Status of thread
|
||||
*/
|
||||
uint32_t __STATIC_INLINE tfm_thrd_get_status(struct tfm_thrd_ctx *pth)
|
||||
{
|
||||
return pth->status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set thread state return value.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
* retval - return value to be set for thread state
|
||||
*
|
||||
* Notes :
|
||||
* This API is useful for blocked syscall blocking thread. Syscall
|
||||
* could set its return value to the caller before caller goes.
|
||||
*/
|
||||
void __STATIC_INLINE tfm_thrd_set_retval(struct tfm_thrd_ctx *pth,
|
||||
uint32_t retval)
|
||||
{
|
||||
TFM_STATE_RET_VAL(&pth->state_ctx) = retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate thread context and insert it into schedulable list.
|
||||
*
|
||||
* Parameters :
|
||||
* pth - pointer of thread context
|
||||
*
|
||||
* Return :
|
||||
* THRD_SUCCESS for success. Or an error is returned.
|
||||
*
|
||||
* Notes :
|
||||
* This function validates thread info. It returns error if thread info
|
||||
* is not correct. Thread is avaliable after successful tfm_thrd_start().
|
||||
*/
|
||||
uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth);
|
||||
|
||||
/*
|
||||
* Get current running thread.
|
||||
*
|
||||
* Return :
|
||||
* Current running thread context pointer.
|
||||
*/
|
||||
struct tfm_thrd_ctx *tfm_thrd_curr_thread(void);
|
||||
|
||||
/*
|
||||
* Get next running thread in list.
|
||||
*
|
||||
* Return :
|
||||
* Pointer of next thread to be run.
|
||||
*/
|
||||
struct tfm_thrd_ctx *tfm_thrd_next_thread(void);
|
||||
|
||||
/*
|
||||
* Start scheduler for existing threads
|
||||
*
|
||||
* Parameters:
|
||||
* pth - pointer of the caller context collecting thread
|
||||
*
|
||||
* Notes :
|
||||
* This function should be called only ONCE to start the scheduler.
|
||||
* Caller needs to provide a thread object to collect current context.
|
||||
* The usage of the collected context is caller defined.
|
||||
*/
|
||||
void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth);
|
||||
|
||||
/*
|
||||
* Activate a scheduling action after exception.
|
||||
*
|
||||
* Notes :
|
||||
* This function could be called multiple times before scheduling.
|
||||
*/
|
||||
void tfm_thrd_activate_schedule(void);
|
||||
|
||||
/*
|
||||
* Save current context into 'prev' thread and switch to 'next'.
|
||||
*
|
||||
* Parameters :
|
||||
* ctxb - latest caller context
|
||||
* prev - previous thread to be switched out
|
||||
* next - thread to be run
|
||||
*
|
||||
* Notes :
|
||||
* This function could be called multiple times before scheduling.
|
||||
*/
|
||||
void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb,
|
||||
struct tfm_thrd_ctx *prev,
|
||||
struct tfm_thrd_ctx *next);
|
||||
|
||||
/*
|
||||
* Svcall to exit current running thread.
|
||||
*
|
||||
* Notes :
|
||||
* Remove current thread out of schedulable list.
|
||||
*/
|
||||
void tfm_svcall_thrd_exit(void);
|
||||
|
||||
/*
|
||||
* Exit current running thread for client.
|
||||
*
|
||||
* Notes:
|
||||
* Must be called in thread mode.
|
||||
*/
|
||||
void tfm_thrd_exit(void);
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_UTILS_H__
|
||||
#define __TFM_UTILS_H__
|
||||
|
||||
/* CPU spin here */
|
||||
void tfm_panic(void);
|
||||
|
||||
/* Assert and spin */
|
||||
#define TFM_ASSERT(cond) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
printf("Assert:%s:%d", __FUNCTION__, __LINE__); \
|
||||
while (1) \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get container structure start address from member */
|
||||
#define TFM_GET_CONTAINER_PTR(ptr, type, member) \
|
||||
(type *)((unsigned long)(ptr) - offsetof(type, member))
|
||||
|
||||
int32_t tfm_bitcount(uint32_t n);
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#ifndef __TFM_WAIT_H__
|
||||
#define __TFM_WAIT_H__
|
||||
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
/* The magic number has two purposes: corruption detection and debug */
|
||||
#define TFM_EVENT_MAGIC 0x65766e74
|
||||
|
||||
struct tfm_event_t {
|
||||
uint32_t magic; /* 'evnt' */
|
||||
struct tfm_thrd_ctx *owner; /* Event blocked thread */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize an event object.
|
||||
*
|
||||
* Parameters:
|
||||
* pevnt - The pointer of event object allocated by the caller
|
||||
*/
|
||||
void __STATIC_INLINE tfm_event_init(struct tfm_event_t *pevnt)
|
||||
{
|
||||
pevnt->magic = TFM_EVENT_MAGIC;
|
||||
pevnt->owner = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait on an event object.
|
||||
*
|
||||
* Parameters:
|
||||
* pevnt - The pointer of event object allocated by the caller
|
||||
*
|
||||
* Notes:
|
||||
* Block caller thread by calling this function.
|
||||
*/
|
||||
void tfm_event_wait(struct tfm_event_t *pevnt);
|
||||
|
||||
/*
|
||||
* Wake up an event object.
|
||||
*
|
||||
* Parameters :
|
||||
* pevnt - The pointer of event object allocated by the caller
|
||||
* retval - Value to be returned to owner
|
||||
*
|
||||
* Notes:
|
||||
* Wake up the blocked thread and set parameter 'retval' as the return value.
|
||||
*/
|
||||
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval);
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "tfm_svc.h"
|
||||
#include "psa_client.h"
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
uint32_t psa_framework_version(void)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
uint32_t psa_version(uint32_t sid)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_VERSION));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_CONNECT));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
psa_status_t psa_call(psa_handle_t handle,
|
||||
const psa_invec *in_vec,
|
||||
size_t in_len,
|
||||
psa_outvec *out_vec,
|
||||
size_t out_len)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_CALL));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_close(psa_handle_t handle)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_CLOSE));
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "tfm_svc.h"
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
|
||||
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_WAIT));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_GET));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_SET_RHANDLE));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
|
||||
void *buffer, size_t num_bytes)
|
||||
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_READ));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_SKIP));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
|
||||
const void *buffer, size_t num_bytes)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_WRITE));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_reply(psa_handle_t msg_handle, psa_status_t retval)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_REPLY));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_notify(int32_t partition_id)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_NOTIFY));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_clear(void)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_CLEAR));
|
||||
}
|
||||
|
||||
__attribute__((naked, section("SFN")))
|
||||
void psa_eoi(psa_signal_t irq_signal)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_PSA_EOI));
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tfm_arch_v8m.h"
|
||||
#include "cmsis.h"
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
|
||||
/* This file contains the ARCH code for ARM V8M */
|
||||
|
||||
__attribute__((section("SFN")))
|
||||
static void exit_zone(void)
|
||||
{
|
||||
tfm_thrd_exit();
|
||||
}
|
||||
|
||||
void tfm_initialize_context(struct tfm_state_context *ctx,
|
||||
uint32_t r0, uint32_t ra,
|
||||
uint32_t sp, uint32_t sp_limit)
|
||||
{
|
||||
/*
|
||||
* For security consideration, set unused registers into ZERO;
|
||||
* and only necessary registers are set here.
|
||||
*/
|
||||
struct tfm_state_context_base *p_ctxa =
|
||||
(struct tfm_state_context_base *)sp;
|
||||
|
||||
/*
|
||||
* Shift back SP to leave space for holding base context
|
||||
* since thread is kicked off through exception return.
|
||||
*/
|
||||
p_ctxa--;
|
||||
|
||||
/* Basic context is considerate at thread start.*/
|
||||
tfm_memset(p_ctxa, 0, sizeof(*p_ctxa));
|
||||
p_ctxa->r0 = r0;
|
||||
p_ctxa->ra = ra;
|
||||
p_ctxa->ra_lr = (uint32_t)exit_zone;
|
||||
p_ctxa->xpsr = XPSR_T32;
|
||||
|
||||
tfm_memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->ctxb.sp = (uint32_t)p_ctxa;
|
||||
ctx->ctxb.sp_limit = sp_limit;
|
||||
ctx->ctxb.lr = LR_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stack status at PendSV entry:
|
||||
*
|
||||
* [ R0 - R3 ]<- PSP
|
||||
* [ R12 ]
|
||||
* [ LR_of_RA ]
|
||||
* MSP->[ ........ ] [ RA ]
|
||||
* [ ........ ] [ XPSR ]
|
||||
* [ ........ ]
|
||||
* [ ........ ]
|
||||
*
|
||||
* Stack status before calling pendsv_do_schedule():
|
||||
*
|
||||
* MSP->[ R4 - R11 ]
|
||||
* [ PSP ]--->[ R0 - R3 ]
|
||||
* [ PSP Limit] [ R12 ]
|
||||
* [ R2(dummy)] [ LR_of_RA ]
|
||||
* [ LR ] [ RA ]
|
||||
* [ ........ ] [ XPSR ]
|
||||
* [ ........ ] [ ........ ]
|
||||
* [ ........ ]
|
||||
*
|
||||
* pendsv_do_schedule() updates stacked context into current thread and
|
||||
* replace stacked context with context of next thread.
|
||||
*
|
||||
* Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
|
||||
* thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
|
||||
* aligned.
|
||||
*/
|
||||
#if defined(__ARM_ARCH_8M_MAIN__)
|
||||
__attribute__((naked)) void PendSV_Handler(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"mrs r0, psp \n"
|
||||
"mrs r1, psplim \n"
|
||||
"push {r0, r1, r2, lr} \n"
|
||||
"push {r4-r11} \n"
|
||||
"mov r0, sp \n"
|
||||
"bl tfm_pendsv_do_schedule \n"
|
||||
"pop {r4-r11} \n"
|
||||
"pop {r0, r1, r2, lr} \n"
|
||||
"msr psp, r0 \n"
|
||||
"msr psplim, r1 \n"
|
||||
"bx lr \n"
|
||||
);
|
||||
}
|
||||
#elif defined(__ARM_ARCH_8M_BASE__)
|
||||
__attribute__((naked)) void PendSV_Handler(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"mrs r0, psp \n"
|
||||
"mrs r1, psplim \n"
|
||||
"push {r0, r1, r2, lr} \n"
|
||||
"push {r4-r7} \n"
|
||||
"mov r4, r8 \n"
|
||||
"mov r5, r9 \n"
|
||||
"mov r6, r10 \n"
|
||||
"mov r7, r11 \n"
|
||||
"push {r4-r7} \n"
|
||||
"mov r0, sp \n"
|
||||
"bl tfm_pendsv_do_schedule \n"
|
||||
"pop {r4-r7} \n"
|
||||
"mov r8, r4 \n"
|
||||
"mov r9, r5 \n"
|
||||
"mov r10, r6 \n"
|
||||
"mov r11, r7 \n"
|
||||
"pop {r4-r7} \n"
|
||||
"pop {r0-r3} \n"
|
||||
"mov lr, r3 \n"
|
||||
"msr psp, r0 \n"
|
||||
"msr psplim, r1 \n"
|
||||
"bx lr \n"
|
||||
);
|
||||
}
|
||||
#else
|
||||
#error "Unsupported ARM Architecture."
|
||||
#endif
|
||||
|
||||
/* Reserved for future usage */
|
||||
__attribute__((naked)) void MemManage_Handler(void)
|
||||
{
|
||||
__ASM volatile("b .");
|
||||
}
|
||||
|
||||
__attribute__((naked)) void BusFault_Handler(void)
|
||||
{
|
||||
__ASM volatile("b .");
|
||||
}
|
||||
__attribute__((naked)) void UsageFault_Handler(void)
|
||||
{
|
||||
__ASM volatile("b .");
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_wait.h"
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_internal_defines.h"
|
||||
#include "tfm_message_queue.h"
|
||||
|
||||
/* Message queue process */
|
||||
int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
|
||||
struct tfm_msg_body_t *node)
|
||||
{
|
||||
if (!queue || !node) {
|
||||
return IPC_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
|
||||
if (queue->size == 0) {
|
||||
queue->head = node;
|
||||
queue->tail = node;
|
||||
} else {
|
||||
queue->tail->next = node;
|
||||
queue->tail = node;
|
||||
}
|
||||
queue->size++;
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue)
|
||||
{
|
||||
struct tfm_msg_body_t *pop_node;
|
||||
|
||||
if (!queue) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (queue->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pop_node = queue->head;
|
||||
queue->head = queue->head->next;
|
||||
queue->size--;
|
||||
return pop_node;
|
||||
}
|
||||
|
||||
int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue)
|
||||
{
|
||||
return queue->size == 0 ? 1 : 0;
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_wait.h"
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_internal_defines.h"
|
||||
#include "cmsis_compiler.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "tfm_list.h"
|
||||
#include "tfm_pools.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
|
||||
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
|
||||
size_t chunksz, size_t num)
|
||||
{
|
||||
struct tfm_pool_chunk_t *pchunk;
|
||||
size_t i;
|
||||
|
||||
if (!pool || num == 0) {
|
||||
return IPC_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Ensure buffer is large enough */
|
||||
if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
|
||||
sizeof(struct tfm_pool_instance_t))) {
|
||||
return IPC_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Buffer should be BSS cleared but clear it again */
|
||||
tfm_memset(pool, 0, poolsz);
|
||||
|
||||
/* Chain pool chunks */
|
||||
tfm_list_init(&pool->chunks_list);
|
||||
|
||||
pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
|
||||
for (i = 0; i < num; i++) {
|
||||
pchunk->pool = pool;
|
||||
tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
|
||||
pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
|
||||
}
|
||||
|
||||
/* Prepare instance and insert to pool list */
|
||||
pool->chunksz = chunksz;
|
||||
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
|
||||
{
|
||||
struct tfm_list_node_t *node;
|
||||
struct tfm_pool_chunk_t *pchunk;
|
||||
|
||||
if (!pool) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tfm_list_is_empty(&pool->chunks_list)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = tfm_list_first_node(&pool->chunks_list);
|
||||
pchunk = TFM_GET_CONTAINER_PTR(node, struct tfm_pool_chunk_t, list);
|
||||
|
||||
/* Remove node from list node, it will be added when pool free */
|
||||
tfm_list_del_node(node);
|
||||
|
||||
return &pchunk->data;
|
||||
}
|
||||
|
||||
void tfm_pool_free(void *ptr)
|
||||
{
|
||||
struct tfm_pool_chunk_t *pchunk;
|
||||
struct tfm_pool_instance_t *pool;
|
||||
|
||||
pchunk = TFM_GET_CONTAINER_PTR(ptr, struct tfm_pool_chunk_t, data);
|
||||
pool = (struct tfm_pool_instance_t *)pchunk->pool;
|
||||
tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
|
||||
}
|
|
@ -1,619 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "platform/include/tfm_spm_hal.h"
|
||||
#include "spm_api.h"
|
||||
#include "spm_db.h"
|
||||
#include "spm_db_setup.h"
|
||||
#include "tfm_internal_defines.h"
|
||||
#include "tfm_wait.h"
|
||||
#include "tfm_message_queue.h"
|
||||
#include "tfm_list.h"
|
||||
#include "tfm_pools.h"
|
||||
#include "tfm_spm.h"
|
||||
#include "tfm_spm_signal_defs.h"
|
||||
#include "tfm_thread.h"
|
||||
#include "region_defs.h"
|
||||
#include "tfm_nspm.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
#include "platform/mbed_toolchain.h"
|
||||
|
||||
/*
|
||||
* IPC partitions.
|
||||
* FixMe: Need to get align with spm_partition_db_t.
|
||||
*/
|
||||
static struct tfm_spm_ipc_partition_t
|
||||
g_spm_ipc_partition[SPM_MAX_PARTITIONS] = {};
|
||||
|
||||
/* Extern SPM variable */
|
||||
extern struct spm_partition_db_t g_spm_partition_db;
|
||||
|
||||
/* Extern secure lock variable */
|
||||
extern int32_t tfm_secure_lock;
|
||||
/* Pools */
|
||||
TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
|
||||
TFM_CONN_HANDLE_MAX_NUM);
|
||||
TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
|
||||
TFM_SPM_MAX_ROT_SERV_NUM);
|
||||
TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
|
||||
TFM_MSG_QUEUE_MAX_MSG_NUM);
|
||||
|
||||
static struct tfm_spm_service_db_t g_spm_service_db[] = {
|
||||
#include "tfm_service_list.inc"
|
||||
};
|
||||
|
||||
/********************** SPM functions for handler mode ***********************/
|
||||
|
||||
/* Service handle management functions */
|
||||
psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
|
||||
{
|
||||
struct tfm_conn_handle_t *node;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
|
||||
/* Get buffer for handle list structure from handle pool */
|
||||
node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
|
||||
if (!node) {
|
||||
return PSA_NULL_HANDLE;
|
||||
}
|
||||
|
||||
/* Global unique handle, use handle buffer address directly */
|
||||
node->handle = (psa_handle_t)node;
|
||||
|
||||
/* Add handle node to list for next psa functions */
|
||||
tfm_list_add_tail(&service->handle_list, &node->list);
|
||||
|
||||
return node->handle;
|
||||
}
|
||||
|
||||
static struct tfm_conn_handle_t *
|
||||
tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle)
|
||||
{
|
||||
struct tfm_conn_handle_t *handle_node;
|
||||
struct tfm_list_node_t *node, *head;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
|
||||
head = &service->handle_list;
|
||||
TFM_LIST_FOR_EACH(node, head) {
|
||||
handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
|
||||
list);
|
||||
if (handle_node->handle == conn_handle) {
|
||||
return handle_node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle)
|
||||
{
|
||||
struct tfm_conn_handle_t *node;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
|
||||
/* There are many handles for each RoT Service */
|
||||
node = tfm_spm_find_conn_handle_node(service, conn_handle);
|
||||
if (!node) {
|
||||
tfm_panic();
|
||||
}
|
||||
|
||||
/* Remove node from handle list */
|
||||
tfm_list_del_node(&node->list);
|
||||
|
||||
node->rhandle = NULL;
|
||||
|
||||
/* Back handle buffer to pool */
|
||||
tfm_pool_free(node);
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle,
|
||||
void *rhandle)
|
||||
{
|
||||
struct tfm_conn_handle_t *node;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
/* Set reverse handle value only be allowed for a connected handle */
|
||||
TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
|
||||
|
||||
/* There are many handles for each RoT Service */
|
||||
node = tfm_spm_find_conn_handle_node(service, conn_handle);
|
||||
if (!node) {
|
||||
tfm_panic();
|
||||
}
|
||||
|
||||
node->rhandle = rhandle;
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
|
||||
psa_handle_t conn_handle)
|
||||
{
|
||||
struct tfm_conn_handle_t *node;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
/* Get reverse handle value only be allowed for a connected handle */
|
||||
TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
|
||||
|
||||
/* There are many handles for each RoT Service */
|
||||
node = tfm_spm_find_conn_handle_node(service, conn_handle);
|
||||
if (!node) {
|
||||
tfm_panic();
|
||||
}
|
||||
|
||||
return node->rhandle;
|
||||
}
|
||||
|
||||
/* Partition management functions */
|
||||
struct tfm_spm_service_t *
|
||||
tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
|
||||
psa_signal_t signal)
|
||||
{
|
||||
struct tfm_list_node_t *node, *head;
|
||||
struct tfm_spm_service_t *service;
|
||||
|
||||
TFM_ASSERT(partition);
|
||||
|
||||
if (tfm_list_is_empty(&partition->service_list)) {
|
||||
tfm_panic();
|
||||
}
|
||||
|
||||
head = &partition->service_list;
|
||||
TFM_LIST_FOR_EACH(node, head) {
|
||||
service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
|
||||
if (service->service_db->signal == signal) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
|
||||
{
|
||||
uint32_t i;
|
||||
struct tfm_list_node_t *node, *head;
|
||||
struct tfm_spm_service_t *service;
|
||||
|
||||
for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
|
||||
/* Skip partition without IPC flag */
|
||||
if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
|
||||
SPM_PART_FLAG_IPC) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
head = &g_spm_ipc_partition[i].service_list;
|
||||
TFM_LIST_FOR_EACH(node, head) {
|
||||
service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
|
||||
list);
|
||||
if (service->service_db->sid == sid) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct tfm_spm_service_t *
|
||||
tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
|
||||
{
|
||||
uint32_t i;
|
||||
struct tfm_conn_handle_t *handle;
|
||||
struct tfm_list_node_t *service_node, *service_head;
|
||||
struct tfm_list_node_t *handle_node, *handle_head;
|
||||
struct tfm_spm_service_t *service;
|
||||
|
||||
for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
|
||||
/* Skip partition without IPC flag */
|
||||
if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
|
||||
SPM_PART_FLAG_IPC) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
service_head = &g_spm_ipc_partition[i].service_list;
|
||||
TFM_LIST_FOR_EACH(service_node, service_head) {
|
||||
service = TFM_GET_CONTAINER_PTR(service_node,
|
||||
struct tfm_spm_service_t, list);
|
||||
handle_head = &service->handle_list;
|
||||
TFM_LIST_FOR_EACH(handle_node, handle_head) {
|
||||
handle = TFM_GET_CONTAINER_PTR(handle_node,
|
||||
struct tfm_conn_handle_t, list);
|
||||
if (handle->handle == conn_handle) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct tfm_spm_ipc_partition_t *
|
||||
tfm_spm_get_partition_by_id(int32_t partition_id)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
|
||||
if (g_spm_ipc_partition[i].id == partition_id) {
|
||||
return &g_spm_ipc_partition[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void)
|
||||
{
|
||||
uint32_t spid;
|
||||
|
||||
spid = tfm_spm_partition_get_running_partition_id_ext();
|
||||
|
||||
return tfm_spm_get_partition_by_id(spid);
|
||||
}
|
||||
|
||||
int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
|
||||
uint32_t minor_version)
|
||||
{
|
||||
TFM_ASSERT(service);
|
||||
|
||||
switch (service->service_db->minor_policy) {
|
||||
case TFM_VERSION_POLICY_RELAXED:
|
||||
if (minor_version > service->service_db->minor_version) {
|
||||
return IPC_ERROR_VERSION;
|
||||
}
|
||||
break;
|
||||
case TFM_VERSION_POLICY_STRICT:
|
||||
if (minor_version != service->service_db->minor_version) {
|
||||
return IPC_ERROR_VERSION;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return IPC_ERROR_VERSION;
|
||||
}
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
/* Message functions */
|
||||
struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
|
||||
{
|
||||
/*
|
||||
* There may be one error handle passed by the caller in two conditions:
|
||||
* 1. Not a valid message handle.
|
||||
* 2. Handle between different Partitions. Partition A passes one handle
|
||||
* belong to other Partitions and tries to access other's data.
|
||||
* So, need do necessary checking to prevent those conditions.
|
||||
*/
|
||||
struct tfm_msg_body_t *msg;
|
||||
uint32_t partition_id;
|
||||
|
||||
msg = (struct tfm_msg_body_t *)msg_handle;
|
||||
if (!msg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* FixMe: For condition 1: using a magic number to define it's a message.
|
||||
* It needs to be an enhancement to check the handle belong to service.
|
||||
*/
|
||||
if (msg->magic != TFM_MSG_MAGIC) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For condition 2: check if the partition ID is same */
|
||||
partition_id = tfm_spm_partition_get_running_partition_id_ext();
|
||||
if (partition_id != msg->service->partition->id) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
|
||||
psa_handle_t handle,
|
||||
uint32_t type, int32_t ns_caller,
|
||||
psa_invec *invec, size_t in_len,
|
||||
psa_outvec *outvec, size_t out_len,
|
||||
psa_outvec *caller_outvec)
|
||||
{
|
||||
struct tfm_msg_body_t *msg = NULL;
|
||||
uint32_t i;
|
||||
|
||||
TFM_ASSERT(service);
|
||||
TFM_ASSERT(!(invec == NULL && in_len != 0));
|
||||
TFM_ASSERT(!(outvec == NULL && out_len != 0));
|
||||
TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
|
||||
TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
|
||||
TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
|
||||
|
||||
/* Get message buffer from message pool */
|
||||
msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
|
||||
if (!msg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Clear message buffer before using it */
|
||||
tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
|
||||
|
||||
tfm_event_init(&msg->ack_evnt);
|
||||
msg->magic = TFM_MSG_MAGIC;
|
||||
msg->service = service;
|
||||
msg->handle = handle;
|
||||
msg->caller_outvec = caller_outvec;
|
||||
/* Get current partition id */
|
||||
if (ns_caller) {
|
||||
msg->msg.client_id = tfm_nspm_get_current_client_id();
|
||||
} else {
|
||||
msg->msg.client_id = tfm_spm_partition_get_running_partition_id_ext();
|
||||
}
|
||||
|
||||
/* Copy contents */
|
||||
msg->msg.type = type;
|
||||
|
||||
for (i = 0; i < in_len; i++) {
|
||||
msg->msg.in_size[i] = invec[i].len;
|
||||
msg->invec[i].base = invec[i].base;
|
||||
}
|
||||
|
||||
for (i = 0; i < out_len; i++) {
|
||||
msg->msg.out_size[i] = outvec[i].len;
|
||||
msg->outvec[i].base = outvec[i].base;
|
||||
/* Out len is used to record the writed number, set 0 here again */
|
||||
msg->outvec[i].len = 0;
|
||||
}
|
||||
|
||||
/* Use message address as handle */
|
||||
msg->msg.handle = (psa_handle_t)msg;
|
||||
|
||||
/* For connected handle, set rhandle to every message */
|
||||
if (handle != PSA_NULL_HANDLE) {
|
||||
msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
|
||||
{
|
||||
tfm_pool_free(msg);
|
||||
}
|
||||
|
||||
int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
|
||||
struct tfm_msg_body_t *msg)
|
||||
{
|
||||
TFM_ASSERT(service);
|
||||
TFM_ASSERT(msg);
|
||||
|
||||
/* Enqueue message to service message queue */
|
||||
if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
|
||||
return IPC_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
/* Messages put. Update signals */
|
||||
service->partition->signals |= service->service_db->signal;
|
||||
|
||||
tfm_event_wake(&service->partition->signal_evnt,
|
||||
(service->partition->signals &
|
||||
service->partition->signal_mask));
|
||||
|
||||
tfm_event_wait(&msg->ack_evnt);
|
||||
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
/* SPM extend functions */
|
||||
uint32_t tfm_spm_partition_get_running_partition_id_ext(void)
|
||||
{
|
||||
struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
|
||||
struct spm_partition_desc_t *partition;
|
||||
|
||||
partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
|
||||
sp_thrd);
|
||||
return partition->static_data.partition_id;
|
||||
}
|
||||
|
||||
static struct tfm_thrd_ctx *
|
||||
tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx)
|
||||
{
|
||||
return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
|
||||
}
|
||||
|
||||
static tfm_thrd_func_t
|
||||
tfm_spm_partition_get_init_func_ext(uint32_t partition_idx)
|
||||
{
|
||||
return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
|
||||
static_data.partition_init);
|
||||
}
|
||||
|
||||
static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].static_data.
|
||||
partition_priority;
|
||||
}
|
||||
|
||||
int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller,
|
||||
enum tfm_memory_access_e access,
|
||||
uint32_t privileged)
|
||||
{
|
||||
int32_t err;
|
||||
|
||||
/* If len is zero, this indicates an empty buffer and base is ignored */
|
||||
if (len == 0) {
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
return IPC_ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
|
||||
if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
|
||||
return IPC_ERROR_MEMORY_CHECK;
|
||||
}
|
||||
|
||||
if (access == TFM_MEMORY_ACCESS_RW) {
|
||||
err = tfm_core_has_write_access_to_region(buffer, len, ns_caller,
|
||||
privileged);
|
||||
} else {
|
||||
err = tfm_core_has_read_access_to_region(buffer, len, ns_caller,
|
||||
privileged);
|
||||
}
|
||||
if (err == TFM_SUCCESS) {
|
||||
return IPC_SUCCESS;
|
||||
}
|
||||
|
||||
return IPC_ERROR_MEMORY_CHECK;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx)
|
||||
{
|
||||
if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) {
|
||||
return TFM_PARTITION_PRIVILEGED_MODE;
|
||||
} else {
|
||||
return TFM_PARTITION_UNPRIVILEGED_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
/********************** SPM functions for thread mode ************************/
|
||||
|
||||
void tfm_spm_init(void)
|
||||
{
|
||||
uint32_t i, num;
|
||||
struct tfm_spm_ipc_partition_t *partition;
|
||||
struct tfm_spm_service_t *service;
|
||||
struct tfm_thrd_ctx *pth, this_thrd;
|
||||
struct spm_partition_desc_t *part;
|
||||
|
||||
tfm_pool_init(conn_handle_pool,
|
||||
POOL_BUFFER_SIZE(conn_handle_pool),
|
||||
sizeof(struct tfm_conn_handle_t),
|
||||
TFM_CONN_HANDLE_MAX_NUM);
|
||||
tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
|
||||
sizeof(struct tfm_spm_service_t),
|
||||
TFM_SPM_MAX_ROT_SERV_NUM);
|
||||
tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
|
||||
sizeof(struct tfm_msg_body_t),
|
||||
TFM_MSG_QUEUE_MAX_MSG_NUM);
|
||||
|
||||
/* Init partition first for it will be used when init service */
|
||||
for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
|
||||
part = &g_spm_partition_db.partitions[i];
|
||||
tfm_spm_hal_configure_default_isolation(part->platform_data);
|
||||
g_spm_ipc_partition[i].index = i;
|
||||
if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
|
||||
continue;
|
||||
}
|
||||
g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
|
||||
|
||||
tfm_event_init(&g_spm_ipc_partition[i].signal_evnt);
|
||||
tfm_list_init(&g_spm_ipc_partition[i].service_list);
|
||||
|
||||
pth = tfm_spm_partition_get_thread_info_ext(i);
|
||||
if (!pth) {
|
||||
tfm_panic();
|
||||
}
|
||||
|
||||
tfm_thrd_init(pth,
|
||||
tfm_spm_partition_get_init_func_ext(i),
|
||||
NULL,
|
||||
(uint8_t *)tfm_spm_partition_get_stack_top(i),
|
||||
(uint8_t *)tfm_spm_partition_get_stack_bottom(i));
|
||||
|
||||
pth->prior = tfm_spm_partition_get_priority_ext(i);
|
||||
|
||||
/* Kick off */
|
||||
if (tfm_thrd_start(pth) != THRD_SUCCESS) {
|
||||
tfm_panic();
|
||||
}
|
||||
}
|
||||
|
||||
/* Init Service */
|
||||
num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
|
||||
for (i = 0; i < num; i++) {
|
||||
partition =
|
||||
tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
|
||||
if (!partition) {
|
||||
tfm_panic();
|
||||
}
|
||||
service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
|
||||
if (!service) {
|
||||
tfm_panic();
|
||||
}
|
||||
service->service_db = &g_spm_service_db[i];
|
||||
service->partition = partition;
|
||||
tfm_list_init(&service->handle_list);
|
||||
tfm_list_add_tail(&partition->service_list, &service->list);
|
||||
}
|
||||
|
||||
/*
|
||||
* All threads initialized, start the scheduler.
|
||||
*
|
||||
* NOTE:
|
||||
* Here is the booting privileged thread mode, and will never
|
||||
* return to this place after scheduler is started. The start
|
||||
* function has to save current runtime context to act as a
|
||||
* 'current thread' to avoid repeating NULL 'current thread'
|
||||
* checking while context switching. This saved context is worthy
|
||||
* of being saved somewhere if there are potential usage purpose.
|
||||
* Let's save this context in a local variable 'this_thrd' at
|
||||
* current since there is no usage for it.
|
||||
* Also set tfm_nspm_thread_entry as pfn for this thread to
|
||||
* use in detecting NS/S thread scheduling changes.
|
||||
*/
|
||||
this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry;
|
||||
tfm_thrd_start_scheduler(&this_thrd);
|
||||
}
|
||||
|
||||
MBED_USED void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
|
||||
{
|
||||
#if TFM_LVL == 2
|
||||
struct spm_partition_desc_t *p_next_partition;
|
||||
uint32_t is_privileged;
|
||||
#endif
|
||||
struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread();
|
||||
struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread();
|
||||
|
||||
if (pth_curr != pth_next) {
|
||||
#if TFM_LVL == 2
|
||||
p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
|
||||
struct spm_partition_desc_t,
|
||||
sp_thrd);
|
||||
|
||||
if (p_next_partition->static_data.partition_flags &
|
||||
SPM_PART_FLAG_PSA_ROT) {
|
||||
is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
|
||||
} else {
|
||||
is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
|
||||
}
|
||||
|
||||
tfm_spm_partition_change_privilege(is_privileged);
|
||||
#endif
|
||||
/* Increase the secure lock, if we enter secure from non-secure */
|
||||
if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) {
|
||||
++tfm_secure_lock;
|
||||
}
|
||||
/* Decrease the secure lock, if we return from secure to non-secure */
|
||||
if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) {
|
||||
--tfm_secure_lock;
|
||||
}
|
||||
|
||||
tfm_thrd_context_switch(ctxb, pth_curr, pth_next);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "tfm_arch_v8m.h"
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
#include "tfm_svc.h"
|
||||
#include "spm_api.h"
|
||||
|
||||
/* Force ZERO in case ZI(bss) clear is missing */
|
||||
static struct tfm_thrd_ctx *p_thrd_head = NULL;
|
||||
static struct tfm_thrd_ctx *p_runn_head = NULL;
|
||||
static struct tfm_thrd_ctx *p_curr_thrd = NULL;
|
||||
|
||||
/* Define Macro to fetch global to support future expansion (PERCPU e.g.) */
|
||||
#define LIST_HEAD p_thrd_head
|
||||
#define RUNN_HEAD p_runn_head
|
||||
#define CURR_THRD p_curr_thrd
|
||||
|
||||
static struct tfm_thrd_ctx *find_next_running_thread(struct tfm_thrd_ctx *pth)
|
||||
{
|
||||
while (pth && pth->status != THRD_STAT_RUNNING) {
|
||||
pth = pth->next;
|
||||
}
|
||||
|
||||
return pth;
|
||||
}
|
||||
|
||||
/* To get next running thread for scheduler */
|
||||
struct tfm_thrd_ctx *tfm_thrd_next_thread(void)
|
||||
{
|
||||
/*
|
||||
* First RUNNING thread has highest priority since threads are sorted with
|
||||
* priority.
|
||||
*/
|
||||
return find_next_running_thread(RUNN_HEAD);
|
||||
}
|
||||
|
||||
/* To get current thread for caller */
|
||||
struct tfm_thrd_ctx *tfm_thrd_curr_thread()
|
||||
{
|
||||
return CURR_THRD;
|
||||
}
|
||||
|
||||
/* Insert a new thread into list by descending priority (Highest at head) */
|
||||
static void insert_by_prior(struct tfm_thrd_ctx **head,
|
||||
struct tfm_thrd_ctx *node)
|
||||
{
|
||||
if (*head == NULL || (node->prior <= (*head)->prior)) {
|
||||
node->next = *head;
|
||||
*head = node;
|
||||
} else {
|
||||
struct tfm_thrd_ctx *iter = *head;
|
||||
|
||||
while (iter->next && (node->prior > iter->next->prior)) {
|
||||
iter = iter->next;
|
||||
}
|
||||
node->next = iter->next;
|
||||
iter->next = node;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set first running thread as head to reduce enumerate
|
||||
* depth while searching for a first running thread.
|
||||
*/
|
||||
static void update_running_head(struct tfm_thrd_ctx **runn,
|
||||
struct tfm_thrd_ctx *node)
|
||||
{
|
||||
if ((node->status == THRD_STAT_RUNNING) &&
|
||||
(*runn == NULL || (node->prior < (*runn)->prior))) {
|
||||
*runn = node;
|
||||
} else {
|
||||
*runn = find_next_running_thread(LIST_HEAD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set context members only. No validation here */
|
||||
void tfm_thrd_init(struct tfm_thrd_ctx *pth,
|
||||
tfm_thrd_func_t pfn, void *param,
|
||||
uint8_t *sp_base, uint8_t *sp_top)
|
||||
{
|
||||
pth->prior = THRD_PRIOR_MEDIUM;
|
||||
pth->status = THRD_STAT_CREATING;
|
||||
pth->pfn = pfn;
|
||||
pth->param = param;
|
||||
pth->sp_base = sp_base;
|
||||
pth->sp_top = sp_top;
|
||||
}
|
||||
|
||||
uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth)
|
||||
{
|
||||
/* Validate parameters before really start */
|
||||
if ((pth->status != THRD_STAT_CREATING) ||
|
||||
(pth->pfn == NULL) ||
|
||||
(pth->sp_base == NULL) ||
|
||||
(pth->sp_top == NULL)) {
|
||||
return THRD_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Thread management runs in handler mode; set context for thread mode. */
|
||||
tfm_initialize_context(&pth->state_ctx,
|
||||
(uint32_t)pth->param, (uint32_t)pth->pfn,
|
||||
(uint32_t)pth->sp_base, (uint32_t)pth->sp_top);
|
||||
|
||||
/* Insert a new thread with priority */
|
||||
insert_by_prior(&LIST_HEAD, pth);
|
||||
|
||||
/* Mark it as RUNNING after insertion */
|
||||
tfm_thrd_set_status(pth, THRD_STAT_RUNNING);
|
||||
|
||||
return THRD_SUCCESS;
|
||||
}
|
||||
|
||||
void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status)
|
||||
{
|
||||
TFM_ASSERT(pth != NULL && new_status < THRD_STAT_INVALID);
|
||||
|
||||
pth->status = new_status;
|
||||
update_running_head(&RUNN_HEAD, pth);
|
||||
}
|
||||
|
||||
/* Scheduling won't happen immediately but after the exception returns */
|
||||
void tfm_thrd_activate_schedule(void)
|
||||
{
|
||||
tfm_trigger_pendsv();
|
||||
}
|
||||
|
||||
void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth)
|
||||
{
|
||||
/*
|
||||
* There is no selected thread before scheduler start, assign
|
||||
* a caller provided thread as current thread. This function
|
||||
* should get called only ONCE; further calling triggers assert.
|
||||
*/
|
||||
TFM_ASSERT(CURR_THRD == NULL);
|
||||
TFM_ASSERT(pth != NULL);
|
||||
|
||||
CURR_THRD = pth;
|
||||
tfm_thrd_activate_schedule();
|
||||
}
|
||||
|
||||
/* Remove current thread out of the schedulable list */
|
||||
void tfm_svcall_thrd_exit(void)
|
||||
{
|
||||
CURR_THRD->status = THRD_STAT_DETACH;
|
||||
tfm_trigger_pendsv();
|
||||
}
|
||||
|
||||
__attribute__((section("SFN")))
|
||||
void tfm_thrd_exit(void)
|
||||
{
|
||||
SVC(TFM_SVC_EXIT_THRD);
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb,
|
||||
struct tfm_thrd_ctx *prev,
|
||||
struct tfm_thrd_ctx *next)
|
||||
{
|
||||
TFM_ASSERT(prev != NULL);
|
||||
TFM_ASSERT(next != NULL);
|
||||
|
||||
/*
|
||||
* First, update latest context into the current thread context.
|
||||
* Then, update background context with next thread's context.
|
||||
*/
|
||||
tfm_memcpy(&prev->state_ctx.ctxb, ctxb, sizeof(*ctxb));
|
||||
tfm_memcpy(ctxb, &next->state_ctx.ctxb, sizeof(next->state_ctx.ctxb));
|
||||
|
||||
/* Update current thread indicator */
|
||||
CURR_THRD = next;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include "tfm_utils.h"
|
||||
|
||||
void tfm_panic(void)
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
int32_t tfm_bitcount(uint32_t n)
|
||||
{
|
||||
int32_t count = 0;
|
||||
uint8_t tmp;
|
||||
|
||||
while (n) {
|
||||
tmp = n & 0xFF;
|
||||
while (tmp) {
|
||||
count += tmp & 0x1;
|
||||
tmp >>= 1;
|
||||
}
|
||||
n >>= 8;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "tfm_wait.h"
|
||||
|
||||
void tfm_event_wait(struct tfm_event_t *pevnt)
|
||||
{
|
||||
TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
|
||||
|
||||
pevnt->owner = tfm_thrd_curr_thread();
|
||||
tfm_thrd_set_status(pevnt->owner, THRD_STAT_BLOCK);
|
||||
tfm_thrd_activate_schedule();
|
||||
}
|
||||
|
||||
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval)
|
||||
{
|
||||
TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
|
||||
|
||||
if (pevnt->owner && pevnt->owner->status == THRD_STAT_BLOCK) {
|
||||
tfm_thrd_set_status(pevnt->owner, THRD_STAT_RUNNING);
|
||||
tfm_thrd_set_retval(pevnt->owner, retval);
|
||||
tfm_thrd_activate_schedule();
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_UTILITIES_H__
|
||||
#define __SECURE_UTILITIES_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cmsis_compiler.h"
|
||||
#include "tfm_svc.h"
|
||||
|
||||
#define EXC_RETURN_INDICATOR (0xF << 28)
|
||||
#define EXC_RETURN_SECURITY_STACK_STATUS_MASK (0x3 << 5)
|
||||
#define EXC_RETURN_SECURE_STACK (1 << 6)
|
||||
#define EXC_RETURN_FPU_FRAME_BASIC (1 << 4)
|
||||
#define EXC_RETURN_MODE_THREAD (1 << 3)
|
||||
#define EXC_RETURN_STACK_PROCESS (1 << 2)
|
||||
#define EXC_RETURN_EXC_SECURE (1)
|
||||
|
||||
#define EXC_NUM_THREAD_MODE (0)
|
||||
#define EXC_NUM_SVCALL (11)
|
||||
#define EXC_NUM_PENDSV (14)
|
||||
#define EXC_NUM_SYSTICK (15)
|
||||
|
||||
#define printf(...)
|
||||
|
||||
/* Disable NS exceptions by setting NS PRIMASK to 1 */
|
||||
#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
|
||||
/* Enable NS exceptions by setting NS PRIMASK to 0 */
|
||||
#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
|
||||
|
||||
struct tfm_exc_stack_t {
|
||||
uint32_t R0;
|
||||
uint32_t R1;
|
||||
uint32_t R2;
|
||||
uint32_t R3;
|
||||
uint32_t R12;
|
||||
uint32_t LR;
|
||||
uint32_t RetAddr;
|
||||
uint32_t XPSR;
|
||||
};
|
||||
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
#define LOG_MSG_HDLR(MSG) printf("[Sec Handler] %s\r\n", MSG)
|
||||
#else
|
||||
/* FixMe: redirect to secure log area */
|
||||
#define LOG_MSG_HDLR(MSG) printf("[Sec Handler] %s\r\n", MSG)
|
||||
#endif
|
||||
|
||||
#define LOG_MSG_THR(MSG) \
|
||||
__ASM volatile("MOV r0, %0\n" \
|
||||
"SVC %1\n" \
|
||||
: : "r" (MSG), "I" (TFM_SVC_PRINT))
|
||||
|
||||
#define LOG_MSG(MSG) \
|
||||
do { \
|
||||
if (__get_active_exc_num()) { \
|
||||
LOG_MSG_HDLR(MSG); \
|
||||
} else { \
|
||||
LOG_MSG_THR(MSG); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
#define ERROR_MSG(MSG) printf("[Sec Error] %s\r\n", MSG)
|
||||
#else
|
||||
/* FixMe: redirect to secure log area */
|
||||
#define ERROR_MSG(MSG) printf("[Sec Error] %s\r\n", MSG)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Get Link Register
|
||||
* \details Returns the value of the Link Register (LR)
|
||||
* \return LR value
|
||||
*/
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
|
||||
{
|
||||
register uint32_t result;
|
||||
|
||||
__ASM volatile ("MOV %0, LR\n" : "=r" (result));
|
||||
return result;
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
__STATIC_INLINE uint32_t __get_active_exc_num(void)
|
||||
{
|
||||
IPSR_Type IPSR;
|
||||
|
||||
/* if non-zero, exception is active. NOT banked S/NS */
|
||||
IPSR.w = __get_IPSR();
|
||||
return IPSR.b.ISR;
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline))
|
||||
__STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL)
|
||||
{
|
||||
CONTROL_Type ctrl;
|
||||
|
||||
ctrl.w = __get_CONTROL();
|
||||
ctrl.b.SPSEL = SPSEL;
|
||||
__set_CONTROL(ctrl.w);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
#endif /* __SECURE_UTILITIES_H__ */
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bl2/include/tfm_boot_status.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
#include "tfm_internal.h"
|
||||
#include "tfm_api.h"
|
||||
#include "flash_layout.h"
|
||||
#include "secure_fw/spm/spm_api.h"
|
||||
#ifdef TFM_PSA_API
|
||||
#include "tfm_internal_defines.h"
|
||||
#include "tfm_utils.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_wait.h"
|
||||
#include "tfm_message_queue.h"
|
||||
#include "tfm_spm.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \def BOOT_DATA_VALID
|
||||
*
|
||||
* \brief Indicates that shared data between bootloader and runtime firmware was
|
||||
* passed the sanity check with success.
|
||||
*/
|
||||
#define BOOT_DATA_VALID (1u)
|
||||
|
||||
/*!
|
||||
* \def BOOT_DATA_INVALID
|
||||
*
|
||||
* \brief Indicates that shared data between bootloader and runtime firmware was
|
||||
* failed on sanity check.
|
||||
*/
|
||||
#define BOOT_DATA_INVALID (0u)
|
||||
|
||||
/*!
|
||||
* \var is_boot_data_valid
|
||||
*
|
||||
* \brief Indicates the status of shared data between bootloader and runtime
|
||||
* firmware
|
||||
*/
|
||||
static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
|
||||
|
||||
void tfm_core_validate_boot_data(void)
|
||||
{
|
||||
struct tfm_boot_data *boot_data;
|
||||
|
||||
boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
|
||||
|
||||
/* FixMe: Enhance sanity check of shared memory area, it might be invalid:
|
||||
* - temporal exposure of RAM to non-secure actors
|
||||
* - mismatched addresses
|
||||
* - version mismatch between bootloader and runtime binary
|
||||
* - etc.
|
||||
*/
|
||||
if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
|
||||
is_boot_data_valid = BOOT_DATA_VALID;
|
||||
}
|
||||
}
|
||||
|
||||
void tfm_core_get_boot_data_handler(uint32_t args[])
|
||||
{
|
||||
uint8_t tlv_major = (uint8_t)args[0];
|
||||
uint8_t *buf_start = (uint8_t *)args[1];
|
||||
uint16_t buf_size = (uint16_t)args[2];
|
||||
uint8_t *ptr;
|
||||
struct tfm_boot_data *boot_data;
|
||||
struct shared_data_tlv_entry tlv_entry;
|
||||
uintptr_t tlv_end, offset;
|
||||
#ifndef TFM_PSA_API
|
||||
uint32_t running_partition_idx =
|
||||
tfm_spm_partition_get_running_partition_idx();
|
||||
uint32_t res;
|
||||
#else
|
||||
struct tfm_spm_ipc_partition_t *partition = NULL;
|
||||
uint32_t privileged;
|
||||
#endif
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
/* Make sure that the output pointer points to a memory area that is owned
|
||||
* by the partition
|
||||
*/
|
||||
res = tfm_core_check_buffer_access(running_partition_idx,
|
||||
(void *)buf_start,
|
||||
buf_size,
|
||||
2); /* Check 4 bytes alignment */
|
||||
if (!res) {
|
||||
/* Not in accessible range, return error */
|
||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
partition = tfm_spm_get_running_partition();
|
||||
if (!partition) {
|
||||
tfm_panic();
|
||||
}
|
||||
privileged = tfm_spm_partition_get_privileged_mode(partition->index);
|
||||
|
||||
if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
|
||||
privileged) != IPC_SUCCESS) {
|
||||
/* Not in accessible range, return error */
|
||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FixMe: Check whether caller has access right to given tlv_major_type */
|
||||
|
||||
if (is_boot_data_valid != BOOT_DATA_VALID) {
|
||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the boundaries of TLV section */
|
||||
boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
|
||||
tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
|
||||
offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
|
||||
|
||||
/* Add header to output buffer as well */
|
||||
if (buf_size < SHARED_DATA_HEADER_SIZE) {
|
||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
} else {
|
||||
boot_data = (struct tfm_boot_data *)buf_start;
|
||||
boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
|
||||
boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
|
||||
ptr = boot_data->data;
|
||||
}
|
||||
|
||||
/* Iterates over the TLV section and copy TLVs with requested major
|
||||
* type to the provided buffer.
|
||||
*/
|
||||
for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
|
||||
/* Create local copy to avoid unaligned access */
|
||||
tfm_memcpy(&tlv_entry,
|
||||
(const void *)offset,
|
||||
SHARED_DATA_ENTRY_HEADER_SIZE);
|
||||
if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
|
||||
/* Check buffer overflow */
|
||||
if (((ptr - buf_start) + tlv_entry.tlv_len) > buf_size) {
|
||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
tfm_memcpy(ptr, (const void *)offset, tlv_entry.tlv_len);
|
||||
|
||||
ptr += tlv_entry.tlv_len;
|
||||
boot_data->header.tlv_tot_len += tlv_entry.tlv_len;
|
||||
}
|
||||
}
|
||||
args[0] = TFM_SUCCESS;
|
||||
return;
|
||||
}
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "region_defs.h"
|
||||
#include "tfm_core.h"
|
||||
#include "tfm_internal.h"
|
||||
#include "tfm_api.h"
|
||||
#include "platform/include/tfm_spm_hal.h"
|
||||
#include "secure_utilities.h"
|
||||
#include "secure_fw/spm/spm_api.h"
|
||||
#include "secure_fw/include/tfm_spm_services_api.h"
|
||||
#ifdef TFM_PSA_API
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "tfm_thread.h"
|
||||
#include "tfm_wait.h"
|
||||
#include "tfm_message_queue.h"
|
||||
#include "tfm_spm.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Avoids the semihosting issue
|
||||
* FixMe: describe 'semihosting issue'
|
||||
*/
|
||||
#if defined(__ARMCC_VERSION)
|
||||
__asm(" .global __ARM_use_no_argv\n");
|
||||
#endif
|
||||
|
||||
#if defined ( __GNUC__ )
|
||||
/* The macro cmse_nsfptr_create defined in the gcc library uses the non-standard
|
||||
* gcc C lanuage extension 'typeof'. TF-M is built with '-std=c99' so typeof
|
||||
* cannot be used in the code. As a workaround cmse_nsfptr_create is redefined
|
||||
* here to use only standard language elements. */
|
||||
#undef cmse_nsfptr_create
|
||||
#define cmse_nsfptr_create(p) ((intptr_t) (p) & ~1)
|
||||
#endif
|
||||
|
||||
#ifndef TFM_LVL
|
||||
#error TFM_LVL is not defined!
|
||||
#endif
|
||||
#if (TFM_LVL != 1) && (TFM_LVL != 2) && (TFM_LVL != 3)
|
||||
#error Only TFM_LVL 1, 2 and 3 are supported!
|
||||
#endif
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
/* Macros to pick linker symbols and allow to form the partition data base */
|
||||
#define REGION(a, b, c) a##b##c
|
||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
|
||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
|
||||
|
||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
|
||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
|
||||
#endif
|
||||
|
||||
void configure_ns_code(void)
|
||||
{
|
||||
/* SCB_NS.VTOR points to the Non-secure vector table base address */
|
||||
SCB_NS->VTOR = tfm_spm_hal_get_ns_VTOR();
|
||||
|
||||
/* Setups Main stack pointer of the non-secure code */
|
||||
uint32_t ns_msp = tfm_spm_hal_get_ns_MSP();
|
||||
|
||||
__TZ_set_MSP_NS(ns_msp);
|
||||
|
||||
/* Get the address of non-secure code entry point to jump there */
|
||||
uint32_t entry_ptr = tfm_spm_hal_get_ns_entry_point();
|
||||
|
||||
/* Clears LSB of the function address to indicate the function-call
|
||||
* will perform the switch from secure to non-secure
|
||||
*/
|
||||
ns_entry = (nsfptr_t) cmse_nsfptr_create(entry_ptr);
|
||||
}
|
||||
|
||||
int32_t tfm_core_init(void)
|
||||
{
|
||||
/* Enables fault handlers */
|
||||
enable_fault_handlers();
|
||||
|
||||
/* Configures the system reset request properties */
|
||||
system_reset_cfg();
|
||||
|
||||
/* Configures debug authentication */
|
||||
tfm_spm_hal_init_debug();
|
||||
|
||||
__enable_irq();
|
||||
|
||||
LOG_MSG("Secure image initializing!");
|
||||
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
printf("TFM level is: %d\r\n", TFM_LVL);
|
||||
#endif
|
||||
|
||||
tfm_core_validate_boot_data();
|
||||
|
||||
tfm_spm_hal_init_isolation_hw();
|
||||
|
||||
configure_ns_code();
|
||||
|
||||
/* Configures all interrupts to retarget NS state, except for
|
||||
* secure peripherals
|
||||
*/
|
||||
nvic_interrupt_target_state_cfg();
|
||||
/* Enable secure peripherals interrupts */
|
||||
nvic_interrupt_enable();
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
/* FixMe: In case of IPC messaging, scratch area must not be referenced
|
||||
* These variables should be removed when all obsolete references are
|
||||
* removed from the codebase
|
||||
*/
|
||||
tfm_scratch_area = NULL;
|
||||
tfm_scratch_area_size = 0;
|
||||
#else
|
||||
tfm_scratch_area =
|
||||
(uint8_t *)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
|
||||
tfm_scratch_area_size =
|
||||
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit) -
|
||||
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tfm_core_set_secure_exception_priorities(void)
|
||||
{
|
||||
uint32_t VECTKEY;
|
||||
SCB_Type *scb = SCB;
|
||||
uint32_t AIRCR;
|
||||
|
||||
/* Set PRIS flag is AIRCR */
|
||||
AIRCR = scb->AIRCR;
|
||||
VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
|
||||
scb->AIRCR = SCB_AIRCR_PRIS_Msk |
|
||||
VECTKEY |
|
||||
(AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
|
||||
|
||||
/* FixMe: Explicitly set secure fault and Secure SVC priority to highest */
|
||||
|
||||
/*
|
||||
* Set secure PendSV priority to the lowest in SECURE state.
|
||||
*
|
||||
* IMPORTANT NOTE:
|
||||
*
|
||||
* Although the priority of the secure PendSV must be the lowest possible
|
||||
* among other interrupts in the Secure state, it must be ensured that
|
||||
* PendSV is not preempted nor masked by Non-Secure interrupts to ensure
|
||||
* the integrity of the Secure operation.
|
||||
* When AIRCR.PRIS is set, the Non-Secure execution can act on
|
||||
* FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
|
||||
* number up to the value 0x80.
|
||||
* For this reason, set the priority of the PendSV interrupt to the next
|
||||
* priority level configurable on the platform, just below 0x80.
|
||||
*/
|
||||
NVIC_SetPriority(PendSV_IRQn, (1 << (__NVIC_PRIO_BITS - 1)) - 1);
|
||||
|
||||
return TFM_SUCCESS;
|
||||
}
|
||||
|
||||
void tfm_core_spm_request_handler(const struct tfm_exc_stack_t *svc_ctx)
|
||||
{
|
||||
uint32_t *res_ptr = (uint32_t *)&svc_ctx->R0;
|
||||
|
||||
/* FixMe: check if caller partition is permitted to make an SPM request */
|
||||
|
||||
switch (svc_ctx->R0) {
|
||||
case TFM_SPM_REQUEST_RESET_VOTE:
|
||||
/* FixMe: this is a placeholder for checks to be performed before
|
||||
* allowing execution of reset
|
||||
*/
|
||||
*res_ptr = TFM_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
*res_ptr = TFM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (tfm_core_init() != 0) {
|
||||
/* Placeholder for error handling, currently ignored. */
|
||||
}
|
||||
|
||||
if (tfm_spm_db_init() != SPM_ERR_OK) {
|
||||
/* Placeholder for error handling, currently ignored. */
|
||||
}
|
||||
|
||||
tfm_spm_hal_setup_isolation_hw();
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING);
|
||||
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
|
||||
uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
|
||||
|
||||
__set_PSPLIM(psp_stack_bottom);
|
||||
|
||||
if (tfm_spm_partition_init() != SPM_ERR_OK) {
|
||||
/* Certain systems might refuse to boot altogether if partitions fail
|
||||
* to initialize. This is a placeholder for such an error handler
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Prioritise secure exceptions to avoid NS being able to pre-empt
|
||||
* secure SVC or SecureFault. Do it before PSA API initialization.
|
||||
*/
|
||||
tfm_core_set_secure_exception_priorities();
|
||||
|
||||
/* We close the TFM_SP_CORE_ID partition, because its only purpose is
|
||||
* to be able to pass the state checks for the tests started from secure.
|
||||
*/
|
||||
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_CLOSED);
|
||||
tfm_spm_partition_set_state(TFM_SP_NON_SECURE_ID,
|
||||
SPM_PARTITION_STATE_RUNNING);
|
||||
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
/* Jumps to non-secure code */
|
||||
LOG_MSG("Jumping to non-secure code...");
|
||||
#endif
|
||||
|
||||
jump_to_ns_code();
|
||||
#else
|
||||
/*
|
||||
* Prioritise secure exceptions to avoid NS being able to pre-empt
|
||||
* secure SVC or SecureFault. Do it before PSA API initialization.
|
||||
*/
|
||||
tfm_core_set_secure_exception_priorities();
|
||||
tfm_spm_init();
|
||||
#endif
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_CORE_H__
|
||||
#define __TFM_CORE_H__
|
||||
|
||||
#include <arm_cmse.h>
|
||||
#include "tfm_svc.h"
|
||||
#include "secure_utilities.h"
|
||||
|
||||
extern uint32_t tfm_scratch_area_size;
|
||||
extern uint8_t *tfm_scratch_area;
|
||||
|
||||
#endif /* __TFM_CORE_H__ */
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "secure_utilities.h"
|
||||
#include "tfm_svc.h"
|
||||
#include "tfm_secure_api.h"
|
||||
#include "region_defs.h"
|
||||
#include "tfm_api.h"
|
||||
#include "tfm_internal.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
#ifdef TFM_PSA_API
|
||||
#include <stdbool.h>
|
||||
#include "tfm_svcalls.h"
|
||||
#endif
|
||||
#include "platform/mbed_toolchain.h"
|
||||
|
||||
/* This SVC handler is called when a secure partition requests access to a
|
||||
* buffer area
|
||||
*/
|
||||
extern int32_t tfm_core_set_buffer_area_handler(const uint32_t args[]);
|
||||
#ifdef TFM_PSA_API
|
||||
extern void tfm_psa_ipc_request_handler(const uint32_t svc_args[]);
|
||||
#endif
|
||||
|
||||
struct tfm_fault_context_s {
|
||||
uint32_t R0;
|
||||
uint32_t R1;
|
||||
uint32_t R2;
|
||||
uint32_t R3;
|
||||
uint32_t R12;
|
||||
uint32_t LR;
|
||||
uint32_t ReturnAddress;
|
||||
uint32_t RETPSR;
|
||||
} tfm_fault_context;
|
||||
|
||||
#if defined(__ARM_ARCH_8M_MAIN__)
|
||||
/**
|
||||
* \brief Overwrites default Secure fault handler.
|
||||
*/
|
||||
void SecureFault_Handler(void)
|
||||
{
|
||||
/* figure out context from which we landed in fault handler */
|
||||
uint32_t lr = __get_LR();
|
||||
uint32_t sp;
|
||||
|
||||
if (lr & EXC_RETURN_SECURE_STACK) {
|
||||
if (lr & EXC_RETURN_STACK_PROCESS) {
|
||||
sp = __get_PSP();
|
||||
} else {
|
||||
sp = __get_MSP();
|
||||
}
|
||||
} else {
|
||||
if (lr & EXC_RETURN_STACK_PROCESS) {
|
||||
sp = __TZ_get_PSP_NS();
|
||||
} else {
|
||||
sp = __TZ_get_MSP_NS();
|
||||
}
|
||||
}
|
||||
|
||||
/* Only save the context if sp is valid */
|
||||
if ((sp >= S_DATA_START &&
|
||||
sp <= (S_DATA_LIMIT - sizeof(tfm_fault_context)) + 1) ||
|
||||
(sp >= NS_DATA_START &&
|
||||
sp <= (NS_DATA_LIMIT - sizeof(tfm_fault_context)) + 1)) {
|
||||
tfm_memcpy(&tfm_fault_context,
|
||||
(const void *)sp,
|
||||
sizeof(tfm_fault_context));
|
||||
}
|
||||
|
||||
LOG_MSG("Oops... Secure fault!!! You're not going anywhere!");
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
#elif defined(__ARM_ARCH_8M_BASE__)
|
||||
/**
|
||||
* \brief Overwrites default Hard fault handler.
|
||||
*
|
||||
* In case of a baseline implementation fault conditions that would generate a
|
||||
* SecureFault in a mainline implementation instead generate a Secure HardFault.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
{
|
||||
/* In a baseline implementation there is no way, to find out whether this is
|
||||
* a hard fault triggered directly, or another fault that has been
|
||||
* escalated.
|
||||
*/
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "Unsupported ARM Architecture."
|
||||
#endif
|
||||
|
||||
#if defined(__ARM_ARCH_8M_MAIN__)
|
||||
__attribute__((naked)) void SVC_Handler(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"TST lr, #4\n" /* Check store SP in thread mode to r0 */
|
||||
"IT EQ\n"
|
||||
"BXEQ lr\n"
|
||||
"MRS r0, PSP\n"
|
||||
"MOV r1, lr\n"
|
||||
"BL SVCHandler_main\n"
|
||||
"BX r0\n"
|
||||
);
|
||||
}
|
||||
#elif defined(__ARM_ARCH_8M_BASE__)
|
||||
__attribute__((naked)) void SVC_Handler(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
".syntax unified\n"
|
||||
"MOVS r0, #4\n" /* Check store SP in thread mode to r0 */
|
||||
"MOV r1, lr\n"
|
||||
"TST r0, r1\n"
|
||||
"BEQ handler\n"
|
||||
"MRS r0, PSP\n" /* Coming from thread mode */
|
||||
"B sp_stored\n"
|
||||
"handler:\n"
|
||||
"BX lr\n" /* Coming from handler mode */
|
||||
"sp_stored:\n"
|
||||
"MOV r1, lr\n"
|
||||
"BL SVCHandler_main\n"
|
||||
"BX r0\n"
|
||||
);
|
||||
}
|
||||
#else
|
||||
#error "Unsupported ARM Architecture."
|
||||
#endif
|
||||
|
||||
MBED_USED uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr)
|
||||
{
|
||||
uint8_t svc_number;
|
||||
/*
|
||||
* Stack contains:
|
||||
* r0, r1, r2, r3, r12, r14 (lr), the return address and xPSR
|
||||
* First argument (r0) is svc_args[0]
|
||||
*/
|
||||
if (lr & EXC_RETURN_SECURE_STACK) {
|
||||
/* SV called directly from secure context. Check instruction for
|
||||
* svc_number
|
||||
*/
|
||||
svc_number = ((uint8_t *)svc_args[6])[-2];
|
||||
} else {
|
||||
/* Secure SV executing with NS return.
|
||||
* NS cannot directly trigger S SVC so this should not happen
|
||||
* FixMe: check for security implications
|
||||
*/
|
||||
return lr;
|
||||
}
|
||||
switch (svc_number) {
|
||||
#ifdef TFM_PSA_API
|
||||
case TFM_SVC_IPC_REQUEST:
|
||||
tfm_psa_ipc_request_handler(svc_args);
|
||||
break;
|
||||
case TFM_SVC_SCHEDULE:
|
||||
case TFM_SVC_EXIT_THRD:
|
||||
case TFM_SVC_PSA_FRAMEWORK_VERSION:
|
||||
case TFM_SVC_PSA_VERSION:
|
||||
case TFM_SVC_PSA_CONNECT:
|
||||
case TFM_SVC_PSA_CALL:
|
||||
case TFM_SVC_PSA_CLOSE:
|
||||
case TFM_SVC_PSA_WAIT:
|
||||
case TFM_SVC_PSA_GET:
|
||||
case TFM_SVC_PSA_SET_RHANDLE:
|
||||
case TFM_SVC_PSA_READ:
|
||||
case TFM_SVC_PSA_SKIP:
|
||||
case TFM_SVC_PSA_WRITE:
|
||||
case TFM_SVC_PSA_REPLY:
|
||||
case TFM_SVC_PSA_NOTIFY:
|
||||
case TFM_SVC_PSA_CLEAR:
|
||||
case TFM_SVC_PSA_EOI:
|
||||
svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr);
|
||||
break;
|
||||
#else
|
||||
case TFM_SVC_SFN_REQUEST:
|
||||
lr = tfm_core_partition_request_svc_handler(svc_args, lr);
|
||||
break;
|
||||
case TFM_SVC_SFN_RETURN:
|
||||
lr = tfm_core_partition_return_handler(lr);
|
||||
break;
|
||||
case TFM_SVC_VALIDATE_SECURE_CALLER:
|
||||
tfm_core_validate_secure_caller_handler(svc_args);
|
||||
break;
|
||||
case TFM_SVC_GET_CALLER_CLIENT_ID:
|
||||
tfm_core_get_caller_client_id_handler(svc_args);
|
||||
break;
|
||||
case TFM_SVC_SPM_REQUEST:
|
||||
tfm_core_spm_request_handler((struct tfm_exc_stack_t *)svc_args);
|
||||
break;
|
||||
case TFM_SVC_MEMORY_CHECK:
|
||||
tfm_core_memory_permission_check_handler(svc_args);
|
||||
break;
|
||||
case TFM_SVC_SET_SHARE_AREA:
|
||||
tfm_core_set_buffer_area_handler(svc_args);
|
||||
break;
|
||||
#endif
|
||||
case TFM_SVC_PRINT:
|
||||
printf("\e[1;34m[Sec Thread] %s\e[0m\r\n", (char *)svc_args[0]);
|
||||
break;
|
||||
case TFM_SVC_GET_BOOT_DATA:
|
||||
tfm_core_get_boot_data_handler(svc_args);
|
||||
break;
|
||||
default:
|
||||
LOG_MSG("Unknown SVC number requested!");
|
||||
break;
|
||||
}
|
||||
|
||||
return lr;
|
||||
}
|
||||
|
||||
void tfm_access_violation_handler(void)
|
||||
{
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include "secure_utilities.h"
|
||||
|
||||
#ifndef __TFM_INTERNAL_H__
|
||||
#define __TFM_INTERNAL_H__
|
||||
|
||||
/*
|
||||
* This function pointer is meant to only hold non secure function pointers.
|
||||
* It will be turned into a non-secure one (LSB cleared) before being called
|
||||
* whatever happens anyway (unless cast to another function pointer type).
|
||||
* Registers will be cleared before branching so that no information leaks
|
||||
* from secure to non-secure world.
|
||||
*/
|
||||
typedef void __attribute__((cmse_nonsecure_call)) (*nsfptr_t) (void);
|
||||
|
||||
extern nsfptr_t ns_entry;
|
||||
|
||||
/**
|
||||
* \brief Signal that secure partition initialisation is finished
|
||||
*/
|
||||
void tfm_secure_api_init_done(void);
|
||||
|
||||
/**
|
||||
* \brief Jumps to non-secure code.
|
||||
*/
|
||||
void jump_to_ns_code(void);
|
||||
|
||||
/**
|
||||
* \brief Called if veneer is running in thread mode
|
||||
*/
|
||||
uint32_t tfm_core_partition_request_svc_handler(
|
||||
const uint32_t *svc_args, uint32_t lr);
|
||||
|
||||
/**
|
||||
* \brief Called when secure service returns
|
||||
*/
|
||||
uint32_t tfm_core_partition_return_handler(uint32_t lr);
|
||||
|
||||
/**
|
||||
* \brief Called by secure service to check if client is secure
|
||||
*/
|
||||
void tfm_core_validate_secure_caller_handler(const uint32_t svc_args[]);
|
||||
|
||||
/**
|
||||
* \brief Stores caller's client id in state context
|
||||
*/
|
||||
void tfm_core_get_caller_client_id_handler(const uint32_t svc_args[]);
|
||||
|
||||
/**
|
||||
* \brief Checks if a secure service's access to a memory location is permitted
|
||||
*/
|
||||
void tfm_core_memory_permission_check_handler(const uint32_t svc_args[]);
|
||||
|
||||
/**
|
||||
* \brief Handle an SPM request by a secure service
|
||||
*/
|
||||
void tfm_core_spm_request_handler(const struct tfm_exc_stack_t *svc_ctx);
|
||||
|
||||
/**
|
||||
* \brief Check whether a buffer is ok for writing to by the privileged API
|
||||
* function.
|
||||
*
|
||||
* This function checks whether the caller partition owns the buffer, can write
|
||||
* to it, and the buffer has proper alignment.
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] start_addr The start address of the buffer
|
||||
* \param[in] len The length of the buffer
|
||||
* \param[in] alignment The expected alignment (in bits)
|
||||
*
|
||||
* \return 1 if the check passes, 0 otherwise.
|
||||
*
|
||||
* \note For a 0 long buffer the check fails.
|
||||
*/
|
||||
int32_t tfm_core_check_buffer_access(uint32_t partition_idx,
|
||||
void *start_addr,
|
||||
size_t len,
|
||||
uint32_t alignment);
|
||||
|
||||
/**
|
||||
* \brief Retrieve secure partition related data from shared memory area, which
|
||||
* stores shared data between bootloader and runtime firmware.
|
||||
*
|
||||
* \param[in] args Pointer to stack frame, which carries input parameters.
|
||||
*/
|
||||
void tfm_core_get_boot_data_handler(uint32_t args[]);
|
||||
|
||||
/**
|
||||
* \brief Validate the content of shared memory area, which stores the shared
|
||||
* data between bootloader and runtime firmware.
|
||||
*/
|
||||
void tfm_core_validate_boot_data(void);
|
||||
|
||||
#endif /* __TFM_INTERNAL_H__ */
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_MEMORY_UTILS_H__
|
||||
#define __TFM_MEMORY_UTILS_H__
|
||||
|
||||
#include <string.h>
|
||||
#include "cmsis_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* FIXME: The following functions are wrappers around standard C library
|
||||
* functions: memcpy, memcmp, memset
|
||||
* In long term standard C library might be removed from TF-M project or
|
||||
* replaced with a secure implementation due to security concerns.
|
||||
*/
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
void *tfm_memcpy(void *dest, const void *src, size_t num)
|
||||
{
|
||||
return (memcpy(dest, src, num));
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
int tfm_memcmp(const void *ptr1, const void *ptr2, size_t num)
|
||||
{
|
||||
return (memcmp(ptr1, ptr2, num));
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
void *tfm_memset(void *ptr, int value, size_t num)
|
||||
{
|
||||
return (memset(ptr, value, num));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TFM_MEMORY_UTILS_H__ */
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "secure_utilities.h"
|
||||
#include "tfm_api.h"
|
||||
#ifdef TFM_PSA_API
|
||||
#include "tfm_utils.h"
|
||||
#include "tfm_internal.h"
|
||||
#endif
|
||||
|
||||
#ifndef TFM_MAX_NS_THREAD_COUNT
|
||||
#define TFM_MAX_NS_THREAD_COUNT 8
|
||||
#endif
|
||||
#define INVALID_CLIENT_ID 0
|
||||
|
||||
#define DEFAULT_NS_CLIENT_ID ((int32_t)-1)
|
||||
|
||||
#define INVALID_NS_CLIENT_IDX (-1)
|
||||
#define DEFAULT_NS_CLIENT_IDX 0
|
||||
|
||||
typedef uint32_t TZ_ModuleId_t;
|
||||
typedef uint32_t TZ_MemoryId_t;
|
||||
|
||||
static struct ns_client_list_t {
|
||||
int32_t ns_client_id;
|
||||
int32_t next_free_index;
|
||||
} NsClientIdList[TFM_MAX_NS_THREAD_COUNT];
|
||||
|
||||
static int32_t free_index = 0U;
|
||||
static int32_t active_ns_client_idx = INVALID_NS_CLIENT_IDX;
|
||||
|
||||
static int get_next_ns_client_id()
|
||||
{
|
||||
#ifdef TFM_NS_CLIENT_IDENTIFICATION
|
||||
static int32_t next_ns_client_id = DEFAULT_NS_CLIENT_ID;
|
||||
|
||||
if (next_ns_client_id > 0)
|
||||
{
|
||||
next_ns_client_id = DEFAULT_NS_CLIENT_ID;
|
||||
}
|
||||
return next_ns_client_id--;
|
||||
#else
|
||||
return DEFAULT_NS_CLIENT_ID;
|
||||
#endif
|
||||
}
|
||||
|
||||
void tfm_nspm_configure_clients(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
/* Default to one NS client */
|
||||
free_index = 1;
|
||||
NsClientIdList[0].ns_client_id = get_next_ns_client_id();
|
||||
for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
|
||||
NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
|
||||
}
|
||||
active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
|
||||
}
|
||||
|
||||
int32_t tfm_nspm_get_current_client_id()
|
||||
{
|
||||
if (active_ns_client_idx == INVALID_NS_CLIENT_IDX)
|
||||
{
|
||||
return 0;
|
||||
} else {
|
||||
return NsClientIdList[active_ns_client_idx].ns_client_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* TF-M implementation of the CMSIS TZ RTOS thread context management API */
|
||||
|
||||
/// Initialize secure context memory system
|
||||
/// \return execution status (1: success, 0: error)
|
||||
/* This veneer is TF-M internal, not a secure service */
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
uint32_t TZ_InitContextSystem_S(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
/* NS RTOS supports TZ context management, override defaults */
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
LOG_MSG("NS RTOS initialized TZ RTOS context management");
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
|
||||
NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
|
||||
NsClientIdList[i].next_free_index = i + 1;
|
||||
}
|
||||
|
||||
/* Terminate list */
|
||||
NsClientIdList[i - 1].next_free_index = INVALID_NS_CLIENT_IDX;
|
||||
/* Success */
|
||||
return 1U;
|
||||
}
|
||||
|
||||
|
||||
/// Allocate context memory for calling secure software modules in TrustZone
|
||||
/// \param[in] module identifies software modules called from non-secure mode
|
||||
/// \return value != 0 id TrustZone memory slot identifier
|
||||
/// \return value 0 no memory available or internal error
|
||||
/* This veneer is TF-M internal, not a secure service */
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module)
|
||||
{
|
||||
TZ_MemoryId_t tz_id;
|
||||
(void) module; /* Currently unused */
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (free_index < 0) {
|
||||
/* No more free slots */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
/* TZ_MemoryId_t must be a positive integer */
|
||||
tz_id = (TZ_MemoryId_t)free_index + 1;
|
||||
NsClientIdList[free_index].ns_client_id = get_next_ns_client_id();
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("TZ_AllocModuleContext_S called, returning id %d\r\n",
|
||||
NsClientIdList[free_index].ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
free_index = NsClientIdList[free_index].next_free_index;
|
||||
|
||||
return tz_id;
|
||||
}
|
||||
|
||||
|
||||
/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
|
||||
/// \param[in] id TrustZone memory slot identifier
|
||||
/// \return execution status (1: success, 0: error)
|
||||
/* This veneer is TF-M internal, not a secure service */
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
|
||||
/* Invalid TZ_MemoryId_t */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
index = id - 1;
|
||||
|
||||
if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
|
||||
/* Non-existent client */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("TZ_FreeModuleContext_S called for id %d\r\n",
|
||||
NsClientIdList[index].ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
if (active_ns_client_idx == index) {
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("Freeing active NS client, NS inactive\r\n");
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
|
||||
}
|
||||
NsClientIdList[index].ns_client_id = INVALID_CLIENT_ID;
|
||||
NsClientIdList[index].next_free_index = free_index;
|
||||
|
||||
free_index = index;
|
||||
|
||||
return 1U; // Success
|
||||
}
|
||||
|
||||
|
||||
/// Load secure context (called on RTOS thread context switch)
|
||||
/// \param[in] id TrustZone memory slot identifier
|
||||
/// \return execution status (1: success, 0: error)
|
||||
/* This veneer is TF-M internal, not a secure service */
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
uint32_t TZ_LoadContext_S (TZ_MemoryId_t id)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
LOG_MSG("TZ_LoadContext_S called");
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
|
||||
/* Invalid TZ_MemoryId_t */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
index = id - 1;
|
||||
|
||||
if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
|
||||
/* Non-existent client */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
active_ns_client_idx = index;
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("TZ_LoadContext_S called for id %d\r\n",
|
||||
NsClientIdList[index].ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
|
||||
return 1U; // Success
|
||||
}
|
||||
|
||||
|
||||
/// Store secure context (called on RTOS thread context switch)
|
||||
/// \param[in] id TrustZone memory slot identifier
|
||||
/// \return execution status (1: success, 0: error)
|
||||
/* This veneer is TF-M internal, not a secure service */
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
uint32_t TZ_StoreContext_S (TZ_MemoryId_t id)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
LOG_MSG("TZ_StoreContext_S called");
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
/* id corresponds to context being swapped out on NS side */
|
||||
if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
|
||||
/* Invalid TZ_MemoryId_t */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
index = id - 1;
|
||||
|
||||
if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
|
||||
/* Non-existent client */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (active_ns_client_idx != index) {
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("TZ_StoreContext_S called for id %d, active id: %d\r\n",
|
||||
NsClientIdList[index].ns_client_id,
|
||||
NsClientIdList[active_ns_client_idx].ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("TZ_StoreContext_S called for id %d\r\n",
|
||||
NsClientIdList[index].ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
|
||||
|
||||
return 1U; // Success
|
||||
}
|
||||
|
||||
#ifdef TFM_NS_CLIENT_IDENTIFICATION
|
||||
__attribute__((cmse_nonsecure_entry))
|
||||
enum tfm_status_e tfm_register_client_id (int32_t ns_client_id)
|
||||
{
|
||||
int current_client_id;
|
||||
|
||||
if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
|
||||
/* This veneer should only be called by NS RTOS in handler mode */
|
||||
return TFM_ERROR_NS_THREAD_MODE_CALL;
|
||||
}
|
||||
|
||||
if (ns_client_id >= 0) {
|
||||
/* The client ID is invalid */
|
||||
return TFM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (active_ns_client_idx < 0) {
|
||||
/* No client is active */
|
||||
return TFM_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
current_client_id = NsClientIdList[active_ns_client_idx].ns_client_id;
|
||||
if (current_client_id >= 0 ) {
|
||||
/* The client ID is invalid */
|
||||
return TFM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NsClientIdList[active_ns_client_idx].ns_client_id = ns_client_id;
|
||||
#ifdef PRINT_NSPM_DEBUG
|
||||
printf("tfm_register_client_id called with id %d\r\n", ns_client_id);
|
||||
#endif /* PRINT_NSPM_DEBUG */
|
||||
|
||||
return TFM_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
__attribute__((section("SFN")))
|
||||
psa_status_t tfm_nspm_thread_entry(void)
|
||||
{
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
/* Jumps to non-secure code */
|
||||
LOG_MSG("Jumping to non-secure code...");
|
||||
#endif
|
||||
|
||||
jump_to_ns_code();
|
||||
|
||||
/* Should not run here */
|
||||
TFM_ASSERT(false);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
#endif
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_NSPM_H__
|
||||
#define __TFM_NSPM_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \brief initialise the NS context database
|
||||
*/
|
||||
void tfm_nspm_configure_clients(void);
|
||||
|
||||
/**
|
||||
* \brief Get the client ID of the current NS client
|
||||
*
|
||||
* \return The client id of the current NS client. 0 (invalid client id) is
|
||||
* returned in case of error.
|
||||
*/
|
||||
int32_t tfm_nspm_get_current_client_id(void);
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
/**
|
||||
* \brief NSPM thread main entry function
|
||||
*
|
||||
* \return PSA_SUCCESS indicates failed.
|
||||
*
|
||||
* Note: This function should not return back.
|
||||
*/
|
||||
psa_status_t tfm_nspm_thread_entry(void);
|
||||
#endif
|
||||
|
||||
#endif /* __TFM_NSPM_H__ */
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_PLATFORM_CORE_API_H__
|
||||
#define __TFM_PLATFORM_CORE_API_H__
|
||||
|
||||
/**
|
||||
* \brief Should be called in case of access violation.
|
||||
*
|
||||
* There might be platform specific means, by which it is possible on a
|
||||
* subsystem to detect access violation. For example a platform can have a
|
||||
* Peripheral Protection Controller, to detect unauthorised accesses to
|
||||
* peripheral registers. Setting up the protection, and handling the violation
|
||||
* is implemented in platform specific code. However TF-M should be able to
|
||||
* decide how to proceed if a violation happens. So to notify TF-M, platform
|
||||
* code have to call this function, if a violation happens.
|
||||
*/
|
||||
void tfm_access_violation_handler(void);
|
||||
|
||||
#endif /* __TFM_PLATFORM_CORE_API_H__ */
|
|
@ -1,176 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <arm_cmse.h>
|
||||
#include "tfm_secure_api.h"
|
||||
#include "tfm_nspm.h"
|
||||
#include "secure_utilities.h"
|
||||
#include "secure_fw/spm/spm_api.h"
|
||||
#include "region_defs.h"
|
||||
#include "tfm_api.h"
|
||||
|
||||
#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
|
||||
|
||||
#ifndef TFM_LVL
|
||||
#error TFM_LVL is not defined!
|
||||
#endif
|
||||
|
||||
/* Macros to pick linker symbols and allow references to sections */
|
||||
#define REGION(a, b, c) a##b##c
|
||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
|
||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
|
||||
|
||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
|
||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
|
||||
REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
/* This is the "Big Lock" on the secure side, to guarantee single entry
|
||||
* to SPE
|
||||
*/
|
||||
int32_t tfm_secure_lock;
|
||||
|
||||
/**
|
||||
* \brief Check whether a memory range is inside a memory region.
|
||||
*
|
||||
* \param[in] p The start address of the range to check
|
||||
* \param[in] s The size of the range to check
|
||||
* \param[in] region_start The start address of the region, which should
|
||||
* contain the range
|
||||
* \param[in] region_len The size of the region, which should contain the
|
||||
* range
|
||||
*
|
||||
* \return TFM_SUCCESS if the region contains the range,
|
||||
* TFM_ERROR_GENERIC otherwise.
|
||||
*/
|
||||
static int32_t check_address_range(const void *p, size_t s,
|
||||
uintptr_t region_start, uint32_t region_len)
|
||||
{
|
||||
int32_t range_in_region;
|
||||
|
||||
/* Check for overflow in the range parameters */
|
||||
if ((uintptr_t)p > UINTPTR_MAX-s) {
|
||||
return TFM_ERROR_GENERIC;
|
||||
}
|
||||
|
||||
/* We trust the region parameters, and don't check for overflow */
|
||||
|
||||
/* Calculate the result */
|
||||
range_in_region = ((uintptr_t)p >= region_start) &&
|
||||
((uintptr_t)p+s <= region_start+region_len);
|
||||
if (range_in_region) {
|
||||
return TFM_SUCCESS;
|
||||
} else {
|
||||
return TFM_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check whether the current partition has access to a memory range
|
||||
*
|
||||
* This function assumes, that the current MPU configuration is set for the
|
||||
* partition to be checked. The flags should contain information of the
|
||||
* execution mode of the partition code (priv/unpriv), and access type
|
||||
* (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
|
||||
* Development Tools" chapter "Address range check intrinsic"
|
||||
*
|
||||
* \param[in] p The start address of the range to check
|
||||
* \param[in] s The size of the range to check
|
||||
* \param[in] flags The flags to pass to the cmse_check_address_range func
|
||||
*
|
||||
* \return TFM_SUCCESS if the partition has access to the memory range,
|
||||
* TFM_ERROR_GENERIC otherwise.
|
||||
*/
|
||||
static int32_t has_access_to_region(const void *p, size_t s, int flags)
|
||||
{
|
||||
int32_t range_access_allowed_by_mpu;
|
||||
|
||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
|
||||
uint32_t scratch_base =
|
||||
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
|
||||
uint32_t scratch_limit =
|
||||
(uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
/* Use the TT instruction to check access to the partition's regions*/
|
||||
range_access_allowed_by_mpu =
|
||||
cmse_check_address_range((void *)p, s, flags) != NULL;
|
||||
|
||||
if (range_access_allowed_by_mpu) {
|
||||
return TFM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
|
||||
/* If the check for the current MPU settings fails, check for the share
|
||||
* region, only if the partition is secure
|
||||
*/
|
||||
if ((flags & CMSE_NONSECURE) == 0) {
|
||||
if (check_address_range(p, s, scratch_base,
|
||||
scratch_limit+1-scratch_base) == TFM_SUCCESS) {
|
||||
return TFM_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
/* If all else fails, check whether the region is in the non-secure
|
||||
* memory
|
||||
*/
|
||||
if (check_address_range(p, s, NS_CODE_START,
|
||||
NS_CODE_LIMIT+1-NS_CODE_START) == TFM_SUCCESS ||
|
||||
check_address_range(p, s, NS_DATA_START,
|
||||
NS_DATA_LIMIT+1-NS_DATA_START) == TFM_SUCCESS) {
|
||||
return TFM_SUCCESS;
|
||||
} else {
|
||||
return TFM_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
|
||||
uint32_t ns_caller,
|
||||
uint32_t privileged)
|
||||
{
|
||||
int flags = CMSE_MPU_READ;
|
||||
|
||||
if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
|
||||
flags |= CMSE_MPU_UNPRIV;
|
||||
}
|
||||
|
||||
if (ns_caller) {
|
||||
flags |= CMSE_NONSECURE;
|
||||
}
|
||||
|
||||
return has_access_to_region(p, s, flags);
|
||||
}
|
||||
|
||||
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
|
||||
uint32_t ns_caller,
|
||||
uint32_t privileged)
|
||||
{
|
||||
int flags = CMSE_MPU_READWRITE;
|
||||
|
||||
if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
|
||||
flags |= CMSE_MPU_UNPRIV;
|
||||
}
|
||||
|
||||
if (ns_caller) {
|
||||
flags |= CMSE_NONSECURE;
|
||||
}
|
||||
|
||||
return has_access_to_region(p, s, flags);
|
||||
}
|
||||
|
||||
void tfm_secure_api_error_handler(void)
|
||||
{
|
||||
ERROR_MSG("Security violation when calling secure API");
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_SECURE_API_H__
|
||||
#define __TFM_SECURE_API_H__
|
||||
|
||||
#include <arm_cmse.h>
|
||||
#include "tfm_svc.h"
|
||||
#include "secure_utilities.h"
|
||||
#include "tfm_core.h"
|
||||
#include "tfm_api.h"
|
||||
#include "bl2/include/tfm_boot_status.h"
|
||||
|
||||
/*!
|
||||
* \def __tfm_secure_gateway_attributes__
|
||||
*
|
||||
* \brief Attributes for secure gateway functions
|
||||
*/
|
||||
#define __tfm_secure_gateway_attributes__ \
|
||||
__attribute__((cmse_nonsecure_entry, noinline, section("SFN")))
|
||||
|
||||
/* Hide specific errors if not debugging */
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
#define TFM_ERROR_STATUS(status) (status)
|
||||
#else
|
||||
#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
|
||||
#endif
|
||||
|
||||
#define TFM_SFN_API_LEGACY 0
|
||||
#define TFM_SFN_API_IOVEC 1
|
||||
|
||||
#ifndef TFM_LVL
|
||||
#error TFM_LVL is not defined!
|
||||
#endif
|
||||
|
||||
extern void tfm_secure_api_error_handler(void);
|
||||
|
||||
typedef int32_t(*sfn_t)(int32_t, int32_t, int32_t, int32_t);
|
||||
|
||||
struct tfm_sfn_req_s {
|
||||
uint32_t sp_id;
|
||||
sfn_t sfn;
|
||||
int32_t *args;
|
||||
uint32_t caller_part_idx;
|
||||
int32_t iovec_api;
|
||||
uint32_t ns_caller;
|
||||
};
|
||||
|
||||
enum tfm_buffer_share_region_e {
|
||||
TFM_BUFFER_SHARE_DISABLE,
|
||||
TFM_BUFFER_SHARE_NS_CODE,
|
||||
TFM_BUFFER_SHARE_SCRATCH,
|
||||
TFM_BUFFER_SHARE_PRIV, /* only for TCB in level 2, all in level 1 */
|
||||
TFM_BUFFER_SHARE_DEFAULT,
|
||||
};
|
||||
|
||||
enum tfm_ns_region_e {
|
||||
TFM_NS_REGION_CODE = 0,
|
||||
TFM_NS_REGION_DATA,
|
||||
TFM_NS_REGION_VENEER,
|
||||
TFM_NS_REGION_PERIPH_1,
|
||||
TFM_NS_REGION_PERIPH_2,
|
||||
TFM_NS_SECONDARY_IMAGE_REGION,
|
||||
};
|
||||
|
||||
enum tfm_memory_access_e {
|
||||
TFM_MEMORY_ACCESS_RO = 1,
|
||||
TFM_MEMORY_ACCESS_RW = 2,
|
||||
};
|
||||
|
||||
extern int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share);
|
||||
|
||||
extern int32_t tfm_core_validate_secure_caller(void);
|
||||
|
||||
extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
|
||||
|
||||
extern int32_t tfm_core_memory_permission_check(const void *ptr,
|
||||
uint32_t size,
|
||||
int32_t access);
|
||||
|
||||
extern int32_t tfm_core_get_boot_data(uint8_t major_type,
|
||||
struct tfm_boot_data *boot_data,
|
||||
uint32_t len);
|
||||
|
||||
int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);
|
||||
|
||||
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
|
||||
|
||||
/**
|
||||
* \brief Check whether the current partition has read access to a memory range
|
||||
*
|
||||
* This function assumes, that the current MPU configuration is set for the
|
||||
* partition to be checked.
|
||||
*
|
||||
* \param[in] p The start address of the range to check
|
||||
* \param[in] s The size of the range to check
|
||||
* \param[in] ns_caller Whether the current partition is a non-secure one
|
||||
* \param[in] privileged Privileged mode or unprivileged mode:
|
||||
* \ref TFM_PARTITION_UNPRIVILEGED_MODE
|
||||
* \ref TFM_PARTITION_PRIVILEGED_MODE
|
||||
*
|
||||
* \return TFM_SUCCESS if the partition has access to the memory range,
|
||||
* TFM_ERROR_GENERIC otherwise.
|
||||
*/
|
||||
int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
|
||||
uint32_t ns_caller,
|
||||
uint32_t privileged);
|
||||
|
||||
/**
|
||||
* \brief Check whether the current partition has write access to a memory range
|
||||
*
|
||||
* This function assumes, that the current MPU configuration is set for the
|
||||
* partition to be checked.
|
||||
*
|
||||
* \param[in] p The start address of the range to check
|
||||
* \param[in] s The size of the range to check
|
||||
* \param[in] ns_caller Whether the current partition is a non-secure one
|
||||
* \param[in] privileged Privileged mode or unprivileged mode:
|
||||
* \ref TFM_PARTITION_UNPRIVILEGED_MODE
|
||||
* \ref TFM_PARTITION_PRIVILEGED_MODE
|
||||
*
|
||||
* \return TFM_SUCCESS if the partition has access to the memory range,
|
||||
* TFM_ERROR_GENERIC otherwise.
|
||||
*/
|
||||
int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
|
||||
uint32_t ns_caller,
|
||||
uint32_t privileged);
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
/* The following macros are only valid if secure services can be called
|
||||
* using veneer functions. This is not the case if IPC messaging is enabled
|
||||
*/
|
||||
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
|
||||
do { \
|
||||
ERROR_MSG("Invalid TF-M configuration detected"); \
|
||||
tfm_secure_api_error_handler(); \
|
||||
/* This point never reached */ \
|
||||
return (int32_t)TFM_ERROR_GENERIC; \
|
||||
} while (0)
|
||||
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
|
||||
do { \
|
||||
ERROR_MSG("Invalid TF-M configuration detected"); \
|
||||
tfm_secure_api_error_handler(); \
|
||||
/* This point never reached */ \
|
||||
return (int32_t)TFM_ERROR_GENERIC; \
|
||||
} while (0)
|
||||
#else
|
||||
#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
|
||||
return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \
|
||||
(int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
|
||||
|
||||
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
|
||||
return tfm_core_partition_request(id, fn, TFM_SFN_API_LEGACY, \
|
||||
(int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api,
|
||||
int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
|
||||
{
|
||||
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
||||
struct tfm_sfn_req_s desc, *desc_ptr = &desc;
|
||||
|
||||
desc.sp_id = id;
|
||||
desc.sfn = (sfn_t) fn;
|
||||
desc.args = args;
|
||||
/*
|
||||
* This preprocessor condition checks if a version of GCC smaller than
|
||||
* 7.3.1 is being used to compile the code.
|
||||
* These versions are affected by a bug on the cmse_nonsecure_caller
|
||||
* intrinsic which returns incorrect results.
|
||||
* Please check Bug 85203 on GCC Bugzilla for more information.
|
||||
*/
|
||||
#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && \
|
||||
(__GNUC__ < 7 || \
|
||||
(__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || \
|
||||
(__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))))
|
||||
/*
|
||||
* Use the fact that, if called from Non-Secure, the LSB of the return
|
||||
* address is set to 0.
|
||||
*/
|
||||
desc.ns_caller = (uint32_t)!(
|
||||
(intptr_t)__builtin_extract_return_addr(__builtin_return_address(0U))
|
||||
& 1);
|
||||
#else
|
||||
/*
|
||||
* Convert the result of cmse_nonsecure_caller from an int to a uint32_t
|
||||
* to prevent using an int in the tfm_sfn_req_s structure.
|
||||
*/
|
||||
desc.ns_caller = (cmse_nonsecure_caller() != 0) ? 1U : 0U;
|
||||
#endif /* Check for GCC compiler version smaller than 7.3.1 */
|
||||
desc.iovec_api = iovec_api;
|
||||
if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
|
||||
/* FixMe: Error severity TBD */
|
||||
return TFM_ERROR_GENERIC;
|
||||
} else {
|
||||
#if TFM_LVL == 1
|
||||
if (desc.ns_caller) {
|
||||
return tfm_core_sfn_request(desc_ptr);
|
||||
} else {
|
||||
return tfm_core_sfn_request_thread_mode(desc_ptr);
|
||||
}
|
||||
#else
|
||||
return tfm_core_sfn_request(desc_ptr);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TFM_SECURE_API_H__ */
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <arm_cmse.h>
|
||||
|
||||
#include "tfm_svc.h"
|
||||
#include "tfm_secure_api.h"
|
||||
#include "tfm_internal.h"
|
||||
#include "secure_fw/include/tfm_spm_services_api.h"
|
||||
#include "spm_api.h"
|
||||
|
||||
uint8_t *tfm_scratch_area;
|
||||
uint32_t tfm_scratch_area_size;
|
||||
nsfptr_t ns_entry;
|
||||
|
||||
void jump_to_ns_code(void)
|
||||
{
|
||||
#if TFM_LVL == 3 || ((!defined(TFM_PSA_API)) && (TFM_LVL != 1))
|
||||
/* Initialization is done, set thread mode to unprivileged. */
|
||||
tfm_spm_partition_change_privilege(TFM_PARTITION_UNPRIVILEGED_MODE);
|
||||
#endif
|
||||
/* All changes made to memory will be effective after this point */
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Calls the non-secure Reset_Handler to jump to the non-secure binary */
|
||||
ns_entry();
|
||||
}
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
#if defined(__ARM_ARCH_8M_MAIN__)
|
||||
__attribute__((naked)) int32_t tfm_core_sfn_request(
|
||||
const struct tfm_sfn_req_s *desc_ptr)
|
||||
{
|
||||
__ASM volatile(
|
||||
"PUSH {r4-r12, lr}\n"
|
||||
"SVC %[SVC_REQ]\n"
|
||||
"MOV r4, #0\n"
|
||||
"MOV r5, #0\n"
|
||||
"MOV r6, #0\n"
|
||||
"MOV r7, #0\n"
|
||||
"MOV r8, #0\n"
|
||||
"MOV r9, #0\n"
|
||||
"MOV r10, #0\n"
|
||||
"MOV r11, #0\n"
|
||||
"BLX lr\n"
|
||||
"SVC %[SVC_RET]\n"
|
||||
"POP {r4-r12, pc}\n"
|
||||
: : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST)
|
||||
, [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
|
||||
: "r0");
|
||||
}
|
||||
#elif defined(__ARM_ARCH_8M_BASE__)
|
||||
__attribute__((naked)) int32_t tfm_core_sfn_request(
|
||||
const struct tfm_sfn_req_s *desc_ptr)
|
||||
{
|
||||
__ASM volatile(
|
||||
".syntax unified\n"
|
||||
"PUSH {lr}\n"
|
||||
"PUSH {r4-r7}\n"
|
||||
"MOV r4, r8\n"
|
||||
"MOV r5, r9\n"
|
||||
"MOV r6, r10\n"
|
||||
"MOV r7, r11\n"
|
||||
"PUSH {r4-r7}\n"
|
||||
"MOV r4, r12\n"
|
||||
"PUSH {r4}\n"
|
||||
"SVC %[SVC_REQ]\n"
|
||||
"MOVS r4, #0\n"
|
||||
"MOV r5, r4\n"
|
||||
"MOV r6, r4\n"
|
||||
"MOV r7, r4\n"
|
||||
"MOV r8, r4\n"
|
||||
"MOV r9, r4\n"
|
||||
"MOV r10, r4\n"
|
||||
"MOV r11, r4\n"
|
||||
"BLX lr\n"
|
||||
"SVC %[SVC_RET]\n"
|
||||
"POP {r4}\n"
|
||||
"MOV r12, r4\n"
|
||||
"POP {r4-r7}\n"
|
||||
"MOV r8, r4\n"
|
||||
"MOV r9, r5\n"
|
||||
"MOV r10, r6\n"
|
||||
"MOV r11, r7\n"
|
||||
"POP {r4-r7}\n"
|
||||
"POP {pc}\n"
|
||||
: : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST)
|
||||
, [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
|
||||
: "r0");
|
||||
}
|
||||
#else
|
||||
#error "Unsupported ARM Architecture."
|
||||
#endif
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_core_memory_permission_check(const void *ptr,
|
||||
uint32_t len,
|
||||
int32_t access)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX lr\n"
|
||||
: : "I" (TFM_SVC_MEMORY_CHECK));
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX LR\n"
|
||||
: : "I" (TFM_SVC_GET_CALLER_CLIENT_ID));
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_spm_request_reset_vote(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"MOVS R0, %0\n"
|
||||
"B tfm_spm_request\n"
|
||||
: : "I" (TFM_SPM_REQUEST_RESET_VOTE));
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_spm_request(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX lr\n"
|
||||
: : "I" (TFM_SVC_SPM_REQUEST));
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_core_validate_secure_caller(void)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX lr\n"
|
||||
: : "I" (TFM_SVC_VALIDATE_SECURE_CALLER));
|
||||
}
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX lr\n"
|
||||
: : "I" (TFM_SVC_SET_SHARE_AREA));
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((naked))
|
||||
int32_t tfm_core_get_boot_data(uint8_t major_type,
|
||||
struct tfm_boot_data *boot_status,
|
||||
uint32_t len)
|
||||
{
|
||||
__ASM volatile(
|
||||
"SVC %0\n"
|
||||
"BX lr\n"
|
||||
: : "I" (TFM_SVC_GET_BOOT_DATA));
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_SVC_H__
|
||||
#define __TFM_SVC_H__
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
typedef enum {
|
||||
TFM_SVC_SFN_REQUEST = 0,
|
||||
TFM_SVC_SFN_RETURN,
|
||||
TFM_SVC_VALIDATE_SECURE_CALLER,
|
||||
TFM_SVC_GET_CALLER_CLIENT_ID,
|
||||
TFM_SVC_MEMORY_CHECK,
|
||||
TFM_SVC_SET_SHARE_AREA,
|
||||
TFM_SVC_SPM_REQUEST,
|
||||
TFM_SVC_PRINT,
|
||||
TFM_SVC_GET_BOOT_DATA,
|
||||
#ifdef TFM_PSA_API
|
||||
TFM_SVC_IPC_REQUEST,
|
||||
TFM_SVC_SCHEDULE,
|
||||
TFM_SVC_EXIT_THRD,
|
||||
/* PSA Client SVC */
|
||||
TFM_SVC_PSA_FRAMEWORK_VERSION,
|
||||
TFM_SVC_PSA_VERSION,
|
||||
TFM_SVC_PSA_CONNECT,
|
||||
TFM_SVC_PSA_CALL,
|
||||
TFM_SVC_PSA_CLOSE,
|
||||
/* PSA Service SVC */
|
||||
TFM_SVC_PSA_WAIT,
|
||||
TFM_SVC_PSA_GET,
|
||||
TFM_SVC_PSA_SET_RHANDLE,
|
||||
TFM_SVC_PSA_READ,
|
||||
TFM_SVC_PSA_SKIP,
|
||||
TFM_SVC_PSA_WRITE,
|
||||
TFM_SVC_PSA_REPLY,
|
||||
TFM_SVC_PSA_NOTIFY,
|
||||
TFM_SVC_PSA_CLEAR,
|
||||
TFM_SVC_PSA_EOI,
|
||||
#endif
|
||||
} tfm_svc_number_t;
|
||||
|
||||
#define SVC(code) __ASM volatile("svc %0" : : "I" (code))
|
||||
|
||||
#endif /* __TFM_SVC_H__ */
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
//This file holds description for the current directory. This documentation
|
||||
//will be included in the Doxygen output.
|
||||
|
||||
/*!
|
||||
\dir
|
||||
\brief Include files for the TF-M.
|
||||
\details This directory currently only holds the include file for the SPM
|
||||
module.
|
||||
|
||||
*/
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TFM_SPM_SERVICES_API_H__
|
||||
#define __TFM_SPM_SERVICES_API_H__
|
||||
|
||||
enum tfm_spm_request_type_t {
|
||||
TFM_SPM_REQUEST_RESET_VOTE,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Request a vote from SPM on a system reset
|
||||
*
|
||||
* \return Returns 0 if request is accepted, any other value means reject
|
||||
*/
|
||||
int32_t tfm_spm_request_reset_vote(void);
|
||||
|
||||
#endif /* __TFM_SPM_SERVICES_API_H__ */
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "psa_client.h"
|
||||
#include "psa_service.h"
|
||||
#include "secure_utilities.h"
|
||||
#include "tfm_secure_api.h"
|
||||
#include "tfm_api.h"
|
||||
#include "tfm_svcalls.h"
|
||||
|
||||
/* FixMe: check if this is really needed */
|
||||
extern int32_t tfm_secure_lock;
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
int32_t tfm_psa_veneer_sanity_check(struct tfm_sfn_req_s *desc_ptr)
|
||||
{
|
||||
if (desc_ptr->ns_caller) {
|
||||
if (tfm_secure_lock != 0) {
|
||||
/* Secure domain is already locked!
|
||||
* FixMe: Decide if this is a fault or permitted in case of PSA
|
||||
* API usage
|
||||
*/
|
||||
return TFM_ERROR_SECURE_DOMAIN_LOCKED;
|
||||
}
|
||||
} else {
|
||||
/* Secure partition should not call a different secure partition
|
||||
* using TFM PSA veneers
|
||||
*/
|
||||
return TFM_ERROR_INVALID_EXC_MODE;
|
||||
}
|
||||
return TFM_SUCCESS;
|
||||
}
|
||||
|
||||
/* Veneer implementation */
|
||||
|
||||
#define TFM_CORE_NS_IPC_REQUEST_VENEER(fn, a, b, c, d) \
|
||||
return tfm_core_ns_ipc_request(fn, (int32_t)a, (int32_t)b, \
|
||||
(int32_t)c, (int32_t)d)
|
||||
|
||||
__attribute__ ((naked, section("SFN")))
|
||||
static int32_t tfm_core_ipc_request(const struct tfm_sfn_req_s *desc_ptr)
|
||||
{
|
||||
__ASM volatile("SVC %0 \n"
|
||||
"BX LR \n"
|
||||
: : "I" (TFM_SVC_IPC_REQUEST));
|
||||
}
|
||||
|
||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||
int32_t tfm_core_ns_ipc_request(void *fn, int32_t arg1, int32_t arg2,
|
||||
int32_t arg3, int32_t arg4)
|
||||
{
|
||||
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
||||
struct tfm_sfn_req_s desc = {0};
|
||||
|
||||
desc.sfn = fn;
|
||||
desc.args = args;
|
||||
desc.ns_caller = cmse_nonsecure_caller();
|
||||
|
||||
if (__get_active_exc_num() != EXC_NUM_THREAD_MODE)
|
||||
{
|
||||
/* FIXME: Proper error handling to be implemented */
|
||||
return TFM_ERROR_INVALID_EXC_MODE;
|
||||
} else {
|
||||
return tfm_core_ipc_request(&desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* FixMe: these functions need to have different attributes compared to those
|
||||
* legacy veneers which may be called by secure partitions.
|
||||
* They won't call legacy SFN but instead will be handlers for TF-M
|
||||
*/
|
||||
|
||||
__tfm_secure_gateway_attributes__
|
||||
uint32_t tfm_psa_framework_version_veneer(void)
|
||||
{
|
||||
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_framework_version, 0, 0,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
__tfm_secure_gateway_attributes__
|
||||
uint32_t tfm_psa_version_veneer(uint32_t sid)
|
||||
{
|
||||
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_version, sid, 0, 0, 0);
|
||||
}
|
||||
|
||||
__tfm_secure_gateway_attributes__
|
||||
psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version)
|
||||
{
|
||||
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_connect, sid,
|
||||
minor_version, 0, 0);
|
||||
}
|
||||
|
||||
__tfm_secure_gateway_attributes__
|
||||
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
|
||||
const psa_invec *in_vecs,
|
||||
psa_outvec *out_vecs)
|
||||
{
|
||||
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs,
|
||||
out_vecs, 0);
|
||||
}
|
||||
|
||||
__tfm_secure_gateway_attributes__
|
||||
psa_status_t tfm_psa_close_veneer(psa_handle_t handle)
|
||||
{
|
||||
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_close, handle, 0, 0, 0);
|
||||
}
|
||||
|
||||
void tfm_psa_ipc_request_handler(uint32_t svc_ctx[])
|
||||
{
|
||||
uint32_t *r0_ptr = svc_ctx;
|
||||
|
||||
/* The only argument to the SVC call is stored in the stacked r0 */
|
||||
struct tfm_sfn_req_s *desc_ptr = (struct tfm_sfn_req_s *) *r0_ptr;
|
||||
|
||||
if(tfm_psa_veneer_sanity_check(desc_ptr) != TFM_SUCCESS) {
|
||||
/* FixMe: consider error handling - this may be critical error */
|
||||
*r0_ptr = TFM_ERROR_INVALID_PARAMETER;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store SVC return value in stacked r0 */
|
||||
*r0_ptr = desc_ptr->sfn((int32_t)desc_ptr->args,
|
||||
desc_ptr->ns_caller,
|
||||
0,
|
||||
0);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
//This file holds description for the current directory. This documentation
|
||||
//will be included in the Doxygen output.
|
||||
|
||||
/*!
|
||||
\dir
|
||||
\brief Source code for the Secure Partition Manager.
|
||||
\details This directory holds the source code of the "TF-M SPM" module.
|
||||
|
||||
*/
|
|
@ -1,416 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
/* This file contains the APIs exported by the SPM to tfm core */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "spm_api.h"
|
||||
#include "platform/include/tfm_spm_hal.h"
|
||||
#include "tfm_memory_utils.h"
|
||||
#include "spm_db_setup.h"
|
||||
#include "tfm_internal.h"
|
||||
#include "tfm_api.h"
|
||||
#include "tfm_nspm.h"
|
||||
#include "secure_fw/core/tfm_core.h"
|
||||
#include "tfm_peripherals_def.h"
|
||||
#include "spm_partition_defs.h"
|
||||
|
||||
|
||||
struct spm_partition_db_t g_spm_partition_db = {0,};
|
||||
|
||||
typedef enum {
|
||||
TFM_INIT_FAILURE,
|
||||
} sp_error_type_t;
|
||||
|
||||
/*
|
||||
* This function is called when a secure partition causes an error.
|
||||
* In case of an error in the error handling, a non-zero value have to be
|
||||
* returned.
|
||||
*/
|
||||
#ifndef TFM_PSA_API
|
||||
static void tfm_spm_partition_err_handler(
|
||||
const struct spm_partition_desc_t *partition,
|
||||
sp_error_type_t err_type,
|
||||
int32_t err_code)
|
||||
{
|
||||
#ifdef TFM_CORE_DEBUG
|
||||
if (err_type == TFM_INIT_FAILURE) {
|
||||
printf("Partition init failed for partition id 0x%08X\r\n",
|
||||
partition->static_data.partition_id);
|
||||
} else {
|
||||
printf(
|
||||
"Unknown partition error %d (code: %d) for partition id 0x%08X\r\n",
|
||||
err_type, err_code, partition->static_data.partition_id);
|
||||
}
|
||||
#else
|
||||
(void)err_type;
|
||||
(void)err_code;
|
||||
#endif
|
||||
tfm_spm_partition_set_state(partition->static_data.partition_id,
|
||||
SPM_PARTITION_STATE_CLOSED);
|
||||
}
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
/*
|
||||
* This function prevents name clashes between the variable names accessibles in
|
||||
* the scope of where tfm_partition_list.inc is included and the varaible names
|
||||
* defined inside tfm_partition_list.inc file.
|
||||
*/
|
||||
static inline enum spm_err_t add_user_defined_partitions(void) {
|
||||
#include "tfm_partition_list.inc"
|
||||
|
||||
return SPM_ERR_OK;
|
||||
}
|
||||
|
||||
uint32_t get_partition_idx(uint32_t partition_id)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (partition_id == INVALID_PARTITION_ID) {
|
||||
return SPM_INVALID_PARTITION_IDX;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_spm_partition_db.partition_count; ++i) {
|
||||
if (g_spm_partition_db.partitions[i].static_data.partition_id ==
|
||||
partition_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return SPM_INVALID_PARTITION_IDX;
|
||||
}
|
||||
|
||||
enum spm_err_t tfm_spm_db_init(void)
|
||||
{
|
||||
struct spm_partition_desc_t *part_ptr;
|
||||
enum spm_err_t err;
|
||||
|
||||
(void)tfm_memset (&g_spm_partition_db, 0, sizeof(g_spm_partition_db));
|
||||
|
||||
/* This function initialises partition db */
|
||||
g_spm_partition_db.running_partition_idx = SPM_INVALID_PARTITION_IDX;
|
||||
g_spm_partition_db.partition_count = 0;
|
||||
|
||||
/* There are a few partitions that are used by TF-M internally.
|
||||
* These are explicitly added to the partition db here.
|
||||
*/
|
||||
|
||||
/* For the non secure Execution environment */
|
||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[];
|
||||
extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[];
|
||||
uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base;
|
||||
uint32_t psp_stack_top = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Limit;
|
||||
#endif
|
||||
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
|
||||
return SPM_ERR_INVALID_CONFIG;
|
||||
}
|
||||
part_ptr = &(g_spm_partition_db.partitions[
|
||||
g_spm_partition_db.partition_count]);
|
||||
part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID;
|
||||
#ifdef TFM_PSA_API
|
||||
part_ptr->static_data.partition_flags = SPM_PART_FLAG_APP_ROT |
|
||||
SPM_PART_FLAG_IPC;
|
||||
part_ptr->static_data.partition_priority = TFM_PRIORITY_LOW;
|
||||
part_ptr->static_data.partition_init = tfm_nspm_thread_entry;
|
||||
#else
|
||||
part_ptr->static_data.partition_flags = 0;
|
||||
#endif
|
||||
|
||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
|
||||
part_ptr->memory_data.stack_bottom = psp_stack_bottom;
|
||||
part_ptr->memory_data.stack_top = psp_stack_top;
|
||||
/* Since RW, ZI and stack are configured as one MPU region, configure
|
||||
* RW start address to psp_stack_bottom to get RW access to stack
|
||||
*/
|
||||
part_ptr->memory_data.rw_start = psp_stack_bottom;
|
||||
#endif
|
||||
|
||||
part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
|
||||
tfm_nspm_configure_clients();
|
||||
++g_spm_partition_db.partition_count;
|
||||
|
||||
/* For the TF-M core environment itself */
|
||||
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) {
|
||||
return SPM_ERR_INVALID_CONFIG;
|
||||
}
|
||||
part_ptr = &(g_spm_partition_db.partitions[
|
||||
g_spm_partition_db.partition_count]);
|
||||
part_ptr->static_data.partition_id = TFM_SP_CORE_ID;
|
||||
part_ptr->static_data.partition_flags =
|
||||
SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT;
|
||||
part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
|
||||
++g_spm_partition_db.partition_count;
|
||||
|
||||
err = add_user_defined_partitions();
|
||||
if (err != SPM_ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
g_spm_partition_db.is_init = 1;
|
||||
|
||||
return SPM_ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
enum spm_err_t tfm_spm_partition_init(void)
|
||||
{
|
||||
struct spm_partition_desc_t *part;
|
||||
struct tfm_sfn_req_s desc;
|
||||
int32_t args[4] = {0};
|
||||
int32_t fail_cnt = 0;
|
||||
uint32_t idx;
|
||||
|
||||
/* Call the init function for each partition */
|
||||
for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
|
||||
part = &g_spm_partition_db.partitions[idx];
|
||||
tfm_spm_hal_configure_default_isolation(part->platform_data);
|
||||
if (part->static_data.partition_init == NULL) {
|
||||
tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
|
||||
tfm_spm_partition_set_caller_partition_idx(idx,
|
||||
SPM_INVALID_PARTITION_IDX);
|
||||
} else {
|
||||
int32_t res;
|
||||
|
||||
desc.args = args;
|
||||
desc.ns_caller = 0U;
|
||||
desc.iovec_api = TFM_SFN_API_IOVEC;
|
||||
desc.sfn = (sfn_t)part->static_data.partition_init;
|
||||
desc.sp_id = part->static_data.partition_id;
|
||||
res = tfm_core_sfn_request(&desc);
|
||||
if (res == TFM_SUCCESS) {
|
||||
tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
|
||||
} else {
|
||||
tfm_spm_partition_err_handler(part, TFM_INIT_FAILURE, res);
|
||||
fail_cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tfm_secure_api_init_done();
|
||||
|
||||
if (fail_cnt == 0) {
|
||||
return SPM_ERR_OK;
|
||||
} else {
|
||||
return SPM_ERR_PARTITION_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
|
||||
uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].
|
||||
memory_data.stack_bottom;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
|
||||
enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx)
|
||||
{
|
||||
struct spm_partition_desc_t *part;
|
||||
if (!g_spm_partition_db.is_init) {
|
||||
return SPM_ERR_PARTITION_DB_NOT_INIT;
|
||||
}
|
||||
|
||||
part = &g_spm_partition_db.partitions[partition_idx];
|
||||
|
||||
return tfm_spm_hal_partition_sandbox_config(&(part->memory_data),
|
||||
part->platform_data);
|
||||
|
||||
}
|
||||
|
||||
enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx)
|
||||
{
|
||||
/* This function takes a partition id and disables the
|
||||
* SPM partition for that partition
|
||||
*/
|
||||
|
||||
struct spm_partition_desc_t *part;
|
||||
|
||||
part = &g_spm_partition_db.partitions[partition_idx];
|
||||
|
||||
return tfm_spm_hal_partition_sandbox_deconfig(&(part->memory_data),
|
||||
part->platform_data);
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].
|
||||
memory_data.zi_start;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_zi_limit(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].
|
||||
memory_data.zi_limit;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].
|
||||
memory_data.rw_start;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].
|
||||
memory_data.rw_limit;
|
||||
}
|
||||
|
||||
void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr)
|
||||
{
|
||||
g_spm_partition_db.partitions[partition_idx].
|
||||
runtime_data.stack_ptr = stack_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].static_data.
|
||||
partition_id;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
|
||||
{
|
||||
return g_spm_partition_db.partitions[partition_idx].static_data.
|
||||
partition_flags;
|
||||
}
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
void tfm_spm_partition_store_context(uint32_t partition_idx,
|
||||
uint32_t stack_ptr, uint32_t lr)
|
||||
{
|
||||
g_spm_partition_db.partitions[partition_idx].
|
||||
runtime_data.stack_ptr = stack_ptr;
|
||||
g_spm_partition_db.partitions[partition_idx].
|
||||
runtime_data.lr = lr;
|
||||
}
|
||||
|
||||
const struct spm_partition_runtime_data_t *
|
||||
tfm_spm_partition_get_runtime_data(uint32_t partition_idx)
|
||||
{
|
||||
return &(g_spm_partition_db.partitions[partition_idx].runtime_data);
|
||||
}
|
||||
|
||||
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state)
|
||||
{
|
||||
g_spm_partition_db.partitions[partition_idx].runtime_data.partition_state =
|
||||
state;
|
||||
if (state == SPM_PARTITION_STATE_RUNNING) {
|
||||
g_spm_partition_db.running_partition_idx = partition_idx;
|
||||
}
|
||||
}
|
||||
|
||||
void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
|
||||
uint32_t caller_partition_idx)
|
||||
{
|
||||
g_spm_partition_db.partitions[partition_idx].runtime_data.
|
||||
caller_partition_idx = caller_partition_idx;
|
||||
}
|
||||
|
||||
void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
|
||||
int32_t caller_client_id)
|
||||
{
|
||||
g_spm_partition_db.partitions[partition_idx].runtime_data.
|
||||
caller_client_id = caller_client_id;
|
||||
}
|
||||
|
||||
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
|
||||
uint32_t share)
|
||||
{
|
||||
enum spm_err_t ret = SPM_ERR_OK;
|
||||
|
||||
#if TFM_LVL != 1
|
||||
/* Only need to set configuration on levels higher than 1 */
|
||||
ret = tfm_spm_hal_set_share_region(share);
|
||||
#endif
|
||||
|
||||
if (ret == SPM_ERR_OK) {
|
||||
g_spm_partition_db.partitions[partition_idx].runtime_data.share = share;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
|
||||
const int32_t *args)
|
||||
{
|
||||
struct spm_partition_runtime_data_t *runtime_data =
|
||||
&g_spm_partition_db.partitions[partition_idx].runtime_data;
|
||||
size_t i;
|
||||
|
||||
if ((args[1] < 0) || (args[3] < 0)) {
|
||||
return SPM_ERR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
runtime_data->iovec_args.in_len = (size_t)args[1];
|
||||
for (i = 0U; i < runtime_data->iovec_args.in_len; ++i) {
|
||||
runtime_data->iovec_args.in_vec[i].base =
|
||||
((psa_invec *)args[0])[i].base;
|
||||
runtime_data->iovec_args.in_vec[i].len = ((psa_invec *)args[0])[i].len;
|
||||
}
|
||||
runtime_data->iovec_args.out_len = (size_t)args[3];
|
||||
for (i = 0U; i < runtime_data->iovec_args.out_len; ++i) {
|
||||
runtime_data->iovec_args.out_vec[i].base =
|
||||
((psa_outvec *)args[2])[i].base;
|
||||
runtime_data->iovec_args.out_vec[i].len =
|
||||
((psa_outvec *)args[2])[i].len;
|
||||
}
|
||||
runtime_data->orig_outvec = (psa_outvec *)args[2];
|
||||
runtime_data->iovec_api = 1;
|
||||
|
||||
return SPM_ERR_OK;
|
||||
}
|
||||
|
||||
uint32_t tfm_spm_partition_get_running_partition_idx(void)
|
||||
{
|
||||
return g_spm_partition_db.running_partition_idx;
|
||||
}
|
||||
|
||||
void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
|
||||
{
|
||||
struct spm_partition_desc_t *partition =
|
||||
&(g_spm_partition_db.partitions[partition_idx]);
|
||||
int32_t i;
|
||||
|
||||
partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
|
||||
partition->runtime_data.share = 0;
|
||||
partition->runtime_data.iovec_args.in_len = 0;
|
||||
for (i = 0; i < PSA_MAX_IOVEC; ++i) {
|
||||
partition->runtime_data.iovec_args.in_vec[i].base = 0;
|
||||
partition->runtime_data.iovec_args.in_vec[i].len = 0;
|
||||
}
|
||||
partition->runtime_data.iovec_args.out_len = 0;
|
||||
for (i = 0; i < PSA_MAX_IOVEC; ++i) {
|
||||
partition->runtime_data.iovec_args.out_vec[i].base = 0;
|
||||
partition->runtime_data.iovec_args.out_vec[i].len = 0;
|
||||
}
|
||||
partition->runtime_data.orig_outvec = 0;
|
||||
partition->runtime_data.iovec_api = 0;
|
||||
}
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
__attribute__((section("SFN")))
|
||||
void tfm_spm_partition_change_privilege(uint32_t privileged)
|
||||
{
|
||||
CONTROL_Type ctrl;
|
||||
|
||||
ctrl.w = __get_CONTROL();
|
||||
|
||||
if (privileged == TFM_PARTITION_PRIVILEGED_MODE) {
|
||||
ctrl.b.nPRIV = 0;
|
||||
} else {
|
||||
ctrl.b.nPRIV = 1;
|
||||
}
|
||||
|
||||
__set_CONTROL(ctrl.w);
|
||||
}
|
|
@ -1,355 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPM_API_H__
|
||||
#define __SPM_API_H__
|
||||
|
||||
/* This file contains the apis exported by the SPM to tfm core */
|
||||
#include "tfm_api.h"
|
||||
#include "spm_partition_defs.h"
|
||||
#include "secure_fw/core/tfm_secure_api.h"
|
||||
|
||||
#define SPM_INVALID_PARTITION_IDX (~0U)
|
||||
|
||||
/* Privileged definitions for partition thread mode */
|
||||
#define TFM_PARTITION_PRIVILEGED_MODE 1
|
||||
#define TFM_PARTITION_UNPRIVILEGED_MODE 0
|
||||
|
||||
enum spm_err_t {
|
||||
SPM_ERR_OK = 0,
|
||||
SPM_ERR_PARTITION_DB_NOT_INIT,
|
||||
SPM_ERR_PARTITION_ALREADY_ACTIVE,
|
||||
SPM_ERR_PARTITION_NOT_AVAILABLE,
|
||||
SPM_ERR_INVALID_PARAMETER,
|
||||
SPM_ERR_INVALID_CONFIG,
|
||||
};
|
||||
|
||||
enum spm_part_state_t {
|
||||
SPM_PARTITION_STATE_UNINIT = 0,
|
||||
SPM_PARTITION_STATE_IDLE,
|
||||
SPM_PARTITION_STATE_RUNNING,
|
||||
SPM_PARTITION_STATE_SUSPENDED,
|
||||
SPM_PARTITION_STATE_BLOCKED,
|
||||
SPM_PARTITION_STATE_CLOSED
|
||||
};
|
||||
|
||||
enum spm_part_flag_mask_t {
|
||||
SPM_PART_FLAG_APP_ROT = 0x01,
|
||||
SPM_PART_FLAG_PSA_ROT = 0x02,
|
||||
SPM_PART_FLAG_IPC = 0x04
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Holds the iovec parameters that are passed to a service
|
||||
*
|
||||
* \note The size of the structure is (and have to be) multiple of 8 bytes
|
||||
*/
|
||||
struct iovec_args_t {
|
||||
psa_invec in_vec[PSA_MAX_IOVEC]; /*!< Array of psa_invec objects */
|
||||
size_t in_len; /*!< Number psa_invec objects in in_vec
|
||||
*/
|
||||
psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
|
||||
size_t out_len; /*!< Number psa_outvec objects in out_vec
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Runtime context information of a partition
|
||||
*/
|
||||
struct spm_partition_runtime_data_t {
|
||||
uint32_t partition_state;
|
||||
uint32_t caller_partition_idx;
|
||||
int32_t caller_client_id;
|
||||
uint32_t share;
|
||||
uint32_t stack_ptr;
|
||||
uint32_t lr;
|
||||
int32_t iovec_api; /*!< Whether the function in the partition
|
||||
* had been called using the iovec API.
|
||||
* FIXME: Remove the field once this is the
|
||||
* only option
|
||||
*/
|
||||
struct iovec_args_t iovec_args;
|
||||
psa_outvec *orig_outvec;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the index of the partition with the given partition ID.
|
||||
*
|
||||
* \param[in] partition_id Partition id
|
||||
*
|
||||
* \return the partition idx if partition_id is valid,
|
||||
* \ref SPM_INVALID_PARTITION_IDX othervise
|
||||
*/
|
||||
uint32_t get_partition_idx(uint32_t partition_id);
|
||||
|
||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
|
||||
/**
|
||||
* \brief Get bottom of stack region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Stack region bottom value
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get top of stack region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Stack region top value
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx);
|
||||
#endif
|
||||
|
||||
#if (TFM_LVL != 1) && !defined(TFM_PSA_API)
|
||||
/**
|
||||
* \brief Configure isolated sandbox for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Deconfigure sandbox for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get the start of the zero-initialised region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition idx
|
||||
*
|
||||
* \return Start of the zero-initialised region
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get the limit of the zero-initialised region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition idx
|
||||
*
|
||||
* \return Limit of the zero-initialised region
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
* \note The address returned is not part of the region.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_zi_limit(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get the start of the read-write region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition idx
|
||||
*
|
||||
* \return Start of the read-write region
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get the limit of the read-write region for a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition idx
|
||||
*
|
||||
* \return Limit of the read-write region
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
* \note The address returned is not part of the region.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Save stack pointer for partition in database
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] stack_ptr Stack pointer to be stored
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Get the id of the partition for its index from the db
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Partition ID for that partition
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Get the flags associated with a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return Flags associated with the partition
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
|
||||
|
||||
#ifndef TFM_PSA_API
|
||||
/**
|
||||
* \brief Get the current runtime data of a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \return The runtime data of the specified partition
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
const struct spm_partition_runtime_data_t *
|
||||
tfm_spm_partition_get_runtime_data(uint32_t partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Returns the index of the partition that has running state
|
||||
*
|
||||
* \return The index of the partition with the running state, if there is any
|
||||
* set. 0 otherwise.
|
||||
*/
|
||||
uint32_t tfm_spm_partition_get_running_partition_idx(void);
|
||||
|
||||
/**
|
||||
* \brief Save stack pointer and link register for partition in database
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] stack_ptr Stack pointer to be stored
|
||||
* \param[in] lr Link register to be stored
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
void tfm_spm_partition_store_context(uint32_t partition_idx,
|
||||
uint32_t stack_ptr, uint32_t lr);
|
||||
|
||||
/**
|
||||
* \brief Set the current state of a partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] state The state to be set
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
* \note The state has to have the value set of \ref spm_part_state_t.
|
||||
*/
|
||||
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
|
||||
|
||||
/**
|
||||
* \brief Set the caller partition index for a given partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] caller_partition_idx The index of the caller partition
|
||||
*
|
||||
* \note This function doesn't check if any of the partition_idxs are valid.
|
||||
*/
|
||||
void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
|
||||
uint32_t caller_partition_idx);
|
||||
|
||||
/**
|
||||
* \brief Set the caller client ID for a given partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] caller_client_id The ID of the calling client
|
||||
*
|
||||
* \note This function doesn't check if any of the partition_idxs are valid.
|
||||
*/
|
||||
void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
|
||||
int32_t caller_client_id);
|
||||
|
||||
/**
|
||||
* \brief Set the buffer share region of the partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] share The buffer share region to be set
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
* \note share has to have the value set of \ref tfm_buffer_share_region_e
|
||||
*/
|
||||
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
|
||||
uint32_t share);
|
||||
|
||||
/**
|
||||
* \brief Set the iovec parameters for the partition
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
* \param[in] args The arguments of the secure function
|
||||
*
|
||||
* args is expected to be of type int32_t[4] where:
|
||||
* args[0] is in_vec
|
||||
* args[1] is in_len
|
||||
* args[2] is out_vec
|
||||
* args[3] is out_len
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
* \note This function assumes that the iovecs that are passed in args are
|
||||
* valid, and does no sanity check on them at all.
|
||||
*/
|
||||
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
|
||||
const int32_t *args);
|
||||
|
||||
/**
|
||||
* \brief Execute partition init function
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*/
|
||||
enum spm_err_t tfm_spm_partition_init(void);
|
||||
|
||||
/**
|
||||
* \brief Clears the context info from the database for a partition.
|
||||
*
|
||||
* \param[in] partition_idx Partition index
|
||||
*
|
||||
* \note This function doesn't check if partition_idx is valid.
|
||||
*/
|
||||
void tfm_spm_partition_cleanup_context(uint32_t partition_idx);
|
||||
#endif /* !defined(TFM_PSA_API) */
|
||||
|
||||
/**
|
||||
* \brief Initialize partition database
|
||||
*
|
||||
* \return Error code \ref spm_err_t
|
||||
*/
|
||||
enum spm_err_t tfm_spm_db_init(void);
|
||||
|
||||
/**
|
||||
* \brief Change the privilege mode for partition thread mode.
|
||||
*
|
||||
* \param[in] privileged Privileged mode,
|
||||
* \ref TFM_PARTITION_PRIVILEGED_MODE
|
||||
* and \ref TFM_PARTITION_UNPRIVILEGED_MODE
|
||||
*
|
||||
* \note Barrier instructions are not called by this function, and if
|
||||
* it is called in thread mode, it might be necessary to call
|
||||
* them after this function returns (just like it is done in
|
||||
* jump_to_ns_code()).
|
||||
*/
|
||||
void tfm_spm_partition_change_privilege(uint32_t privileged);
|
||||
|
||||
#endif /*__SPM_API_H__ */
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPM_DB_H__
|
||||
#define __SPM_DB_H__
|
||||
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
#include "tfm_thread.h"
|
||||
#endif
|
||||
|
||||
struct spm_partition_desc_t;
|
||||
struct spm_partition_db_t;
|
||||
|
||||
typedef psa_status_t(*sp_init_function)(void);
|
||||
|
||||
#define TFM_PARTITION_TYPE_APP "APPLICATION-ROT"
|
||||
#define TFM_PARTITION_TYPE_PSA "PSA-ROT"
|
||||
|
||||
#ifdef TFM_PSA_API
|
||||
enum tfm_partition_priority {
|
||||
TFM_PRIORITY_LOW = THRD_PRIOR_LOWEST,
|
||||
TFM_PRIORITY_NORMAL = THRD_PRIOR_MEDIUM,
|
||||
TFM_PRIORITY_HIGH = THRD_PRIOR_HIGHEST,
|
||||
};
|
||||
#else
|
||||
enum tfm_partition_priority {
|
||||
TFM_PRIORITY_LOW = 0xFF,
|
||||
TFM_PRIORITY_NORMAL = 0x7F,
|
||||
TFM_PRIORITY_HIGH = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define TFM_PRIORITY(LEVEL) TFM_PRIORITY_##LEVEL
|
||||
|
||||
/**
|
||||
* Holds the fields of the partition DB used by the SPM code. The values of
|
||||
* these fields are calculated at compile time, and set during initialisation
|
||||
* phase.
|
||||
*/
|
||||
struct spm_partition_static_data_t {
|
||||
uint32_t partition_id;
|
||||
uint32_t partition_flags;
|
||||
uint32_t partition_priority;
|
||||
sp_init_function partition_init;
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds the fields that define a partition for SPM. The fields are further
|
||||
* divided to structures, to keep the related fields close to each other.
|
||||
*/
|
||||
struct spm_partition_desc_t {
|
||||
struct spm_partition_static_data_t static_data;
|
||||
struct spm_partition_runtime_data_t runtime_data;
|
||||
struct tfm_spm_partition_platform_data_t *platform_data;
|
||||
#if (TFM_LVL != 1) || defined(TFM_PSA_API)
|
||||
struct tfm_spm_partition_memory_data_t memory_data;
|
||||
#endif
|
||||
#ifdef TFM_PSA_API
|
||||
struct tfm_thrd_ctx sp_thrd;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Macros to pick linker symbols and allow to form the partition data base */
|
||||
#define REGION(a, b, c) a##b##c
|
||||
#define REGION_NAME(a, b, c) REGION(a, b, c)
|
||||
/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error.
|
||||
TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not
|
||||
hve that in mbed-os build yet.
|
||||
*/
|
||||
#if (TFM_LVL == 1)
|
||||
#define REGION_DECLARE(a, b, c)
|
||||
#else
|
||||
#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
|
||||
#define PART_REGION_ADDR(partition, region) \
|
||||
(uint32_t)®ION_NAME(Image$$, partition, region)
|
||||
#endif
|
||||
|
||||
#endif /* __SPM_DB_H__ */
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPM_DB_SETUP_H__
|
||||
#define __SPM_DB_SETUP_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "spm_db.h"
|
||||
|
||||
/**
|
||||
* \brief Get the index of a partition.
|
||||
*
|
||||
* Gets the index of a partition in the partition db based on the partition ID
|
||||
* provided as a parameter.
|
||||
*
|
||||
* \param[in] partition_idx The index of the partition
|
||||
*
|
||||
* \return \ref INVALID_PARTITION_IDX if the provided index is invalid. The
|
||||
* index of the partition otherwise.
|
||||
*/
|
||||
uint32_t get_partition_idx(uint32_t partition_id);
|
||||
|
||||
struct spm_partition_db_t {
|
||||
uint32_t is_init;
|
||||
uint32_t partition_count;
|
||||
uint32_t running_partition_idx;
|
||||
struct spm_partition_desc_t partitions[SPM_MAX_PARTITIONS];
|
||||
};
|
||||
|
||||
#define PARTITION_INIT_STATIC_DATA(data, partition, flags, id, priority) \
|
||||
do { \
|
||||
data.partition_id = partition##_ID; \
|
||||
data.partition_flags = flags; \
|
||||
data.partition_priority = TFM_PRIORITY(priority); \
|
||||
} while (0)
|
||||
|
||||
/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error.
|
||||
TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not
|
||||
hve that in mbed-os build yet.
|
||||
*/
|
||||
#if (TFM_LVL == 1)
|
||||
#define PARTITION_INIT_MEMORY_DATA(data, partition)
|
||||
#else
|
||||
#define PARTITION_INIT_MEMORY_DATA(data, partition) \
|
||||
do { \
|
||||
data.code_start = PART_REGION_ADDR(partition, $$Base); \
|
||||
data.code_limit = PART_REGION_ADDR(partition, $$Limit); \
|
||||
data.ro_start = PART_REGION_ADDR(partition, $$RO$$Base); \
|
||||
data.ro_limit = PART_REGION_ADDR(partition, $$RO$$Limit); \
|
||||
data.rw_start = PART_REGION_ADDR(partition, _DATA$$RW$$Base); \
|
||||
data.rw_limit = PART_REGION_ADDR(partition, _DATA$$RW$$Limit); \
|
||||
data.zi_start = PART_REGION_ADDR(partition, _DATA$$ZI$$Base); \
|
||||
data.zi_limit = PART_REGION_ADDR(partition, _DATA$$ZI$$Limit); \
|
||||
data.stack_bottom = PART_REGION_ADDR(partition, _STACK$$ZI$$Base); \
|
||||
data.stack_top = PART_REGION_ADDR(partition, _STACK$$ZI$$Limit); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#if TFM_LVL == 1
|
||||
#define PARTITION_INIT_RUNTIME_DATA(data, partition) \
|
||||
do { \
|
||||
data.partition_state = SPM_PARTITION_STATE_UNINIT; \
|
||||
} while (0)
|
||||
#else
|
||||
#define PARTITION_INIT_RUNTIME_DATA(data, partition) \
|
||||
do { \
|
||||
data.partition_state = SPM_PARTITION_STATE_UNINIT; \
|
||||
/* The top of the stack is reserved for the iovec */ \
|
||||
/* parameters of the service called. That's why in */ \
|
||||
/* data.stack_ptr we extract sizeof(struct iovec_args_t) */ \
|
||||
/* from the limit. */ \
|
||||
data.stack_ptr = \
|
||||
PART_REGION_ADDR(partition, _STACK$$ZI$$Limit - \
|
||||
sizeof(struct iovec_args_t)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define PARTITION_DECLARE(partition, flag, type, id, priority, part_stack_size) \
|
||||
do { \
|
||||
REGION_DECLARE(Image$$, partition, $$Base); \
|
||||
REGION_DECLARE(Image$$, partition, $$Limit); \
|
||||
REGION_DECLARE(Image$$, partition, $$RO$$Base); \
|
||||
REGION_DECLARE(Image$$, partition, $$RO$$Limit); \
|
||||
REGION_DECLARE(Image$$, partition, _DATA$$RW$$Base); \
|
||||
REGION_DECLARE(Image$$, partition, _DATA$$RW$$Limit); \
|
||||
REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Base); \
|
||||
REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Limit); \
|
||||
REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Base); \
|
||||
REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Limit); \
|
||||
int32_t flags = flag; \
|
||||
if (tfm_memcmp(type, TFM_PARTITION_TYPE_APP, \
|
||||
strlen(TFM_PARTITION_TYPE_APP)) == 0) { \
|
||||
flags |= SPM_PART_FLAG_APP_ROT; \
|
||||
} else if (tfm_memcmp(type, TFM_PARTITION_TYPE_PSA, \
|
||||
strlen(TFM_PARTITION_TYPE_PSA)) == 0) { \
|
||||
flags |= SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT; \
|
||||
} else { \
|
||||
return SPM_ERR_INVALID_CONFIG; \
|
||||
} \
|
||||
struct spm_partition_desc_t *part_ptr; \
|
||||
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \
|
||||
return SPM_ERR_INVALID_CONFIG; \
|
||||
} \
|
||||
__attribute__((section(".data.partitions_stacks"))) \
|
||||
static uint8_t partition##_stack[part_stack_size] __attribute__((aligned(8))); \
|
||||
part_ptr = &(g_spm_partition_db.partitions[ \
|
||||
g_spm_partition_db.partition_count]); \
|
||||
part_ptr->memory_data.stack_bottom = (uint32_t)partition##_stack; \
|
||||
part_ptr->memory_data.stack_top = part_ptr->memory_data.stack_bottom + part_stack_size; \
|
||||
PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \
|
||||
id, priority); \
|
||||
PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \
|
||||
PARTITION_INIT_MEMORY_DATA(part_ptr->memory_data, partition); \
|
||||
++g_spm_partition_db.partition_count; \
|
||||
} while (0)
|
||||
|
||||
#define PARTITION_ADD_INIT_FUNC(partition, init_func) \
|
||||
do { \
|
||||
extern int32_t init_func(void); \
|
||||
uint32_t partition_idx = get_partition_idx(partition##_ID); \
|
||||
struct spm_partition_desc_t *part_ptr = \
|
||||
&(g_spm_partition_db.partitions[partition_idx]); \
|
||||
part_ptr->static_data.partition_init = init_func; \
|
||||
} while (0)
|
||||
|
||||
#define PARTITION_ADD_PERIPHERAL(partition, peripheral) \
|
||||
do { \
|
||||
uint32_t partition_idx = get_partition_idx(partition##_ID); \
|
||||
struct spm_partition_desc_t *part_ptr = \
|
||||
&(g_spm_partition_db.partitions[partition_idx]); \
|
||||
part_ptr->platform_data = peripheral; \
|
||||
} while (0)
|
||||
|
||||
#endif /* __SPM_DB_SETUP_H__ */
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SPM_PARTITION_DEFS_H__
|
||||
#define __SPM_PARTITION_DEFS_H__
|
||||
|
||||
/* FixMe: allocations to be settled.
|
||||
* 8 bits reserved by TFM for secure partition Id in this prototype
|
||||
*/
|
||||
#define TFM_SP_BASE 256
|
||||
|
||||
/* A reserved partition ID that is used for uninitialised data */
|
||||
#define INVALID_PARTITION_ID (~0U)
|
||||
|
||||
/* ***** partition ID-s internal to the TFM ***** */
|
||||
#define TFM_INTERNAL_PARTITIONS (2)
|
||||
|
||||
/* From the SPM point of view the non secure processing environment is handled
|
||||
* as a special secure partition. This simplifies the context switch
|
||||
* operations.
|
||||
*/
|
||||
#define TFM_SP_NON_SECURE_ID (0)
|
||||
/* A dummy partition for TFM_SP_CORE is created to handle secure partition
|
||||
* calls done directly from the core, before NS execution started.
|
||||
*/
|
||||
#define TFM_SP_CORE_ID (1)
|
||||
|
||||
#include "tfm_partition_defs.inc"
|
||||
|
||||
/* This limit is only used to define the size of the database reserved for
|
||||
* partitions. There's no requirement that it match the number of partitions
|
||||
* that get registered in a specific build
|
||||
*/
|
||||
#define SPM_MAX_PARTITIONS (TFM_MAX_USER_PARTITIONS + TFM_INTERNAL_PARTITIONS)
|
||||
|
||||
#endif /* __SPM_PARTITION_DEFS_H__ */
|
|
@ -1,111 +0,0 @@
|
|||
# TF-M integration to Mbed-OS
|
||||
This document is an initial draft for TF-M for Mbed-OS porting guide .
|
||||
|
||||
## Audience
|
||||
This guide is intended for developers wishing to port Mbed-OS with TF-M used as a secure kernel for ARMv8-M targets.
|
||||
|
||||
Prior knowledge with both TF-M & Mbed-OS concepts is assumed.
|
||||
|
||||
## Build system concepts:
|
||||
|
||||
Mbed-OS build system is based on [Mbed-CLI](https://github.com/ARMmbed/mbed-cli).
|
||||
Mbed-CLI build system performs lookup for source and header files within project directory and adds them all to a build. All folders will be scanned for sources except for:
|
||||
- folders starting with `TARGET_*`
|
||||
- folders starting with `COMPONENT_*`
|
||||
- folders starting with `FEATURE_*`
|
||||
- folders starting with `TESTS_*` (not true for `mbed test` builds)
|
||||
- files and folders listed in `.mbedignore`
|
||||
|
||||
The ignored folders listed above can be explicitly added to a compilation by adding following keys to a target description in `targets.json`:
|
||||
- adding `extra_labels_add`, `inherits` and `sub_target` for adding `TARGET_*`
|
||||
- adding `components_add` for adding `COMPONENT_*`
|
||||
- `features_add` for adding `FEATURE_*`
|
||||
|
||||
TF-M is built as bare-metal in a secure target, in order to build a secure target with TF-M as its' kernel need to add `--app-config <MBED-OS-ROOT>/tools/psa/tfm/mbed_app.json` to the build command of the secure target.
|
||||
|
||||
## Build hooks
|
||||
|
||||
Mbed-OS testing tools are designed to work with a single image (`.bin` or `.hex`).
|
||||
When building mbed-os for TF-M targets two images are created. One for normal world(NW) and one for TrustZone(TZ).
|
||||
Mbed-OS build system provides `post_binary_hook` that allows executing arbitrary Python script for merging NW and TZ images. Typically `post_binary_hook` is added to NW target and assumes TZ target images as a prerequisite.
|
||||
|
||||
## Porting TF-M targets
|
||||
|
||||
Typically firmware for TF-M targets consist of 2 or more images: normal world and TrustZone image. More images can be present in case boot loaders are used.
|
||||
Two images must be built and linked separately. TrustZone image must be built first.
|
||||
|
||||
There may be code and/or header files sharing between the two targets.
|
||||
Nested folder layout typically provides more easy code reuse between two targets:
|
||||
Example:
|
||||
|
||||
```txt
|
||||
└── tragets
|
||||
└── TARGET_<VENDOR>
|
||||
└── TARGET_<BOARD>
|
||||
├── common_files <-- files shared between NW and TZ images
|
||||
├── TARGET_<BOARD>_NS
|
||||
│ └── normal_world_files <-- files only to be included for NW build
|
||||
└── TARGET_<BOARD>_S
|
||||
└── trustzone_files <-- files only to be included for TZ build
|
||||
```
|
||||
|
||||
The target should be represented in a following way in `target.json` (`MUSCA_A1` is taken for example and should be substituted):
|
||||
```json
|
||||
...
|
||||
"ARM_MUSCA_A1": {
|
||||
"public": false,
|
||||
"inherits": ["Target"],
|
||||
"supported_toolchains": ["ARMC6", "GCC_ARM"],
|
||||
"default_toolchain": "ARMC6",
|
||||
"extra_labels": ["ARM_SSG", "MUSCA_A1"],
|
||||
},
|
||||
"ARM_MUSCA_A1_NS": {
|
||||
"inherits": ["NSPE_Target", "ARM_MUSCA_A1"],
|
||||
"core": "Cortex-M33-NS",
|
||||
"device_has_add": ["INTERRUPTIN", "LPTICKER", "SERIAL", "SLEEP", "USTICKER"],
|
||||
"macros": [
|
||||
"MBED_FAULT_HANDLER_DISABLED",
|
||||
"MBEDTLS_PSA_CRYPTO_C"
|
||||
],
|
||||
"extra_labels_add": ["MUSCA_A1_NS", "PSA", "TFM"],
|
||||
"post_binary_hook": {"function": "ArmMuscaA1Code.binary_hook"}
|
||||
},
|
||||
"ARM_MUSCA_A1_S": {
|
||||
"inherits": ["SPE_Target", "ARM_MUSCA_A1"],
|
||||
"core": "Cortex-M33",
|
||||
"device_has_add": ["FLASH"],
|
||||
"macros": [
|
||||
"MBED_MPU_CUSTOM",
|
||||
"MBEDTLS_PSA_CRYPTO_SPM",
|
||||
"MBEDTLS_PSA_CRYPTO_C",
|
||||
"MBEDTLS_ENTROPY_NV_SEED"
|
||||
],
|
||||
"components_add": ["FLASHIAP"],
|
||||
"extra_labels_add": ["MUSCA_A1_S", "PSA", "TFM"]
|
||||
},
|
||||
```
|
||||
|
||||
Example details:
|
||||
- Secure target:
|
||||
- `"device_has_add": ["FLASH"]` and `"components_add": ["FLASHIAP"]` for enabling storage stack. Required by PSA Internal storage service.
|
||||
- `"extra_labels_add": ["PSA", "TFM"]` are required to add PSA services and TF-M SPM implementation sources to a compilation
|
||||
- all the macros from the example above are required
|
||||
- must inherit from `SPE_Target`
|
||||
- Nonsecure target:
|
||||
- must inherit from `NSPE_Target`
|
||||
- `"extra_labels_add": ["PSA", "TFM"]` are required to add PSA services and TF-M SPM implementation sources to a compilation
|
||||
- all the macros from the example above are required
|
||||
- `post_binary_hook` is used to combine secure and non-secure images
|
||||
|
||||
### HAL
|
||||
For porting Mbed-OS & TF-M both Mbed-OS and TF-M HAL layers should be created.
|
||||
|
||||
#### Mbed-OS HAL:
|
||||
Follow instructions for [Mbed-OS HAL porting](https://os.mbed.com/docs/mbed-os/v5.11/porting/porting-hal-modules.html)
|
||||
|
||||
#### TF-M:
|
||||
Mbed-OS contains customized TF-M version. TF-M services reference implementation was replaced by Mbed-OS version. Thus TF-M has different HAL layer comparing to vanilla [TF-M reference implementation](https://git.trustedfirmware.org/trusted-firmware-m.git/about/).
|
||||
|
||||
The porting layer consists of:
|
||||
- All functions listed in: `components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h`
|
||||
- Flash API `mbed-os/hal/flash_api.h` implementation is required for TZ image. It is used by PSA Internal trusted storage implementation.
|
|
@ -1,253 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 ARM Limited. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// ---------------------------------- Includes ---------------------------------
|
||||
#include "psa/client.h"
|
||||
#include "psa/service.h"
|
||||
|
||||
#include "mbed_spm_partitions.h"
|
||||
#include "psa_initial_attestation_api.h"
|
||||
#include "psa_attest_inject_key.h"
|
||||
#include "psa_inject_attestation_key_impl.h"
|
||||
#include "attestation.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "psa/crypto.h"
|
||||
|
||||
int32_t g_caller_id = 0;
|
||||
|
||||
static void set_caller_id(psa_msg_t *msg)
|
||||
{
|
||||
g_caller_id = msg->client_id;
|
||||
}
|
||||
|
||||
// ------------------------- Partition's Main Thread ---------------------------
|
||||
|
||||
static void psa_attest_get_token(void)
|
||||
{
|
||||
psa_msg_t msg = { 0 };
|
||||
enum psa_attest_err_t status = PSA_ATTEST_ERR_SUCCESS;
|
||||
|
||||
if (PSA_SUCCESS != psa_get(PSA_ATTEST_GET_TOKEN, &msg)) {
|
||||
return;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
uint8_t *challenge_buff = NULL;
|
||||
uint8_t *token_buff = NULL;
|
||||
uint32_t bytes_read = 0;
|
||||
|
||||
challenge_buff = calloc(1, msg.in_size[0]);
|
||||
if (challenge_buff == NULL) {
|
||||
status = PSA_ATTEST_ERR_GENERAL;
|
||||
break;
|
||||
}
|
||||
bytes_read = psa_read(msg.handle, 0,
|
||||
challenge_buff, msg.in_size[0]);
|
||||
if (bytes_read != msg.in_size[0]) {
|
||||
free(challenge_buff);
|
||||
SPM_PANIC("SPM read length mismatch");
|
||||
}
|
||||
|
||||
token_buff = calloc(1, msg.out_size[0]);
|
||||
if (token_buff == NULL) {
|
||||
status = PSA_ATTEST_ERR_GENERAL;
|
||||
free(challenge_buff);
|
||||
break;
|
||||
}
|
||||
|
||||
psa_invec in_vec[1] = { { challenge_buff, msg.in_size[0] } };
|
||||
psa_outvec out_vec[1] = { { token_buff, msg.out_size[0] } };
|
||||
|
||||
status = attest_init();
|
||||
if (status != PSA_ATTEST_ERR_SUCCESS) {
|
||||
free(challenge_buff);
|
||||
free(token_buff);
|
||||
break;
|
||||
}
|
||||
|
||||
set_caller_id(&msg);
|
||||
status = initial_attest_get_token(in_vec, 1, out_vec, 1);
|
||||
if (status == PSA_ATTEST_ERR_SUCCESS) {
|
||||
psa_write(msg.handle, 0, out_vec[0].base, out_vec[0].len);
|
||||
}
|
||||
|
||||
free(challenge_buff);
|
||||
free(token_buff);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, status);
|
||||
}
|
||||
|
||||
static void psa_attest_get_token_size(void)
|
||||
{
|
||||
psa_msg_t msg = { 0 };
|
||||
enum psa_attest_err_t status = PSA_ATTEST_ERR_SUCCESS;
|
||||
|
||||
if (PSA_SUCCESS != psa_get(PSA_ATTEST_GET_TOKEN_SIZE, &msg)) {
|
||||
return;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
uint32_t challenge_size;
|
||||
uint32_t token_size;
|
||||
uint32_t bytes_read = 0;
|
||||
|
||||
bytes_read = psa_read(msg.handle, 0,
|
||||
&challenge_size, msg.in_size[0]);
|
||||
if (bytes_read != msg.in_size[0]) {
|
||||
SPM_PANIC("SPM read length mismatch");
|
||||
}
|
||||
|
||||
psa_invec in_vec[1] = { { &challenge_size, msg.in_size[0] } };
|
||||
psa_outvec out_vec[1] = { { &token_size, msg.out_size[0] } };
|
||||
|
||||
status = attest_init();
|
||||
if (status != PSA_ATTEST_ERR_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
set_caller_id(&msg);
|
||||
status = initial_attest_get_token_size(in_vec, 1, out_vec, 1);
|
||||
if (status == PSA_ATTEST_ERR_SUCCESS) {
|
||||
psa_write(msg.handle, 0, out_vec[0].base, out_vec[0].len);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, status);
|
||||
}
|
||||
|
||||
static void psa_attest_inject_key(void)
|
||||
{
|
||||
psa_msg_t msg = { 0 };
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
|
||||
if (PSA_SUCCESS != psa_get(PSA_ATTEST_INJECT_KEY, &msg)) {
|
||||
return;
|
||||
}
|
||||
switch (msg.type) {
|
||||
case PSA_IPC_CONNECT:
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
uint8_t *public_key_data = NULL;
|
||||
size_t public_key_data_length = 0;
|
||||
uint8_t *key_data = NULL;
|
||||
psa_key_type_t type;
|
||||
uint32_t bytes_read = 0;
|
||||
|
||||
if (msg.in_size[0] != sizeof(psa_key_type_t)) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_read = psa_read(msg.handle, 0, &type, msg.in_size[0]);
|
||||
if (bytes_read != msg.in_size[0]) {
|
||||
SPM_PANIC("SPM read length mismatch");
|
||||
}
|
||||
|
||||
public_key_data = calloc(1, msg.out_size[0]);
|
||||
if (public_key_data == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (msg.in_size[1] != 0) {
|
||||
key_data = calloc(1, msg.in_size[1]);
|
||||
if (key_data == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
free(public_key_data);
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_read = psa_read(msg.handle, 1,
|
||||
key_data, msg.in_size[1]);
|
||||
if (bytes_read != msg.in_size[1]) {
|
||||
free(public_key_data);
|
||||
free(key_data);
|
||||
SPM_PANIC("SPM read length mismatch");
|
||||
}
|
||||
}
|
||||
status = psa_attestation_inject_key_impl(key_data,
|
||||
msg.in_size[1],
|
||||
type,
|
||||
public_key_data,
|
||||
msg.out_size[0],
|
||||
&public_key_data_length);
|
||||
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg.handle, 0, public_key_data, public_key_data_length);
|
||||
}
|
||||
|
||||
psa_write(msg.handle, 1,
|
||||
&public_key_data_length, sizeof(public_key_data_length));
|
||||
free(public_key_data);
|
||||
if (key_data != NULL) {
|
||||
free(key_data);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %d!", (int)(msg.type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
psa_reply(msg.handle, status);
|
||||
}
|
||||
|
||||
void attest_main(void *ptr)
|
||||
{
|
||||
while (1) {
|
||||
uint32_t signals = psa_wait(ATTEST_SRV_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
if (signals & PSA_ATTEST_GET_TOKEN) {
|
||||
psa_attest_get_token();
|
||||
}
|
||||
if (signals & PSA_ATTEST_GET_TOKEN_SIZE) {
|
||||
psa_attest_get_token_size();
|
||||
}
|
||||
if (signals & PSA_ATTEST_INJECT_KEY) {
|
||||
psa_attest_inject_key();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"name": "ATTEST_SRV",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000025",
|
||||
"entry_point": "attest_main",
|
||||
"stack_size": "0x2000",
|
||||
"heap_size": "0x2000",
|
||||
"services": [
|
||||
{
|
||||
"name": "PSA_ATTEST_GET_TOKEN_ID",
|
||||
"identifier": "0x00000F10",
|
||||
"signal": "PSA_ATTEST_GET_TOKEN",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ATTEST_GET_TOKEN_SIZE_ID",
|
||||
"identifier": "0x00000F11",
|
||||
"signal": "PSA_ATTEST_GET_TOKEN_SIZE",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ATTEST_INJECT_KEY_ID",
|
||||
"identifier": "0x00000F12",
|
||||
"signal": "PSA_ATTEST_INJECT_KEY",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
}
|
||||
],
|
||||
"extern_sids": [
|
||||
"PSA_CRYPTO_INIT_ID",
|
||||
"PSA_HASH_ID",
|
||||
"PSA_ASYMMETRIC_ID",
|
||||
"PSA_KEY_MNG_ID",
|
||||
"PSA_CRYPTO_FREE_ID",
|
||||
"PSA_KEY_DERIVATION_ID",
|
||||
"PSA_PLATFORM_LC_GET"
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/psa_attestation_partition.c"
|
||||
]
|
||||
}
|
|
@ -14,9 +14,4 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifdef PSA_CRYPTO_SECURE
|
||||
#include "crypto_struct_spe.h"
|
||||
#else
|
||||
#include "crypto_struct_ipc.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*/
|
||||
/**
|
||||
* \file psa/crypto_spe.h
|
||||
* \brief Platform Security Architecture cryptography module
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_SPE_H
|
||||
#define PSA_CRYPTO_SPE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define psa_crypto_init psa_sec_crypto_init
|
||||
#define psa_get_key_attributes psa_sec_get_key_attributes
|
||||
#define psa_reset_key_attributes psa_sec_reset_key_attributes
|
||||
#define psa_open_key psa_sec_open_key
|
||||
#define psa_close_key psa_sec_close_key
|
||||
#define psa_import_key psa_sec_import_key
|
||||
#define psa_destroy_key psa_sec_destroy_key
|
||||
#define psa_export_key psa_sec_export_key
|
||||
#define psa_export_public_key psa_sec_export_public_key
|
||||
#define psa_copy_key psa_sec_copy_key
|
||||
#define psa_hash_compute psa_sec_hash_compute
|
||||
#define psa_hash_compare psa_sec_hash_compare
|
||||
#define psa_hash_setup psa_sec_hash_setup
|
||||
#define psa_hash_update psa_sec_hash_update
|
||||
#define psa_hash_finish psa_sec_hash_finish
|
||||
#define psa_hash_verify psa_sec_hash_verify
|
||||
#define psa_hash_abort psa_sec_hash_abort
|
||||
#define psa_hash_clone psa_sec_hash_clone
|
||||
#define psa_mac_compute psa_sec_mac_compute
|
||||
#define psa_mac_verify psa_sec_mac_verify
|
||||
#define psa_mac_sign_setup psa_sec_mac_sign_setup
|
||||
#define psa_mac_verify_setup psa_sec_mac_verify_setup
|
||||
#define psa_mac_update psa_sec_mac_update
|
||||
#define psa_mac_sign_finish psa_sec_mac_sign_finish
|
||||
#define psa_mac_verify_finish psa_sec_mac_verify_finish
|
||||
#define psa_mac_abort psa_sec_mac_abort
|
||||
#define psa_cipher_encrypt psa_sec_cipher_encrypt
|
||||
#define psa_cipher_decrypt psa_sec_cipher_decrypt
|
||||
#define psa_cipher_encrypt_setup psa_sec_cipher_encrypt_setup
|
||||
#define psa_cipher_decrypt_setup psa_sec_cipher_decrypt_setup
|
||||
#define psa_cipher_generate_iv psa_sec_cipher_generate_iv
|
||||
#define psa_cipher_set_iv psa_sec_cipher_set_iv
|
||||
#define psa_cipher_update psa_sec_cipher_update
|
||||
#define psa_cipher_finish psa_sec_cipher_finish
|
||||
#define psa_cipher_abort psa_sec_cipher_abort
|
||||
#define psa_aead_encrypt psa_sec_aead_encrypt
|
||||
#define psa_aead_decrypt psa_sec_aead_decrypt
|
||||
#define psa_aead_encrypt_setup psa_sec_aead_encrypt_setup
|
||||
#define psa_aead_decrypt_setup psa_sec_aead_decrypt_setup
|
||||
#define psa_aead_generate_nonce psa_sec_aead_generate_nonce
|
||||
#define psa_aead_set_nonce psa_sec_aead_set_nonce
|
||||
#define psa_aead_set_lengths psa_sec_aead_set_lengths
|
||||
#define psa_aead_update_ad psa_sec_aead_update_ad
|
||||
#define psa_aead_update psa_sec_aead_update
|
||||
#define psa_aead_finish psa_sec_aead_finish
|
||||
#define psa_aead_verify psa_sec_aead_verify
|
||||
#define psa_aead_abort psa_sec_aead_abort
|
||||
#define psa_sign_hash psa_sec_sign_hash
|
||||
#define psa_verify_hash psa_sec_verify_hash
|
||||
#define psa_asymmetric_encrypt psa_sec_asymmetric_encrypt
|
||||
#define psa_asymmetric_decrypt psa_sec_asymmetric_decrypt
|
||||
#define psa_key_derivation_setup psa_sec_key_derivation_setup
|
||||
#define psa_key_derivation_get_capacity psa_sec_key_derivation_get_capacity
|
||||
#define psa_key_derivation_set_capacity psa_sec_key_derivation_set_capacity
|
||||
#define psa_key_derivation_input_bytes psa_sec_key_derivation_input_bytes
|
||||
#define psa_key_derivation_input_key psa_sec_key_derivation_input_key
|
||||
#define psa_key_derivation_key_agreement psa_sec_key_derivation_key_agreement
|
||||
#define psa_key_derivation_output_bytes psa_sec_key_derivation_output_bytes
|
||||
#define psa_key_derivation_output_key psa_sec_key_derivation_output_key
|
||||
#define psa_key_derivation_abort psa_sec_key_derivation_abort
|
||||
#define psa_raw_key_agreement psa_sec_raw_key_agreement
|
||||
#define psa_generate_random psa_sec_generate_random
|
||||
#define psa_generate_key psa_sec_generate_key
|
||||
|
||||
#define mbedtls_psa_crypto_free mbedtls_psa_sec_crypto_free
|
||||
#define mbedtls_psa_inject_entropy mbedtls_psa_sec_inject_entropy
|
||||
#define psa_set_key_domain_parameters psa_sec_set_key_domain_parameters
|
||||
#define psa_get_key_domain_parameters psa_sec_get_key_domain_parameters
|
||||
|
||||
#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER 1
|
||||
|
||||
#include "crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The file "crypto_extra.h" contains vendor-specific definitions. This
|
||||
* can include vendor-defined algorithms, extra functions, etc. */
|
||||
#include "crypto_extra.h"
|
||||
|
||||
#endif /* PSA_CRYPTO_SPE_H */
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* 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/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "psa_crypto_access_control.h"
|
||||
#include "psa_crypto_core.h"
|
||||
#include "psa_crypto_slot_management.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];
|
||||
|
||||
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;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +0,0 @@
|
|||
{
|
||||
"name": "CRYPTO_SRV",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000023",
|
||||
"entry_point": "crypto_main",
|
||||
"stack_size": "0x4000",
|
||||
"heap_size": "0x400",
|
||||
"services": [
|
||||
{
|
||||
"name": "PSA_CRYPTO_INIT_ID",
|
||||
"identifier": "0x00000F00",
|
||||
"signal": "PSA_CRYPTO_INIT",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_MAC_ID",
|
||||
"identifier": "0x00000F01",
|
||||
"signal": "PSA_MAC",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_HASH_ID",
|
||||
"identifier": "0x00000F02",
|
||||
"signal": "PSA_HASH",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ASYMMETRIC_ID",
|
||||
"identifier": "0x00000F03",
|
||||
"signal": "PSA_ASYMMETRIC",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_SYMMETRIC_ID",
|
||||
"identifier": "0x00000F04",
|
||||
"signal": "PSA_SYMMETRIC",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_AEAD_ID",
|
||||
"identifier": "0x00000F05",
|
||||
"signal": "PSA_AEAD",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_KEY_MNG_ID",
|
||||
"identifier": "0x00000F06",
|
||||
"signal": "PSA_KEY_MNG",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_RNG_ID",
|
||||
"identifier": "0x00000F07",
|
||||
"signal": "PSA_RNG",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_CRYPTO_FREE_ID",
|
||||
"identifier": "0x00000F08",
|
||||
"signal": "PSA_CRYPTO_FREE",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_KEY_DERIVATION_ID",
|
||||
"identifier": "0x00000F09",
|
||||
"signal": "PSA_KEY_DERIVATION",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ENTROPY_ID",
|
||||
"identifier": "0x00000F0A",
|
||||
"signal": "PSA_ENTROPY_INJECT",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "STRICT"
|
||||
}
|
||||
],
|
||||
"extern_sids": [
|
||||
"PSA_ITS_GET",
|
||||
"PSA_ITS_SET",
|
||||
"PSA_ITS_INFO",
|
||||
"PSA_ITS_REMOVE"
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/psa_crypto_partition.c"
|
||||
]
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
/* Copyright (c) 2019-2020 Arm Limited
|
||||
*
|
||||
* 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 "mbed_spm_partitions.h"
|
||||
#include "platform_srv_impl.h"
|
||||
#include "psa/lifecycle.h"
|
||||
#include "psa/internal_trusted_storage.h"
|
||||
#include "psa/service.h"
|
||||
|
||||
#define INPUT_BUFFER_SIZE 64
|
||||
#define OUTPUT_BUFFER_SIZE 64
|
||||
|
||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
|
||||
|
||||
static psa_status_t lifecycle_get(psa_msg_t *msg)
|
||||
{
|
||||
uint32_t lc_state;
|
||||
|
||||
if (msg->out_size[0] != sizeof(lc_state)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
psa_status_t status = psa_platfrom_lifecycle_get_impl(&lc_state);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &lc_state, sizeof(lc_state));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t lifecycle_change_request(psa_msg_t *msg)
|
||||
{
|
||||
uint32_t lc_state;
|
||||
|
||||
if (msg->in_size[0] != sizeof(lc_state)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
if (psa_read(msg->handle, 0, &lc_state, sizeof(lc_state)) != sizeof(lc_state)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
return psa_platfrom_lifecycle_change_request_impl(lc_state);
|
||||
|
||||
}
|
||||
|
||||
static MBED_NORETURN psa_status_t system_reset_request(psa_msg_t *msg)
|
||||
{
|
||||
(void)msg;
|
||||
mbed_psa_system_reset_impl();
|
||||
}
|
||||
|
||||
static enum tfm_platform_err_t
|
||||
platform_sp_ioctl_ipc(const psa_msg_t *msg) {
|
||||
void *input = NULL;
|
||||
void *output = NULL;
|
||||
psa_invec invec = {0};
|
||||
psa_outvec outvec = {0};
|
||||
uint8_t input_buffer[INPUT_BUFFER_SIZE] = {0};
|
||||
uint8_t output_buffer[OUTPUT_BUFFER_SIZE] = {0};
|
||||
tfm_platform_ioctl_req_t request = 0;
|
||||
enum tfm_platform_err_t ret = TFM_PLATFORM_ERR_SYSTEM_ERROR;
|
||||
size_t num = 0;
|
||||
uint32_t in_len = PSA_MAX_IOVEC;
|
||||
uint32_t out_len = PSA_MAX_IOVEC;
|
||||
|
||||
while ((in_len > 0) && (msg->in_size[in_len - 1] == 0))
|
||||
{
|
||||
in_len--;
|
||||
}
|
||||
|
||||
while ((out_len > 0) && (msg->out_size[out_len - 1] == 0))
|
||||
{
|
||||
out_len--;
|
||||
}
|
||||
|
||||
if ((in_len < 1) || (in_len > 2) ||
|
||||
(out_len > 1))
|
||||
{
|
||||
return TFM_PLATFORM_ERR_SYSTEM_ERROR;
|
||||
}
|
||||
|
||||
num = psa_read(msg->handle, 0, &request, sizeof(request));
|
||||
if (num != sizeof(request))
|
||||
{
|
||||
return PSA_ERROR_PROGRAMMER_ERROR;
|
||||
}
|
||||
|
||||
if (in_len > 1)
|
||||
{
|
||||
if (msg->in_size[1] > INPUT_BUFFER_SIZE) {
|
||||
return PSA_ERROR_PROGRAMMER_ERROR;
|
||||
}
|
||||
num = psa_read(msg->handle, 1, &input_buffer, msg->in_size[1]);
|
||||
if (num != msg->in_size[1]) {
|
||||
return PSA_ERROR_PROGRAMMER_ERROR;
|
||||
}
|
||||
invec.base = input_buffer;
|
||||
invec.len = msg->in_size[1];
|
||||
input = &invec;
|
||||
}
|
||||
|
||||
if (out_len > 0)
|
||||
{
|
||||
if (msg->out_size[0] > OUTPUT_BUFFER_SIZE) {
|
||||
return PSA_ERROR_PROGRAMMER_ERROR;
|
||||
}
|
||||
outvec.base = output_buffer;
|
||||
outvec.len = msg->out_size[0];
|
||||
output = &outvec;
|
||||
}
|
||||
|
||||
ret = tfm_platform_hal_ioctl(request, input, output);
|
||||
|
||||
if (output != NULL)
|
||||
{
|
||||
psa_write(msg->handle, 0, outvec.base, outvec.len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static psa_status_t platform_ioctl(psa_msg_t *msg)
|
||||
{
|
||||
/* platform_sp_ioctl_ipc returns either psa_status_t or one of the
|
||||
* following errorcodes:
|
||||
* enum tfm_platform_err_t {
|
||||
* TFM_PLATFORM_ERR_SUCCESS = 0,
|
||||
* TFM_PLATFORM_ERR_SYSTEM_ERROR,
|
||||
* TFM_PLATFORM_ERR_INVALID_PARAM,
|
||||
* TFM_PLATFORM_ERR_NOT_SUPPORTED,
|
||||
*
|
||||
* TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX
|
||||
* };
|
||||
*/
|
||||
return platform_sp_ioctl_ipc(msg);
|
||||
}
|
||||
|
||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
switch (msg->type) {
|
||||
case PSA_IPC_CONNECT: //fallthrough
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
status = handler(msg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %lu!", msg->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
psa_reply(msg->handle, status);
|
||||
}
|
||||
|
||||
void platform_partition_entry(void *ptr)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
while (1) {
|
||||
signals = psa_wait(PLATFORM_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
if ((signals & PSA_PLATFORM_LC_GET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_PLATFORM_LC_GET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, lifecycle_get);
|
||||
}
|
||||
if ((signals & PSA_PLATFORM_LC_SET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_PLATFORM_LC_SET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, lifecycle_change_request);
|
||||
}
|
||||
if ((signals & PSA_PLATFORM_SYSTEM_RESET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_PLATFORM_SYSTEM_RESET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, system_reset_request);
|
||||
}
|
||||
if ((signals & PSA_PLATFORM_IOCTL_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_PLATFORM_IOCTL_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, platform_ioctl);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"name": "PLATFORM",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x00000008",
|
||||
"entry_point": "platform_partition_entry",
|
||||
"stack_size": "0x400",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "PSA_PLATFORM_LC_GET",
|
||||
"identifier": "0x00011000",
|
||||
"signal": "PSA_PLATFORM_LC_GET_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_PLATFORM_LC_SET",
|
||||
"identifier": "0x00011001",
|
||||
"signal": "PSA_PLATFORM_LC_SET_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_PLATFORM_SYSTEM_RESET",
|
||||
"identifier": "0x00011002",
|
||||
"signal": "PSA_PLATFORM_SYSTEM_RESET_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_PLATFORM_IOCTL",
|
||||
"identifier": "0x00011003",
|
||||
"signal": "PSA_PLATFORM_IOCTL_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
}
|
||||
],
|
||||
"extern_sids": [
|
||||
"PSA_ITS_RESET"
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/platform_partition.c"
|
||||
]
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
/* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "psa/client.h"
|
||||
#include "psa/service.h"
|
||||
#include "mbed_spm_partitions.h"
|
||||
#include "psa/internal_trusted_storage.h"
|
||||
#include "pits_impl.h"
|
||||
#include "mbed_error.h"
|
||||
|
||||
int kv_init_storage_config();
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef psa_status_t (*SignalHandler)(psa_msg_t *);
|
||||
|
||||
static psa_status_t storage_set(psa_msg_t *msg)
|
||||
{
|
||||
psa_storage_uid_t key = 0;
|
||||
void *data = NULL;
|
||||
uint32_t alloc_size = msg->in_size[1];
|
||||
psa_storage_create_flags_t flags = 0;
|
||||
|
||||
if ((msg->in_size[0] != sizeof(key)) || (msg->in_size[2] != sizeof(flags))) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 2, &flags, sizeof(flags)) != sizeof(flags)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
data = malloc(alloc_size);
|
||||
if (data == NULL) {
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 1, data, msg->in_size[1]) != msg->in_size[1]) {
|
||||
free(data);
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
psa_status_t status = psa_its_set_impl(msg->client_id, key, alloc_size, data, flags);
|
||||
memset(data, 0, alloc_size);
|
||||
free(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t storage_get(psa_msg_t *msg)
|
||||
{
|
||||
psa_storage_uid_t key = 0;
|
||||
uint32_t offset = 0;
|
||||
size_t actual_size;
|
||||
|
||||
if ((msg->in_size[0] != sizeof(key)) ||
|
||||
(msg->in_size[1] != sizeof(offset)) ||
|
||||
(msg->out_size[1] != sizeof(actual_size))) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 1, &offset, sizeof(offset)) != sizeof(offset)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
uint8_t *data = (uint8_t *)malloc(msg->out_size[0]);
|
||||
if (data == NULL) {
|
||||
return PSA_ERROR_STORAGE_FAILURE;
|
||||
}
|
||||
|
||||
psa_status_t status = psa_its_get_impl(msg->client_id, key, offset, msg->out_size[0], data, &actual_size);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, data, actual_size);
|
||||
psa_write(msg->handle, 1, &actual_size, sizeof(actual_size));
|
||||
}
|
||||
|
||||
memset(data, 0, msg->out_size[0]);
|
||||
free(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t storage_info(psa_msg_t *msg)
|
||||
{
|
||||
struct psa_storage_info_t info = { 0 };
|
||||
psa_storage_uid_t key = 0;
|
||||
|
||||
if ((msg->in_size[0] != sizeof(key)) || (msg->out_size[0] != sizeof(info))) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
psa_status_t status = psa_its_get_info_impl(msg->client_id, key, &info);
|
||||
if (status == PSA_SUCCESS) {
|
||||
psa_write(msg->handle, 0, &info, msg->out_size[0]);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t storage_remove(psa_msg_t *msg)
|
||||
{
|
||||
psa_storage_uid_t key = 0;
|
||||
|
||||
if (msg->in_size[0] != sizeof(key)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
if (psa_read(msg->handle, 0, &key, sizeof(key)) != sizeof(key)) {
|
||||
return PSA_DROP_CONNECTION;
|
||||
}
|
||||
|
||||
return psa_its_remove_impl(msg->client_id, key);
|
||||
}
|
||||
static psa_status_t storage_reset(psa_msg_t *msg)
|
||||
{
|
||||
(void)msg;
|
||||
return psa_its_reset_impl();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void message_handler(psa_msg_t *msg, SignalHandler handler)
|
||||
{
|
||||
psa_status_t status = PSA_SUCCESS;
|
||||
switch (msg->type) {
|
||||
case PSA_IPC_CONNECT: //fallthrough
|
||||
case PSA_IPC_DISCONNECT: {
|
||||
break;
|
||||
}
|
||||
case PSA_IPC_CALL: {
|
||||
status = handler(msg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SPM_PANIC("Unexpected message type %lu!", msg->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
psa_reply(msg->handle, status);
|
||||
}
|
||||
|
||||
void its_entry(void *ptr)
|
||||
{
|
||||
psa_signal_t signals = 0;
|
||||
psa_msg_t msg = {0};
|
||||
|
||||
while (1) {
|
||||
signals = psa_wait(ITS_WAIT_ANY_SID_MSK, PSA_BLOCK);
|
||||
// KVStore initiation:
|
||||
// - Must be done after the psa_wait() call since only now we know OS initialization is done
|
||||
// - Repeating calls has no effect
|
||||
int kv_status = kv_init_storage_config();
|
||||
if (kv_status != MBED_SUCCESS) {
|
||||
SPM_PANIC("KVStore initiation failed with status %d!", kv_status);
|
||||
}
|
||||
|
||||
if ((signals & PSA_ITS_SET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_ITS_SET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, storage_set);
|
||||
}
|
||||
if ((signals & PSA_ITS_GET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_ITS_GET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, storage_get);
|
||||
}
|
||||
if ((signals & PSA_ITS_INFO_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_ITS_INFO_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, storage_info);
|
||||
}
|
||||
if ((signals & PSA_ITS_REMOVE_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_ITS_REMOVE_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, storage_remove);
|
||||
}
|
||||
if ((signals & PSA_ITS_RESET_MSK) != 0) {
|
||||
if (PSA_SUCCESS != psa_get(PSA_ITS_RESET_MSK, &msg)) {
|
||||
continue;
|
||||
}
|
||||
message_handler(&msg, storage_reset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||
{
|
||||
"name": "ITS",
|
||||
"type": "APPLICATION-ROT",
|
||||
"priority": "NORMAL",
|
||||
"id": "0x0000000A",
|
||||
"entry_point": "its_entry",
|
||||
"stack_size": "0x800",
|
||||
"heap_size": "0x400",
|
||||
"services": [{
|
||||
"name": "PSA_ITS_GET",
|
||||
"identifier": "0x00011A00",
|
||||
"signal": "PSA_ITS_GET_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ITS_SET",
|
||||
"identifier": "0x00011A01",
|
||||
"signal": "PSA_ITS_SET_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ITS_INFO",
|
||||
"identifier": "0x00011A02",
|
||||
"signal": "PSA_ITS_INFO_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ITS_REMOVE",
|
||||
"identifier": "0x00011A03",
|
||||
"signal": "PSA_ITS_REMOVE_MSK",
|
||||
"non_secure_clients": true,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
},
|
||||
{
|
||||
"name": "PSA_ITS_RESET",
|
||||
"identifier": "0x00011A04",
|
||||
"signal": "PSA_ITS_RESET_MSK",
|
||||
"non_secure_clients": false,
|
||||
"minor_version": 1,
|
||||
"minor_policy": "RELAXED"
|
||||
}
|
||||
],
|
||||
"source_files": [
|
||||
"COMPONENT_SPE/its_partition.c"
|
||||
]
|
||||
}
|
|
@ -2102,7 +2102,6 @@ PREDEFINED = DOXYGEN_ONLY \
|
|||
DEVICE_QSPI \
|
||||
DEVICE_STORAGE \
|
||||
DEVICE_WATCHDOG \
|
||||
COMPONENT_SPE \
|
||||
"TFM_LVL=1" \
|
||||
"MBED_DEPRECATED_SINCE(d, m)=" \
|
||||
"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=" \
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"SEARCH_INCLUDES": "YES",
|
||||
"INCLUDE_PATH": "",
|
||||
"INCLUDE_FILE_PATTERNS": "",
|
||||
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE DEVICE_WATCHDOG DEVICE_RESET_REASON COMPONENT_SPE \"TFM_LVL=1\" \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\" \"BLE_ROLE_OBSERVER=1\" \"BLE_ROLE_BROADCASTER=1\" \"BLE_ROLE_PERIPHERAL=1\" \"BLE_ROLE_CENTRAL=1\" \"BLE_FEATURE_GATT_CLIENT=1\" \"BLE_FEATURE_GATT_SERVER=1\" \"BLE_FEATURE_SECURITY=1\" \"BLE_FEATURE_SECURE_CONNECTIONS=1\" \"BLE_FEATURE_SIGNING=1\" \"BLE_FEATURE_PHY_MANAGEMENT=1\" \"BLE_FEATURE_WHITELIST=1\" \"BLE_FEATURE_PRIVACY=1\" \"BLE_FEATURE_PERIODIC_ADVERTISING=1\" \"BLE_FEATURE_EXTENDED_ADVERTISING=1\"",
|
||||
"PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE DEVICE_WATCHDOG DEVICE_RESET_REASON \"TFM_LVL=1\" \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\" \"BLE_ROLE_OBSERVER=1\" \"BLE_ROLE_BROADCASTER=1\" \"BLE_ROLE_PERIPHERAL=1\" \"BLE_ROLE_CENTRAL=1\" \"BLE_FEATURE_GATT_CLIENT=1\" \"BLE_FEATURE_GATT_SERVER=1\" \"BLE_FEATURE_SECURITY=1\" \"BLE_FEATURE_SECURE_CONNECTIONS=1\" \"BLE_FEATURE_SIGNING=1\" \"BLE_FEATURE_PHY_MANAGEMENT=1\" \"BLE_FEATURE_WHITELIST=1\" \"BLE_FEATURE_PRIVACY=1\" \"BLE_FEATURE_PERIODIC_ADVERTISING=1\" \"BLE_FEATURE_EXTENDED_ADVERTISING=1\"",
|
||||
"EXPAND_AS_DEFINED": "",
|
||||
"SKIP_FUNCTION_MACROS": "NO",
|
||||
"STRIP_CODE_COMMENTS": "NO",
|
||||
|
|
|
@ -89,13 +89,13 @@ static void reset_storage_for_compliance_test()
|
|||
|
||||
static void inject_entropy()
|
||||
{
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
|
||||
#if defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
|
||||
for (int i = 0; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
|
||||
seed[i] = i;
|
||||
}
|
||||
mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
|
||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED) || defined(COMPONENT_PSA_SRV_IPC)
|
||||
#endif // defined(MBEDTLS_ENTROPY_NV_SEED)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,522 +0,0 @@
|
|||
/**
|
||||
* \file psa/crypto_struct.h
|
||||
*
|
||||
* \brief PSA cryptography module: Mbed TLS structured type implementations
|
||||
*
|
||||
* \note This file may not be included directly. Applications must
|
||||
* include psa/crypto.h.
|
||||
*
|
||||
* This file contains the definitions of some data structures with
|
||||
* implementation-specific definitions.
|
||||
*
|
||||
* In implementations with isolation between the application and the
|
||||
* cryptography module, it is expected that the front-end and the back-end
|
||||
* would have different versions of this file.
|
||||
*
|
||||
* <h3>Design notes about multipart operation structures</h3>
|
||||
*
|
||||
* Each multipart operation structure contains a `psa_algorithm_t alg`
|
||||
* field which indicates which specific algorithm the structure is for.
|
||||
* When the structure is not in use, `alg` is 0. Most of the structure
|
||||
* consists of a union which is discriminated by `alg`.
|
||||
*
|
||||
* Note that when `alg` is 0, the content of other fields is undefined.
|
||||
* In particular, it is not guaranteed that a freshly-initialized structure
|
||||
* is all-zero: we initialize structures to something like `{0, 0}`, which
|
||||
* is only guaranteed to initializes the first member of the union;
|
||||
* GCC and Clang initialize the whole structure to 0 (at the time of writing),
|
||||
* but MSVC and CompCert don't.
|
||||
*
|
||||
* In Mbed Crypto, multipart operation structures live independently from
|
||||
* the key. This allows Mbed Crypto to free the key objects when destroying
|
||||
* a key slot. If a multipart operation needs to remember the key after
|
||||
* the setup function returns, the operation structure needs to contain a
|
||||
* copy of the key.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2018, ARM Limited, All Rights Reserved
|
||||
* 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.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#ifndef PSA_CRYPTO_STRUCT_H
|
||||
#define PSA_CRYPTO_STRUCT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Include the Mbed TLS configuration file, the way Mbed TLS does it
|
||||
* in each of its header files. */
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/cipher.h"
|
||||
#include "mbedtls/cmac.h"
|
||||
#include "mbedtls/gcm.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/md2.h"
|
||||
#include "mbedtls/md4.h"
|
||||
#include "mbedtls/md5.h"
|
||||
#include "mbedtls/ripemd160.h"
|
||||
#include "mbedtls/sha1.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/sha512.h"
|
||||
|
||||
struct psa_hash_operation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
union
|
||||
{
|
||||
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
|
||||
#if defined(MBEDTLS_MD2_C)
|
||||
mbedtls_md2_context md2;
|
||||
#endif
|
||||
#if defined(MBEDTLS_MD4_C)
|
||||
mbedtls_md4_context md4;
|
||||
#endif
|
||||
#if defined(MBEDTLS_MD5_C)
|
||||
mbedtls_md5_context md5;
|
||||
#endif
|
||||
#if defined(MBEDTLS_RIPEMD160_C)
|
||||
mbedtls_ripemd160_context ripemd160;
|
||||
#endif
|
||||
#if defined(MBEDTLS_SHA1_C)
|
||||
mbedtls_sha1_context sha1;
|
||||
#endif
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
mbedtls_sha256_context sha256;
|
||||
#endif
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
mbedtls_sha512_context sha512;
|
||||
#endif
|
||||
} ctx;
|
||||
};
|
||||
|
||||
#define PSA_HASH_OPERATION_INIT {0, {0}}
|
||||
static inline struct psa_hash_operation_s psa_hash_operation_init( void )
|
||||
{
|
||||
const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
typedef struct
|
||||
{
|
||||
/** The hash context. */
|
||||
struct psa_hash_operation_s hash_ctx;
|
||||
/** The HMAC part of the context. */
|
||||
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||
} psa_hmac_internal_data;
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
|
||||
struct psa_mac_operation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
unsigned int key_set : 1;
|
||||
unsigned int iv_required : 1;
|
||||
unsigned int iv_set : 1;
|
||||
unsigned int has_input : 1;
|
||||
unsigned int is_sign : 1;
|
||||
uint8_t mac_size;
|
||||
union
|
||||
{
|
||||
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
psa_hmac_internal_data hmac;
|
||||
#endif
|
||||
#if defined(MBEDTLS_CMAC_C)
|
||||
mbedtls_cipher_context_t cmac;
|
||||
#endif
|
||||
} ctx;
|
||||
};
|
||||
|
||||
#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}}
|
||||
static inline struct psa_mac_operation_s psa_mac_operation_init( void )
|
||||
{
|
||||
const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
struct psa_cipher_operation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
unsigned int key_set : 1;
|
||||
unsigned int iv_required : 1;
|
||||
unsigned int iv_set : 1;
|
||||
uint8_t iv_size;
|
||||
uint8_t block_size;
|
||||
union
|
||||
{
|
||||
unsigned dummy; /* Enable easier initializing of the union. */
|
||||
mbedtls_cipher_context_t cipher;
|
||||
} ctx;
|
||||
};
|
||||
|
||||
#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}}
|
||||
static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
|
||||
{
|
||||
const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
struct psa_aead_operation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
unsigned int key_set : 1;
|
||||
unsigned int iv_set : 1;
|
||||
uint8_t iv_size;
|
||||
uint8_t block_size;
|
||||
union
|
||||
{
|
||||
unsigned dummy; /* Enable easier initializing of the union. */
|
||||
mbedtls_cipher_context_t cipher;
|
||||
} ctx;
|
||||
};
|
||||
|
||||
#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}}
|
||||
static inline struct psa_aead_operation_s psa_aead_operation_init( void )
|
||||
{
|
||||
const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *info;
|
||||
size_t info_length;
|
||||
psa_hmac_internal_data hmac;
|
||||
uint8_t prk[PSA_HASH_MAX_SIZE];
|
||||
uint8_t output_block[PSA_HASH_MAX_SIZE];
|
||||
#if PSA_HASH_MAX_SIZE > 0xff
|
||||
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
|
||||
#endif
|
||||
uint8_t offset_in_block;
|
||||
uint8_t block_number;
|
||||
unsigned int state : 2;
|
||||
unsigned int info_set : 1;
|
||||
} psa_hkdf_key_derivation_t;
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
typedef enum
|
||||
{
|
||||
TLS12_PRF_STATE_INIT, /* no input provided */
|
||||
TLS12_PRF_STATE_SEED_SET, /* seed has been set */
|
||||
TLS12_PRF_STATE_KEY_SET, /* key has been set */
|
||||
TLS12_PRF_STATE_LABEL_SET, /* label has been set */
|
||||
TLS12_PRF_STATE_OUTPUT /* output has been started */
|
||||
} psa_tls12_prf_key_derivation_state_t;
|
||||
|
||||
typedef struct psa_tls12_prf_key_derivation_s
|
||||
{
|
||||
#if PSA_HASH_MAX_SIZE > 0xff
|
||||
#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
|
||||
#endif
|
||||
|
||||
/* Indicates how many bytes in the current HMAC block have
|
||||
* not yet been read by the user. */
|
||||
uint8_t left_in_block;
|
||||
|
||||
/* The 1-based number of the block. */
|
||||
uint8_t block_number;
|
||||
|
||||
psa_tls12_prf_key_derivation_state_t state;
|
||||
|
||||
uint8_t *seed;
|
||||
size_t seed_length;
|
||||
uint8_t *label;
|
||||
size_t label_length;
|
||||
psa_hmac_internal_data hmac;
|
||||
uint8_t Ai[PSA_HASH_MAX_SIZE];
|
||||
|
||||
/* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */
|
||||
uint8_t output_block[PSA_HASH_MAX_SIZE];
|
||||
} psa_tls12_prf_key_derivation_t;
|
||||
#endif /* MBEDTLS_MD_C */
|
||||
|
||||
struct psa_key_derivation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
unsigned int can_output_key : 1;
|
||||
size_t capacity;
|
||||
union
|
||||
{
|
||||
/* Make the union non-empty even with no supported algorithms. */
|
||||
uint8_t dummy;
|
||||
#if defined(MBEDTLS_MD_C)
|
||||
psa_hkdf_key_derivation_t hkdf;
|
||||
psa_tls12_prf_key_derivation_t tls12_prf;
|
||||
#endif
|
||||
} ctx;
|
||||
};
|
||||
|
||||
/* This only zeroes out the first byte in the union, the rest is unspecified. */
|
||||
#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}}
|
||||
static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void )
|
||||
{
|
||||
const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
struct psa_key_policy_s
|
||||
{
|
||||
psa_key_usage_t usage;
|
||||
psa_algorithm_t alg;
|
||||
psa_algorithm_t alg2;
|
||||
};
|
||||
typedef struct psa_key_policy_s psa_key_policy_t;
|
||||
|
||||
#define PSA_KEY_POLICY_INIT {0, 0, 0}
|
||||
static inline struct psa_key_policy_s psa_key_policy_init( void )
|
||||
{
|
||||
const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
/* The type used internally for key sizes.
|
||||
* Public interfaces use size_t, but internally we use a smaller type. */
|
||||
typedef uint16_t psa_key_bits_t;
|
||||
/* The maximum value of the type used to represent bit-sizes.
|
||||
* This is used to mark an invalid key size. */
|
||||
#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) )
|
||||
/* The maximum size of a key in bits.
|
||||
* Currently defined as the maximum that can be represented, rounded down
|
||||
* to a whole number of bytes.
|
||||
* This is an uncast value so that it can be used in preprocessor
|
||||
* conditionals. */
|
||||
#define PSA_MAX_KEY_BITS 0xfff8
|
||||
|
||||
/** A mask of flags that can be stored in key attributes.
|
||||
*
|
||||
* This type is also used internally to store flags in slots. Internal
|
||||
* flags are defined in library/psa_crypto_core.h. Internal flags may have
|
||||
* the same value as external flags if they are properly handled during
|
||||
* key creation and in psa_get_key_attributes.
|
||||
*/
|
||||
typedef uint16_t psa_key_attributes_flag_t;
|
||||
|
||||
#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \
|
||||
( (psa_key_attributes_flag_t) 0x0001 )
|
||||
|
||||
/* A mask of key attribute flags used externally only.
|
||||
* Only meant for internal checks inside the library. */
|
||||
#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \
|
||||
MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \
|
||||
0 )
|
||||
|
||||
/* A mask of key attribute flags used both internally and externally.
|
||||
* Currently there aren't any. */
|
||||
#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \
|
||||
0 )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
psa_key_type_t type;
|
||||
psa_key_lifetime_t lifetime;
|
||||
psa_key_id_t id;
|
||||
psa_key_policy_t policy;
|
||||
psa_key_bits_t bits;
|
||||
psa_key_attributes_flag_t flags;
|
||||
} psa_core_key_attributes_t;
|
||||
|
||||
/* The server must be able to interpret the attributes as specified by the
|
||||
* client. The server works with the psa_key_id_t encoding the key owner, but
|
||||
* the client works with the psa_key_id_t not containing the key owner (pure
|
||||
* psa_app_key_id_t. */
|
||||
typedef struct
|
||||
{
|
||||
psa_key_type_t type;
|
||||
psa_key_lifetime_t lifetime;
|
||||
psa_app_key_id_t id;
|
||||
psa_key_policy_t policy;
|
||||
psa_key_bits_t bits;
|
||||
psa_key_attributes_flag_t flags;
|
||||
} psa_client_core_key_attributes_t;
|
||||
|
||||
#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0}
|
||||
|
||||
struct psa_key_attributes_s
|
||||
{
|
||||
psa_core_key_attributes_t core;
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
|
||||
psa_key_slot_number_t slot_number;
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
|
||||
void *domain_parameters;
|
||||
size_t domain_parameters_size;
|
||||
};
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
|
||||
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0}
|
||||
#else
|
||||
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
|
||||
#endif
|
||||
typedef struct psa_client_key_attributes_s
|
||||
{
|
||||
psa_client_core_key_attributes_t core;
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
|
||||
psa_key_slot_number_t slot_number;
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
|
||||
void *domain_parameters;
|
||||
size_t domain_parameters_size;
|
||||
} psa_client_key_attributes_t;
|
||||
|
||||
static inline struct psa_key_attributes_s psa_key_attributes_init( void )
|
||||
{
|
||||
const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
|
||||
return( v );
|
||||
}
|
||||
|
||||
static void psa_core_attributes_to_client(
|
||||
const psa_core_key_attributes_t *server,
|
||||
psa_client_core_key_attributes_t *client)
|
||||
{
|
||||
client->type = server->type;
|
||||
client->lifetime = server->lifetime;
|
||||
client->id = server->id.key_id;
|
||||
client->policy = server->policy;
|
||||
client->bits = server->bits;
|
||||
client->flags = server->flags;
|
||||
}
|
||||
|
||||
static void psa_core_attributes_to_server(
|
||||
const psa_client_core_key_attributes_t *client,
|
||||
psa_key_owner_id_t owner,
|
||||
psa_core_key_attributes_t *server)
|
||||
{
|
||||
server->type = client->type;
|
||||
server->lifetime = client->lifetime;
|
||||
server->id.key_id = client->id;
|
||||
server->id.owner = owner;
|
||||
server->policy = client->policy;
|
||||
server->bits = client->bits;
|
||||
server->flags = client->flags;
|
||||
}
|
||||
|
||||
static inline void psa_set_key_id(psa_key_attributes_t *attributes,
|
||||
psa_key_id_t id)
|
||||
{
|
||||
attributes->core.id = id;
|
||||
if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE )
|
||||
attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
|
||||
}
|
||||
|
||||
static inline psa_key_id_t psa_get_key_id(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.id );
|
||||
}
|
||||
|
||||
static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
|
||||
psa_key_lifetime_t lifetime)
|
||||
{
|
||||
attributes->core.lifetime = lifetime;
|
||||
if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
|
||||
{
|
||||
#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
|
||||
attributes->core.id.key_id = 0;
|
||||
attributes->core.id.owner = 0;
|
||||
#else
|
||||
attributes->core.id = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline psa_key_lifetime_t psa_get_key_lifetime(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.lifetime );
|
||||
}
|
||||
|
||||
static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
|
||||
psa_key_usage_t usage_flags)
|
||||
{
|
||||
attributes->core.policy.usage = usage_flags;
|
||||
}
|
||||
|
||||
static inline psa_key_usage_t psa_get_key_usage_flags(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.policy.usage );
|
||||
}
|
||||
|
||||
static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
attributes->core.policy.alg = alg;
|
||||
}
|
||||
|
||||
static inline psa_algorithm_t psa_get_key_algorithm(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.policy.alg );
|
||||
}
|
||||
|
||||
/* This function is declared in crypto_extra.h, which comes after this
|
||||
* header file, but we need the function here, so repeat the declaration. */
|
||||
psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
|
||||
psa_key_type_t type,
|
||||
const uint8_t *data,
|
||||
size_t data_length);
|
||||
|
||||
static inline void psa_set_key_type(psa_key_attributes_t *attributes,
|
||||
psa_key_type_t type)
|
||||
{
|
||||
if( attributes->domain_parameters == NULL )
|
||||
{
|
||||
/* Common case: quick path */
|
||||
attributes->core.type = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the bigger function to free the old domain paramteres.
|
||||
* Ignore any errors which may arise due to type requiring
|
||||
* non-default domain parameters, since this function can't
|
||||
* report errors. */
|
||||
(void) psa_set_key_domain_parameters( attributes, type, NULL, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static inline psa_key_type_t psa_get_key_type(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.type );
|
||||
}
|
||||
|
||||
static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
|
||||
size_t bits)
|
||||
{
|
||||
if( bits > PSA_MAX_KEY_BITS )
|
||||
attributes->core.bits = PSA_KEY_BITS_TOO_LARGE;
|
||||
else
|
||||
attributes->core.bits = (psa_key_bits_t) bits;
|
||||
}
|
||||
|
||||
static inline size_t psa_get_key_bits(
|
||||
const psa_key_attributes_t *attributes)
|
||||
{
|
||||
return( attributes->core.bits );
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PSA_CRYPTO_STRUCT_H */
|
|
@ -1,73 +0,0 @@
|
|||
|
||||
/** \addtogroup hal */
|
||||
/** @{*/
|
||||
/* Copyright (c) 2017-2018 ARM Limited
|
||||
*
|
||||
* 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 __SPM_API_H__
|
||||
#define __SPM_API_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** @defgroup SPM-HAL SPM HAL API
|
||||
* The HAL functions for PSA SPM
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/* ------------------------------------ HAL-SPE API ------------------------- */
|
||||
|
||||
|
||||
#if defined(COMPONENT_SPE)
|
||||
/**
|
||||
* Start running the NSPE.
|
||||
*
|
||||
* Secure Processing Environment (SPE) expected to boot first. Once all
|
||||
* the initializations are done, Nonsecure Processing Environment (NSPE)
|
||||
* should be booted.
|
||||
*
|
||||
* @note The function must be implemented by target specific code.
|
||||
*/
|
||||
void spm_hal_start_nspe(void);
|
||||
|
||||
|
||||
/**
|
||||
* Configure memory protection mechanism.
|
||||
*
|
||||
* Apply memory protection schemes to ensure secure memory can only be accessed
|
||||
* from secure-state.
|
||||
*
|
||||
* @note The function must be implemented by target specific code.
|
||||
*
|
||||
*/
|
||||
void spm_hal_memory_protection_init(void);
|
||||
|
||||
#endif // defined(COMPONENT_SPE)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SPM_API_H__
|
||||
|
||||
/** @}*/
|
|
@ -1077,7 +1077,7 @@ extern "C" long PREFIX(_flen)(FILEHANDLE fh)
|
|||
}
|
||||
|
||||
// Do not compile this code for TFM secure target
|
||||
#if !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
|
||||
#if !defined(TARGET_TFM)
|
||||
|
||||
#if !defined(__MICROLIB)
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
|
@ -1138,7 +1138,7 @@ MBED_USED extern "C" __value_in_regs struct __initial_stackheap __user_setup_sta
|
|||
return _mbed_user_setup_stackheap(R0, R1, R2, R3);
|
||||
}
|
||||
|
||||
#endif // !defined(COMPONENT_SPE) || !defined(TARGET_TFM)
|
||||
#endif // !defined(TARGET_TFM)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue