Skip to content

PSA Crypto SPM #8804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 58 commits into from
Nov 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
dd73fa6
PSA SPM
Nov 13, 2018
c7d3523
Include `deliver_into` in Config mock
theotherjimmy Nov 15, 2018
aea01a8
astyle changes
Nov 18, 2018
9cc017f
Normalize license headers
Nov 18, 2018
9406450
Coverity bug fixes
Nov 21, 2018
53be3cc
Fix the SPM HAL test
Nov 22, 2018
ecd556b
Generate better magic numbers
Nov 25, 2018
4a391d3
Remove internal RTX includes
Nov 25, 2018
6cd4f77
Add Version to SPM templates and generator
Nov 25, 2018
1e27eb1
Remove SPM negative tests
Nov 25, 2018
f771a5a
Fix FVP_MPS2 & ARM_CM3DS_MPS2 components definition
Nov 25, 2018
1a33ae5
Handle manager documentation fix
Nov 26, 2018
2b9f94a
Remove dead code
Nov 26, 2018
773ac8d
CR fixes
Nov 26, 2018
628ef9b
spm_internal.h - add missing function docs
Nov 26, 2018
8501e79
spm_init.h add function docs
Nov 26, 2018
5455a2d
Astyle fixes
Nov 26, 2018
aea9713
Doxygen fixes in tests
Nov 26, 2018
25239a4
Edit spm_client.h
Nov 26, 2018
b87ab25
Edit spm_server.h
Nov 26, 2018
ba6fdcf
Edit psa_defs.h
Nov 26, 2018
34bcf6b
Edit spm_api.h
Nov 26, 2018
ed8505a
Update components/TARGET_PSA/spm/psa_defs.h
Nov 27, 2018
2b3822e
Fix targets.json
Nov 27, 2018
f4581fa
Create a new partition for the crypto service
Nov 13, 2018
bd47a8c
Add entropy inject to spm
mohammad1603 Nov 21, 2018
7b2c924
Adding defualt behaviour for platforms without TRNG.
mohammad1603 Nov 21, 2018
587fdbb
Remove crypto init that was not called by the user
mohammad1603 Nov 21, 2018
1325084
Add tests to PSA entropy injection
mohammad1603 Nov 21, 2018
7203774
Update auto generated SPM files
mohammad1603 Nov 21, 2018
0fde6af
change MBEDTLS_RANDOM_SEED_ITS_UID define to be PSA_CRYPTO_ITS_RANDO…
mohammad1603 Nov 21, 2018
73ebe1a
Fix inject entropy tests
mohammad1603 Nov 22, 2018
fb88cb4
Add missing guards
mohammad1603 Nov 22, 2018
54cd8bf
Change behavior realted to MBEDTLS_ENTROPY_NV_SEED and MBEDTLS_PSA_HA…
mohammad1603 Nov 22, 2018
ae0fa60
remove psa_its_get_info from seed read function
Nov 22, 2018
73cb013
skip inject entropy test if they not supported
Nov 22, 2018
4816266
add comment to explain why (-1 * rc) is returned
Nov 25, 2018
58f92c3
remove execute permissions from file
Nov 25, 2018
7f49fd2
Fix memory leak if user does not calls abort. call abort when connect…
Nov 25, 2018
59c3c9f
crypto init with multiple client guard & tests
Nov 25, 2018
e72d910
Add a weak implementation for trng_get_bytes()
danny4478 Nov 25, 2018
a4c498e
Integrate psa_key_agreement() with SPM code
mohammad1603 Nov 26, 2018
bab6116
compilation fix
Nov 26, 2018
352bac3
Crypto SPM - fix - PART1
Nov 26, 2018
7776fea
Remove unneeded includes
mohammad1603 Nov 26, 2018
ba47b45
Remove unnecessary define
mohammad1603 Nov 26, 2018
79d957a
Change PSA_MAX_NONCE_SIZE to PSA_AEAD_MAX_NONCE_SIZE
mohammad1603 Nov 26, 2018
1d4b6a4
Return invalid argument error in case of zero or negative handle for …
mohammad1603 Nov 26, 2018
5c2cf07
Revert file permission change
mohammad1603 Nov 26, 2018
88f4f48
Astyle fixes for the source
mohammad1603 Nov 26, 2018
4cef73d
Update output_length in trng_get_bytes() provided by psa.
mohammad1603 Nov 26, 2018
6e862cf
Fix psa_crypto_generator_init implementation to use the init define m…
mohammad1603 Nov 27, 2018
abf1ccc
Disable crypto_init tests when Mbed Crypto is OFF
Nov 27, 2018
daeb19d
Fix entropy_inject test compilation
Nov 27, 2018
b9ea334
Change __WEAK to MBED_WEAK
mohammad1603 Nov 27, 2018
8195944
Refactor trng_get_bytes()
mohammad1603 Nov 27, 2018
f1c5aeb
add MBEDTLS_PSA_CRYPTO_C defined to K64F PSA target
Nov 27, 2018
5f36447
do not run crypto init SPM test if not SPM target
Nov 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,6 @@ log

