Skip to content

Commit 6c7c68c

Browse files
Oren CohenMichael Schwarcz
authored andcommitted
PSA SPM
* Intorduce PSA-SPM to mbed-os * Add SPM tests (for PSA targets) * Add PSA PRoT internal storage Secure implementation * Integrate SPM into the boot proccess * PSA manifest data generator * Introduce PSA targets skeleton to mbed-os * Add artifact delivery to the tools
1 parent e5ae50a commit 6c7c68c

File tree

136 files changed

+14885
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+14885
-14
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,6 @@ log
9494

9595
# Icetea related file
9696
test_suite.json
97+
98+
# default delivery dir
99+
DELIVERY/

TESTS/mbed_hal/spm/main.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "utest/utest.h"
18+
#include "unity/unity.h"
19+
#include "greentea-client/test_env.h"
20+
#include "cmsis.h"
21+
#include "spm_api.h"
22+
#include <stdlib.h>
23+
24+
using namespace utest::v1;
25+
26+
#if !defined(COMPONENT_PSA_SRV_IPC)
27+
#error [NOT_SUPPORTED] Test supported only on PSA targets
28+
#endif
29+
30+
#if !defined ( __GNUC__ )
31+
#error [NOT_SUPPORTED] this test is supported on GCC only
32+
#endif
33+
34+
extern "C" {
35+
#define HARDFAULT_IRQn ((IRQn_Type)-13)
36+
#define EXC_RETURN_RETURN_STACK_MSK ((uint32_t)(0x00000004))
37+
#define PC_INDEX_IN_STACK_FRAME 6
38+
39+
volatile uint32_t fault_occurred;
40+
uint32_t real_hard_fault_handler;
41+
42+
__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
43+
{
44+
register uint32_t result;
45+
46+
__ASM volatile ("MOV %0, LR\n" : "=r" (result));
47+
return result;
48+
}
49+
50+
// This function is required as we need a symbol/address
51+
// to jump to from fault handler.
52+
void do_nothing(void)
53+
{
54+
__NOP();
55+
}
56+
57+
// Test exception handler
58+
static void hard_fault_handler_test()
59+
{
60+
fault_occurred++;
61+
// LR is set EXC_RETURN
62+
// lowest bits identify PSP vs MSP stack used for stacking
63+
uint32_t lr = __get_LR();
64+
uint32_t sp;
65+
66+
if (lr & EXC_RETURN_RETURN_STACK_MSK) {
67+
sp = __get_PSP();
68+
} else {
69+
sp = __get_MSP();
70+
}
71+
72+
// Overwrite return address.
73+
// Fake return to a our special function since current
74+
// instruction under test will always fail due to memory protection
75+
((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing;
76+
}
77+
78+
// Using naked function as it will not be executed from beginning to the end.
79+
// The execution flow expected to be interrupted by exception and we will
80+
// return to other function.
81+
// compiler will not produce prolog and epilog code for naked function
82+
// and thus will preserve stack in un-corrupted state
83+
__attribute__((naked)) void call_mem(uint32_t addr)
84+
{
85+
// Only first instruction will be executed in positive flow,
86+
// since exception will be generated for invalid memory access.
87+
// Other instructions are for calling do_nothing function according to AAPCS.
88+
__ASM(
89+
"LDR r1, [r0]\n"
90+
"BX lr\n"
91+
);
92+
}
93+
}
94+
95+
static void test_memory(uint32_t addr, uint32_t expected_fatal_count)
96+
{
97+
call_mem(addr);
98+
// Although call_mem is a "naked" function, it is called using AAPCS.
99+
// Thus we can assume LR will point to next instruction, and caller save registers are backed up
100+
TEST_ASSERT_EQUAL(expected_fatal_count, fault_occurred);
101+
}
102+
103+
static void secure_ram_fault_test(void)
104+
{
105+
test_memory(PSA_SECURE_RAM_START, 1);
106+
}
107+
108+
static void secure_flash_fault_test(void)
109+
{
110+
test_memory(PSA_SECURE_ROM_START, 1);
111+
}
112+
113+
static void non_secure_ram_fault_test(void)
114+
{
115+
test_memory(PSA_NON_SECURE_RAM_START, 0);
116+
}
117+
118+
static void non_secure_flash_fault_test(void)
119+
{
120+
test_memory(PSA_NON_SECURE_ROM_START, 0);
121+
}
122+
123+
utest::v1::status_t fault_override_setup(const Case *const source, const size_t index_of_case)
124+
{
125+
// Save old hard fault handler and replace it with a new one
126+
// NOTE: only works when VTOR is set to RAM
127+
real_hard_fault_handler = NVIC_GetVector(HARDFAULT_IRQn);
128+
NVIC_SetVector(HARDFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
129+
fault_occurred = 0;
130+
131+
return greentea_case_setup_handler(source, index_of_case);
132+
}
133+
134+
utest::v1::status_t fault_override_teardown(const Case *const source, const size_t passed, const size_t failed,
135+
const failure_t reason)
136+
{
137+
// Restore real hard fault handler
138+
NVIC_SetVector(HARDFAULT_IRQn, real_hard_fault_handler);
139+
140+
return greentea_case_teardown_handler(source, passed, failed, reason);
141+
}
142+
143+
Case cases[] = {
144+
Case("SPM - Access secure RAM", fault_override_setup, secure_ram_fault_test, fault_override_teardown),
145+
Case("SPM - Access secure Flash", fault_override_setup, secure_flash_fault_test, fault_override_teardown),
146+
Case("SPM - Access non-secure RAM", fault_override_setup, non_secure_ram_fault_test, fault_override_teardown),
147+
Case("SPM - Access non-secure Flash", fault_override_setup, non_secure_flash_fault_test, fault_override_teardown),
148+
};
149+
150+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
151+
{
152+
#ifndef NO_GREENTEA
153+
GREENTEA_SETUP(20, "default_auto");
154+
#endif
155+
return greentea_test_setup_handler(number_of_cases);
156+
}
157+
158+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
159+
160+
int main()
161+
{
162+
Harness::run(specification);
163+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* Copyright (c) 2017 ARM Limited
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/***********************************************************************************************************************
17+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
18+
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
19+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20+
**********************************************************************************************************************/
21+
22+
#include "spm_panic.h"
23+
#include "spm_internal.h"
24+
#include "handles_manager.h"
25+
#include "cmsis.h"
26+
#include "psa_test_its_reset_partition.h"
27+
#include "psa_its_partition.h"
28+
29+
30+
spm_partition_t g_partitions[2] = {
31+
{
32+
.partition_id = TEST_ITS_RESET_ID,
33+
.thread_id = 0,
34+
.flags_rot_srv = TEST_ITS_RESET_WAIT_ANY_SID_MSK,
35+
.flags_interrupts = 0,
36+
.rot_services = NULL,
37+
.rot_services_count = TEST_ITS_RESET_ROT_SRV_COUNT,
38+
.extern_sids = NULL,
39+
.extern_sids_count = TEST_ITS_RESET_EXT_ROT_SRV_COUNT,
40+
.irq_mapper = NULL,
41+
},
42+
{
43+
.partition_id = ITS_ID,
44+
.thread_id = 0,
45+
.flags_rot_srv = ITS_WAIT_ANY_SID_MSK,
46+
.flags_interrupts = 0,
47+
.rot_services = NULL,
48+
.rot_services_count = ITS_ROT_SRV_COUNT,
49+
.extern_sids = NULL,
50+
.extern_sids_count = ITS_EXT_ROT_SRV_COUNT,
51+
.irq_mapper = NULL,
52+
},
53+
};
54+
55+
/* Check all the defined memory regions for overlapping. */
56+
57+
/* A list of all the memory regions. */
58+
const mem_region_t *mem_regions = NULL;
59+
60+
const uint32_t mem_region_count = 0;
61+
62+
// forward declaration of partition initializers
63+
void test_its_reset_init(spm_partition_t *partition);
64+
void its_init(spm_partition_t *partition);
65+
66+
uint32_t init_partitions(spm_partition_t **partitions)
67+
{
68+
if (NULL == partitions) {
69+
SPM_PANIC("partitions is NULL!\n");
70+
}
71+
72+
test_its_reset_init(&(g_partitions[0]));
73+
its_init(&(g_partitions[1]));
74+
75+
*partitions = g_partitions;
76+
return 2;
77+
}
78+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "spm_client.h"
2+
#include "psa_prot_internal_storage.h"
3+
#include "test_pits.h"
4+
#include "psa_test_its_reset_ifs.h"
5+
6+
psa_its_status_t test_psa_its_reset(void)
7+
{
8+
psa_handle_t conn = psa_connect(TEST_PSA_ITS_RESET, 1);
9+
if (conn <= PSA_NULL_HANDLE) {
10+
return PSA_ITS_ERROR_STORAGE_FAILURE;
11+
}
12+
13+
psa_error_t status = psa_call(conn, NULL, 0, NULL, 0);
14+
if (status == PSA_DROP_CONNECTION) {
15+
status = PSA_ITS_ERROR_STORAGE_FAILURE;
16+
}
17+
18+
psa_close(conn);
19+
return status;
20+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/* Copyright (c) 2017 ARM Limited
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/***********************************************************************************************************************
17+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
18+
* THIS FILE IS AN AUTO-GENERATED FILE - DO NOT MODIFY IT.
19+
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20+
**********************************************************************************************************************/
21+
22+
#include "cmsis.h"
23+
#include "mbed_toolchain.h" /* For using MBED_ALIGN macro */
24+
#include "rtx_os.h"
25+
#include "spm_panic.h"
26+
#include "spm_internal.h"
27+
#include "psa_test_its_reset_partition.h"
28+
#include "psa_test_its_reset_ifs.h"
29+
30+
31+
/* Threads stacks */
32+
MBED_ALIGN(8) uint8_t test_its_reset_thread_stack[1024] = {0};
33+
34+
/* Threads control blocks */
35+
osRtxThread_t test_its_reset_thread_cb = {0};
36+
37+
/* Thread attributes - for thread initialization */
38+
osThreadAttr_t test_its_reset_thread_attr = {
39+
.name = "test_its_reset",
40+
.attr_bits = 0,
41+
.cb_mem = &test_its_reset_thread_cb,
42+
.cb_size = sizeof(test_its_reset_thread_cb),
43+
.stack_mem = test_its_reset_thread_stack,
44+
.stack_size = 1024,
45+
.priority = osPriorityNormal,
46+
.tz_module = 0,
47+
.reserved = 0
48+
};
49+
50+
spm_rot_service_t test_its_reset_rot_services[TEST_ITS_RESET_ROT_SRV_COUNT] = {
51+
{
52+
.sid = TEST_PSA_ITS_RESET,
53+
.mask = TEST_PSA_ITS_RESET_MSK,
54+
.partition = NULL,
55+
.min_version = 1,
56+
.min_version_policy = PSA_MINOR_VERSION_POLICY_RELAXED,
57+
.allow_nspe = true,
58+
.queue = {
59+
.head = NULL,
60+
.tail = NULL
61+
}
62+
},
63+
};
64+
65+
66+
static osRtxMutex_t test_its_reset_mutex = {0};
67+
static const osMutexAttr_t test_its_reset_mutex_attr = {
68+
.name = "test_its_reset_mutex",
69+
.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust,
70+
.cb_mem = &test_its_reset_mutex,
71+
.cb_size = sizeof(test_its_reset_mutex),
72+
};
73+
74+
75+
extern void test_pits_entry(void *ptr);
76+
77+
void test_its_reset_init(spm_partition_t *partition)
78+
{
79+
if (NULL == partition) {
80+
SPM_PANIC("partition is NULL!\n");
81+
}
82+
83+
partition->mutex = osMutexNew(&test_its_reset_mutex_attr);
84+
if (NULL == partition->mutex) {
85+
SPM_PANIC("Failed to create mutex for secure partition test_its_reset!\n");
86+
}
87+
88+
for (uint32_t i = 0; i < TEST_ITS_RESET_ROT_SRV_COUNT; ++i) {
89+
test_its_reset_rot_services[i].partition = partition;
90+
}
91+
partition->rot_services = test_its_reset_rot_services;
92+
93+
partition->thread_id = osThreadNew(test_pits_entry, NULL, &test_its_reset_thread_attr);
94+
if (NULL == partition->thread_id) {
95+
SPM_PANIC("Failed to create start main thread of partition test_its_reset!\n");
96+
}
97+
}

0 commit comments

Comments
 (0)