mbed-os/features/frameworks/TARGET_PSA/val_greentea.cpp

316 lines
9.1 KiB
C++

#include "greentea-client/test_env.h"
#include "inttypes.h"
#include "val_greentea.h"
void pal_mbed_os_compliance_test_initialize(void);
void pal_mbed_os_compliance_test_destroy(void);
extern "C" {
/* globals */
test_status_buffer_t g_status_buffer;
void mbed_val_test_init(uint32_t test_num, char8_t *desc, uint32_t test_bitfield)
{
/*global init*/
g_status_buffer.state = 0;
g_status_buffer.status = VAL_STATUS_INVALID;
mbed_val_print(PRINT_ALWAYS, "\nTEST: %d | DESCRIPTION: ", test_num);
mbed_val_print(PRINT_ALWAYS, desc, 0);
GREENTEA_SETUP(100, "default_auto");
mbed_val_set_status(RESULT_START(VAL_STATUS_SUCCESS));
pal_mbed_os_compliance_test_initialize();
return;
}
void mbed_val_test_exit(void)
{
uint32_t status = mbed_val_get_status();
pal_mbed_os_compliance_test_destroy();
/* return if test skipped or failed */
if (IS_TEST_FAIL(status) || IS_TEST_SKIP(status))
{
GREENTEA_TESTSUITE_RESULT(false);
}
else
{
GREENTEA_TESTSUITE_RESULT(true);
mbed_val_set_status(RESULT_END(VAL_STATUS_SUCCESS));
}
}
/**
@brief - This function executes given list of tests from non-secure sequentially
This covers non-secure to secure IPC API scenario
@param - test_num : Test_num
@param - tests_list : list of tests to be executed
@param - server_hs : Initiate a server handshake
@return - val_status_t
**/
val_status_t mbed_val_execute_non_secure_tests(uint32_t test_num, client_test_t *tests_list,
bool_t server_hs)
{
val_status_t status = VAL_STATUS_SUCCESS;
int32_t test_status = VAL_STATUS_SUCCESS;
psa_handle_t handle;
uint32_t i = 1;
test_info_t test_info;
char testcase_name[100] = "";
bool continue_test = true;
test_info.test_num = test_num;
mbed_val_print(PRINT_TEST, "[Info] Executing tests from non-secure\n", 0);
while (tests_list[i] != NULL)
{
memset(testcase_name, 0, 100);
sprintf(testcase_name, "Check%" PRIu32, i);
GREENTEA_TESTCASE_START(testcase_name);
if (server_hs == TRUE)
{
/* Handshake with server tests */
test_info.block_num = i;
status = mbed_val_execute_secure_test_func(&handle, test_info,
SERVER_TEST_DISPATCHER_SID);
if (VAL_ERROR(status))
{
mbed_val_set_status(RESULT_FAIL(status));
mbed_val_print(PRINT_ERROR, "[Check%d] START\n", i);
return status;
}
else
{
mbed_val_print(PRINT_DEBUG, "[Check%d] START\n", i);
}
}
/* Execute client tests */
test_status = tests_list[i](CALLER_NONSECURE);
if (server_hs == TRUE)
{
/* Retrive Server test status */
status = mbed_val_get_secure_test_result(&handle);
}
if (test_status != VAL_STATUS_SUCCESS)
{
status = VAL_STATUS_ERROR;
}
if (IS_TEST_SKIP(status))
{
mbed_val_set_status(status);
mbed_val_print(PRINT_DEBUG, "[Check%d] SKIPPED\n", i);
GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0);
continue_test = false;
}
else if (VAL_ERROR(status))
{
mbed_val_set_status(RESULT_FAIL(status));
if (server_hs == TRUE)
mbed_val_print(PRINT_ERROR, "[Check%d] FAILED\n", i);
GREENTEA_TESTCASE_FINISH(testcase_name, 0, 1);
continue_test = false;
}
else
{
if (server_hs == TRUE)
mbed_val_print(PRINT_DEBUG, "[Check%d] PASSED\n", i);
GREENTEA_TESTCASE_FINISH(testcase_name, 1, 0);
continue_test = true;
}
if (!continue_test)
{
return status;
}
i++;
}
return status;
}
/**
@brief - Records the state and status of test
@return - val_status_t
**/
val_status_t mbed_val_set_status(uint32_t status)
{
g_status_buffer.state = ((status >> TEST_STATE_BIT) & TEST_STATE_MASK);
g_status_buffer.status = (status & TEST_STATUS_MASK);
return VAL_STATUS_SUCCESS;
}
/**
@brief - Updates the state and status for a given test
@return - test status
**/
uint32_t mbed_val_get_status(void)
{
return ((g_status_buffer.state) << TEST_STATE_BIT) | (g_status_buffer.status);
}
/**
@brief - This function is used to handshake between:
- nonsecure client fn to server test fn
- secure client fn and server test fn
- nonsecure client fn to secure client test fn
@param - handle : handle returned while connecting given sid
@param - test_info : Test_num and block_num to be executed
@param - sid : RoT service to be connected. Partition dispatcher sid
@return - val_status_t
**/
val_status_t mbed_val_execute_secure_test_func(psa_handle_t *handle, test_info_t test_info, uint32_t sid)
{
uint32_t test_data;
val_status_t status = VAL_STATUS_SUCCESS;
psa_status_t status_of_call = PSA_SUCCESS;
*handle = pal_ipc_connect(sid, 0);
if (*handle < 0)
{
mbed_val_print(PRINT_ERROR, "Could not connect SID. Handle=%x\n", *handle);
return VAL_STATUS_CONNECTION_FAILED;
}
test_data = ((uint32_t)(test_info.test_num) | ((uint32_t)(test_info.block_num) << BLOCK_NUM_POS) | ((uint32_t)(TEST_EXECUTE_FUNC) << ACTION_POS));
psa_invec data[1] = {{&test_data, sizeof(test_data)}};
status_of_call = pal_ipc_call(*handle, data, 1, NULL, 0);
if (status_of_call != PSA_SUCCESS)
{
status = VAL_STATUS_CALL_FAILED;
mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
pal_ipc_close(*handle);
}
return status;
}
/**
@brief - Print module. This is client interface API of secure partition
mbed_val_print_sf API for nspe world
@param - verbosity: Print verbosity level
- string : Input string
- data : Value for format specifier
@return - val_status_t
**/
val_status_t mbed_val_print(print_verbosity_t verbosity, const char *string, uint32_t data)
{
if (data != 0) {
printf(string, data);
} else {
printf(string);
}
return VAL_STATUS_SUCCESS;
}
/**
@brief - This function is used to retrive the status of previously connected test function
using mbed_val_execute_secure_test_func
@param - handle : handle of server function. Handle of Partition dispatcher sid
@return - The status of test functions
**/
val_status_t mbed_val_get_secure_test_result(psa_handle_t *handle)
{
uint32_t test_data;
val_status_t status = VAL_STATUS_SUCCESS;
psa_status_t status_of_call = PSA_SUCCESS;
test_data = (TEST_RETURN_RESULT << ACTION_POS);
psa_outvec resp = {&status, sizeof(status)};
psa_invec data[1] = {{&test_data, sizeof(test_data)}};
status_of_call = pal_ipc_call(*handle, data, 1, &resp, 1);
if (status_of_call != PSA_SUCCESS)
{
status = VAL_STATUS_CALL_FAILED;
mbed_val_print(PRINT_ERROR, "Call to dispatch SF failed. Status=%x\n", status_of_call);
}
pal_ipc_close(*handle);
return status;
}
/**
* @brief Connect to given sid
@param -sid : RoT service id
@param -minor_version : minor_version of RoT service
@param -handle - return connection handle
* @return val_status_t
*/
val_status_t mbed_val_ipc_connect(uint32_t sid, uint32_t minor_version, psa_handle_t *handle )
{
*handle = pal_ipc_connect(sid, minor_version);
if (*handle < 0)
{
return VAL_STATUS_CONNECTION_FAILED;
}
return VAL_STATUS_SUCCESS;
}
/**
* @brief Call a connected Root of Trust Service.@n
* The caller must provide an array of ::psa_invec_t structures as the input payload.
*
* @param handle Handle for the connection.
* @param in_vec Array of psa_invec structures.
* @param in_len Number of psa_invec structures in in_vec.
* @param out_vec Array of psa_outvec structures for optional Root of Trust Service response.
* @param out_len Number of psa_outvec structures in out_vec.
* @return val_status_t
*/
val_status_t mbed_val_ipc_call(psa_handle_t handle, psa_invec *in_vec, size_t in_len,
psa_outvec *out_vec, size_t out_len)
{
psa_status_t call_status = PSA_SUCCESS;
call_status = pal_ipc_call(handle, in_vec, in_len, out_vec, out_len);
if (call_status != PSA_SUCCESS)
{
return VAL_STATUS_CALL_FAILED;
}
return VAL_STATUS_SUCCESS;
}
/**
* @brief Close a connection to a Root of Trust Service.
* Sends the PSA_IPC_DISCONNECT message to the Root of Trust Service so it can clean up resources.
*
* @param handle Handle for the connection.
* @return void
*/
void mbed_val_ipc_close(psa_handle_t handle)
{
pal_ipc_close(handle);
}
/**
* @brief reprogram the watchdog timer
* always succeeds on mbed-greentead testing.
*
* @param timeout_type type of timeout.
* @return val_status_t
*/
val_status_t mbed_val_wd_reprogram_timer(wd_timeout_type_t timeout_type)
{
return VAL_STATUS_SUCCESS;
}
} // extern "C"