# Icetea related file
test_suite.json

# default delivery dir
DELIVERY/
49 changes: 49 additions & 0 deletions TESTS/mbed_hal/spm/fault_functions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* 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__
156 changes: 156 additions & 0 deletions TESTS/mbed_hal/spm/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/* 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
#endif

#if (defined( __CC_ARM ) || defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
#error [NOT_SUPPORTED] this test is supported on GCC only
#endif

#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 r1, [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 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),
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),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
#ifndef NO_GREENTEA
GREENTEA_SETUP(20, "default_auto");
#endif
return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
Harness::run(specification);
}
106 changes: 106 additions & 0 deletions TESTS/psa/crypto_init/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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.
*/

#if ((!defined(TARGET_PSA)) || (!defined(MBEDTLS_PSA_CRYPTO_C)) || (!defined(MBEDTLS_PSA_CRYPTO_SPM )))
#error [NOT_SUPPORTED] Mbed SPM Crypto is OFF - skipping.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we run tests without SPM enabled? Mbed Crypto should work fine without SPM.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a different behavior to init with SPM
without you can call init as much as you want and the free releases the context but with SPM in a client-server mode you can have more than 1 client, therefore we keep track on how many time you init and how many times you free.
this test is checking this feature

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, this is just for the crypto init test.

#endif // TARGET_PSA

#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include "crypto.h"
#include "entropy.h"
#include "entropy_poll.h"

#define TEST_RANDOM_SIZE 64

#if !defined(MAX)
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif

/* Calculating the minimum allowed entropy size in bytes */
#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE \
MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)

using namespace utest::v1;

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
#ifndef NO_GREENTEA
GREENTEA_SETUP(60, "default_auto");
#endif
return greentea_test_setup_handler(number_of_cases);
}

static void check_multi_crypto_init_deinit()
{
uint8_t output[TEST_RANDOM_SIZE] = {0};
uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0};
/* inject some a seed for test*/
for (int i; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
seed[i] = i;
}
/* don't really care if this succeed this is just to make crypto init pass*/
mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
psa_status_t status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_NOT_EQUAL(PSA_ERROR_BAD_STATE, status);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major: if status is not PSA_SUCCESS, there's something wrong, so the test should fail.

mbedtls_psa_crypto_free();
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_NOT_EQUAL(PSA_ERROR_BAD_STATE, status);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major: You've just closed the connection to the crypto library, so psa_generate_random should return BAD_STATE.

I see that you've implemented a connection counter in the SPE. It makes sense, but this violates the documented semantics of psa_crypto_init and mbedtls_psa_crypto_free: multiple calls to psa_crypto_init are supposed to be equivalent to a single call and a single call to mbedtls_psa_crypto_free is supposed to always free all resources associated with the current client.

Should the semantics change? My reasoning for the current semantics is that you should be able to call mbedtls_psa_crypto_free in your exit code regardless of how many times mbedtls_psa_crypto_free has been called. If you think the current semantics is wrong and the semantics in this PR is better, please submit PSA crypto API design feedback via internal or external channels that explains your reasoning.

This deviation needs to be documented in the known issues for this release.

mbedtls_psa_crypto_free();
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status);
}

static void check_crypto_init_deinit()
{
psa_status_t status;
uint8_t output[TEST_RANDOM_SIZE] = {0};
uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = {0};
/* inject some a seed for test*/
for (int i; i < MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE; ++i) {
seed[i] = i;
}
/* don't really care if this succeed this is just to make crypto init pass*/
mbedtls_psa_inject_entropy(seed, MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE);
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status);
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_NOT_EQUAL(PSA_ERROR_BAD_STATE, status);
mbedtls_psa_crypto_free();
status = psa_generate_random(output, sizeof(output));
TEST_ASSERT_EQUAL(PSA_ERROR_BAD_STATE, status);
}

Case cases[] = {
Case("PSA crypto-init De-init", check_crypto_init_deinit),
Case("PSA crypto- multiple init De-init", check_multi_crypto_init_deinit),
};

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
return !Harness::run(specification);
}
Loading