mirror of https://github.com/wolfSSL/wolfBoot.git
Fix two regressions after the fenrir changes
In hal/va416x0.c, FRAM_Write now explicitly aborts the split SPI write transaction on command-phase failure before returning, instead of leaving the bus in the half-open state introduced by the early return. I also added a host-side regression test in tools/unit-tests/unit-va416x0-fram.c that injects a command-phase HAL_Spi_Transmit(..., false) failure and verifies a later write still reaches the closing ...true phase. In src/arm_tee_psa_ipc.c, I extracted the protected-storage dispatch path into a small helper so it can be tested directly without changing runtime behavior. The new test in tools/unit- tests/unit-arm-tee-psa-ipc.c covers the short-vector invalid-argument branches for SET, GET, GET_INFO, and REMOVE, plus a full success path across those operations. The unit harness additions are wired up in tools/unit-tests/Makefile and use a tiny local CMSE stub in tools/unit-tests/arm_cmse.h.pull/795/head
parent
809b98ddd6
commit
fe934ff277
|
|
@ -202,6 +202,15 @@ tools/unit-tests/unit-mpusize
|
|||
tools/unit-tests/unit-otp-keystore
|
||||
tools/unit-tests/unit-tpm-api-names
|
||||
tools/unit-tests/unit-elf-bss-guard
|
||||
tools/unit-tests/unit-fit-fpga
|
||||
tools/unit-tests/unit-flash-erase-c0
|
||||
tools/unit-tests/unit-flash-erase-g0
|
||||
tools/unit-tests/unit-flash-erase-l0
|
||||
tools/unit-tests/unit-flash-erase-u3
|
||||
tools/unit-tests/unit-flash-erase-wb
|
||||
tools/unit-tests/unit-fwtpm-nv-oob
|
||||
tools/unit-tests/unit-x86-paging-oob
|
||||
|
||||
|
||||
|
||||
# Elf preprocessing tools
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
||||
#include "image.h"
|
||||
#include "string.h"
|
||||
|
||||
|
|
@ -40,7 +41,9 @@
|
|||
|
||||
#include "printf.h"
|
||||
#include "loader.h"
|
||||
#endif
|
||||
|
||||
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
||||
const stc_iocfg_pin_cfg_t bootDefaultConfig[] =
|
||||
{
|
||||
{VOR_PORTB,14,en_iocfg_dir_dncare, {{.fltclk=0,.invinp=0,.iewo=0,.opendrn=0,.invout=0,.plevel=0,.pen=0,.pwoa=0,.funsel=3,.iodis=0}}}, /* UART1 TX */
|
||||
|
|
@ -163,6 +166,7 @@ void uart_flush(void)
|
|||
while (DEBUG_UART_BASE->TXSTATUS & UART_TXSTATUS_WRBUSY_Msk);
|
||||
}
|
||||
#endif /* DEBUG_UART */
|
||||
#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */
|
||||
|
||||
|
||||
/* FRAM Driver */
|
||||
|
|
@ -194,6 +198,15 @@ static void FRAM_WaitIdle(uint8_t spiBank)
|
|||
(SPI_FIFO_CLR_RXFIFO_Msk | SPI_FIFO_CLR_TXFIFO_Msk);
|
||||
}
|
||||
|
||||
static void FRAM_AbortWriteTransaction(uint8_t spiBank)
|
||||
{
|
||||
/* Terminate a split write transaction after a command-phase failure so
|
||||
* the next FRAM operation does not inherit the previous chip-select state.
|
||||
*/
|
||||
FRAM_WaitIdle(spiBank);
|
||||
spiHandle.state = hal_spi_state_ready;
|
||||
}
|
||||
|
||||
/* Init SPI FRAM access */
|
||||
hal_status_t FRAM_Init(uint8_t spiBank, uint8_t csNum)
|
||||
{
|
||||
|
|
@ -265,8 +278,10 @@ hal_status_t FRAM_Write(uint8_t spiBank, uint32_t addr, uint8_t *buf,
|
|||
spiData[2] = (uint8_t)((addr>>8) & 0xFF); /* Address mid byte */
|
||||
spiData[3] = (uint8_t)( addr & 0xFF); /* Address low byte */
|
||||
status = HAL_Spi_Transmit(&spiHandle, spiData, 4, 0, false);
|
||||
if (status != hal_status_ok)
|
||||
if (status != hal_status_ok) {
|
||||
FRAM_AbortWriteTransaction(spiBank);
|
||||
return status;
|
||||
}
|
||||
return HAL_Spi_Transmit(&spiHandle, buf, len, 0, true);
|
||||
}
|
||||
|
||||
|
|
@ -326,6 +341,7 @@ hal_status_t FRAM_Erase(uint8_t spiBank, uint32_t addr, uint32_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
||||
|
||||
void RAMFUNCTION hal_flash_unlock(void)
|
||||
{
|
||||
|
|
@ -661,3 +677,4 @@ uint64_t hal_get_timer_us(void)
|
|||
((uint64_t)elapsed_ticks * 1000000ULL / SystemCoreClock);
|
||||
}
|
||||
#endif
|
||||
#endif /* !WOLFBOOT_UNIT_TEST_VA416X0_FRAM */
|
||||
|
|
|
|||
|
|
@ -262,6 +262,9 @@ static struct wolfboot_ps_entry *wolfboot_ps_alloc(psa_storage_uid_t uid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t arm_tee_psa_ps_dispatch(int32_t type, const psa_invec *in_vec,
|
||||
size_t in_len, psa_outvec *out_vec, size_t out_len);
|
||||
|
||||
static psa_status_t wolfboot_psa_open_key(psa_key_id_t id, psa_key_id_t *key)
|
||||
{
|
||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
|
@ -774,138 +777,7 @@ static int32_t arm_tee_psa_dispatch(psa_handle_t handle, int32_t type,
|
|||
}
|
||||
|
||||
if (handle == (psa_handle_t)ARM_TEE_PROTECTED_STORAGE_HANDLE) {
|
||||
if (type == ARM_TEE_PS_SET) {
|
||||
const psa_storage_uid_t *uid;
|
||||
const void *data;
|
||||
const psa_storage_create_flags_t *flags;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
size_t data_len;
|
||||
if (in_vec == NULL || in_len < 3) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
data = in_vec[1].base;
|
||||
flags = (const psa_storage_create_flags_t *)in_vec[2].base;
|
||||
/* Snapshot the NS-supplied length once into a Secure-stack local.
|
||||
* in_vec lives in NS memory and may be mutated concurrently (a
|
||||
* preempting NS interrupt or NS-accessible DMA), so re-reading
|
||||
* in_vec[1].len after the bounds check would allow a TOCTOU
|
||||
* double-fetch to grow the copy past WOLFBOOT_PS_MAX_DATA. */
|
||||
data_len = in_vec[1].len;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid) ||
|
||||
flags == NULL || in_vec[2].len < sizeof(*flags)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (data_len > WOLFBOOT_PS_MAX_DATA) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
entry = wolfboot_ps_alloc(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
} else if ((entry->flags & PSA_STORAGE_FLAG_WRITE_ONCE) != 0U) {
|
||||
return PSA_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
if (data_len > 0 && data == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (data_len > 0) {
|
||||
XMEMCPY(entry->data, data, data_len);
|
||||
}
|
||||
entry->size = data_len;
|
||||
entry->flags = *flags;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET) {
|
||||
const psa_storage_uid_t *uid;
|
||||
const rot_size_t *offset;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
size_t read_len;
|
||||
if (in_vec == NULL || in_len < 2 || out_vec == NULL || out_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
offset = (const rot_size_t *)in_vec[1].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid) ||
|
||||
offset == NULL || in_vec[1].len < sizeof(*offset)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
if (*offset > entry->size) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
read_len = entry->size - *offset;
|
||||
if (read_len > out_vec[0].len) {
|
||||
read_len = out_vec[0].len;
|
||||
}
|
||||
if (read_len > 0 && out_vec[0].base != NULL) {
|
||||
XMEMCPY(out_vec[0].base, entry->data + *offset, read_len);
|
||||
}
|
||||
out_vec[0].len = read_len;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET_INFO) {
|
||||
const psa_storage_uid_t *uid;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
if (in_vec == NULL || in_len < 1 || out_vec == NULL || out_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
{
|
||||
struct psa_storage_info_t info;
|
||||
info.capacity = WOLFBOOT_PS_MAX_DATA;
|
||||
info.size = entry->size;
|
||||
info.flags = entry->flags;
|
||||
if (out_vec[0].len < sizeof(info)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
XMEMCPY(out_vec[0].base, &info, sizeof(info));
|
||||
out_vec[0].len = sizeof(info);
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_REMOVE) {
|
||||
const psa_storage_uid_t *uid;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
if (in_vec == NULL || in_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
wc_ForceZero(entry->data, sizeof(entry->data));
|
||||
entry->in_use = 0;
|
||||
entry->uid = 0;
|
||||
entry->size = 0;
|
||||
entry->flags = 0;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET_SUPPORT) {
|
||||
if (out_vec != NULL && out_len >= 1 && out_vec[0].base != NULL) {
|
||||
uint32_t support = 0;
|
||||
XMEMCPY(out_vec[0].base, &support, sizeof(support));
|
||||
out_vec[0].len = sizeof(support);
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
return arm_tee_psa_ps_dispatch(type, in_vec, in_len, out_vec, out_len);
|
||||
}
|
||||
|
||||
if (handle == (psa_handle_t)ARM_TEE_ATTESTATION_HANDLE) {
|
||||
|
|
@ -1007,6 +879,151 @@ static int32_t arm_tee_psa_dispatch(psa_handle_t handle, int32_t type,
|
|||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static int32_t arm_tee_psa_ps_dispatch(int32_t type, const psa_invec *in_vec,
|
||||
size_t in_len, psa_outvec *out_vec, size_t out_len)
|
||||
{
|
||||
if (type == ARM_TEE_PS_SET) {
|
||||
const psa_storage_uid_t *uid;
|
||||
const void *data;
|
||||
const psa_storage_create_flags_t *flags;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
size_t data_len;
|
||||
if (in_vec == NULL || in_len < 3) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
data = in_vec[1].base;
|
||||
flags = (const psa_storage_create_flags_t *)in_vec[2].base;
|
||||
/* Snapshot the NS-supplied length once into a Secure-stack local.
|
||||
* in_vec lives in NS memory and may be mutated concurrently (a
|
||||
* preempting NS interrupt or NS-accessible DMA), so re-reading
|
||||
* in_vec[1].len after the bounds check would allow a TOCTOU
|
||||
* double-fetch to grow the copy past WOLFBOOT_PS_MAX_DATA. */
|
||||
data_len = in_vec[1].len;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid) ||
|
||||
flags == NULL || in_vec[2].len < sizeof(*flags)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (data_len > WOLFBOOT_PS_MAX_DATA) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
entry = wolfboot_ps_alloc(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
} else if ((entry->flags & PSA_STORAGE_FLAG_WRITE_ONCE) != 0U) {
|
||||
return PSA_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
if (data_len > 0 && data == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (data_len > 0) {
|
||||
XMEMCPY(entry->data, data, data_len);
|
||||
}
|
||||
entry->size = data_len;
|
||||
entry->flags = *flags;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET) {
|
||||
const psa_storage_uid_t *uid;
|
||||
const rot_size_t *offset;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
size_t read_len;
|
||||
if (in_vec == NULL || in_len < 2 || out_vec == NULL || out_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
offset = (const rot_size_t *)in_vec[1].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid) ||
|
||||
offset == NULL || in_vec[1].len < sizeof(*offset)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
if (*offset > entry->size) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
read_len = entry->size - *offset;
|
||||
if (read_len > out_vec[0].len) {
|
||||
read_len = out_vec[0].len;
|
||||
}
|
||||
if (read_len > 0 && out_vec[0].base != NULL) {
|
||||
XMEMCPY(out_vec[0].base, entry->data + *offset, read_len);
|
||||
}
|
||||
out_vec[0].len = read_len;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET_INFO) {
|
||||
const psa_storage_uid_t *uid;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
if (in_vec == NULL || in_len < 1 || out_vec == NULL || out_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
{
|
||||
struct psa_storage_info_t info;
|
||||
info.capacity = WOLFBOOT_PS_MAX_DATA;
|
||||
info.size = entry->size;
|
||||
info.flags = entry->flags;
|
||||
if (out_vec[0].len < sizeof(info)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
XMEMCPY(out_vec[0].base, &info, sizeof(info));
|
||||
out_vec[0].len = sizeof(info);
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_REMOVE) {
|
||||
const psa_storage_uid_t *uid;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
if (in_vec == NULL || in_len < 1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
if (uid == NULL || in_vec[0].len < sizeof(*uid)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
if (entry == NULL) {
|
||||
return PSA_ERROR_DOES_NOT_EXIST;
|
||||
}
|
||||
wc_ForceZero(entry->data, sizeof(entry->data));
|
||||
entry->in_use = 0;
|
||||
entry->uid = 0;
|
||||
entry->size = 0;
|
||||
entry->flags = 0;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
if (type == ARM_TEE_PS_GET_SUPPORT) {
|
||||
if (out_vec != NULL && out_len >= 1 && out_vec[0].base != NULL) {
|
||||
uint32_t support = 0;
|
||||
XMEMCPY(out_vec[0].base, &support, sizeof(support));
|
||||
out_vec[0].len = sizeof(support);
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
int32_t arm_tee_psa_test_ps_dispatch(int32_t type, const psa_invec *in_vec,
|
||||
size_t in_len, psa_outvec *out_vec, size_t out_len)
|
||||
{
|
||||
return arm_tee_psa_ps_dispatch(type, in_vec, in_len, out_vec, out_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t arm_tee_psa_call(psa_handle_t handle, int32_t type,
|
||||
const psa_invec *in_vec, size_t in_len,
|
||||
psa_outvec *out_vec, size_t out_len)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ TESTS+=unit-otp-keystore
|
|||
TESTS+=unit-x86-paging-oob
|
||||
TESTS+=unit-fwtpm-nv-oob
|
||||
TESTS+=unit-elf-bss-guard
|
||||
TESTS+=unit-arm-tee-psa-ipc
|
||||
TESTS+=unit-va416x0-fram
|
||||
|
||||
# linux_loader.c is x86 32-bit only, so its unit tests need a working 32-bit
|
||||
# (multilib) toolchain. Probe whether "gcc -m32" can link, and only add the
|
||||
|
|
@ -277,6 +279,14 @@ unit-store-sbrk: unit-store-sbrk.c ../../src/store_sbrk.c
|
|||
unit-string: ../../include/target.h unit-string.c
|
||||
gcc -o $@ $^ $(CFLAGS) -DDEBUG_UART -DPRINTF_ENABLED $(LDFLAGS)
|
||||
|
||||
unit-arm-tee-psa-ipc: ../../include/target.h unit-arm-tee-psa-ipc.c ../../src/arm_tee_psa_ipc.c
|
||||
gcc -o $@ unit-arm-tee-psa-ipc.c $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFPSA)/wolfpsa \
|
||||
-ffunction-sections -fdata-sections \
|
||||
$(LDFLAGS) -Wl,--gc-sections
|
||||
|
||||
unit-va416x0-fram: unit-va416x0-fram.c ../../hal/va416x0.c
|
||||
gcc -o $@ unit-va416x0-fram.c $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-max-space: ../../include/target.h unit-max-space.c
|
||||
gcc -o $@ $^ $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef UNIT_TEST_ARM_CMSE_H
|
||||
#define UNIT_TEST_ARM_CMSE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CMSE_NONSECURE 0
|
||||
#define cmse_check_address_range(ptr, size, flags) \
|
||||
((void *)(uintptr_t)(ptr))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
#include <check.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
void ForceZero(void *mem, size_t len)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)mem;
|
||||
|
||||
while (len-- > 0) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wc_ForceZero(void *mem, size_t len)
|
||||
{
|
||||
ForceZero(mem, len);
|
||||
}
|
||||
|
||||
#include "../../src/arm_tee_psa_ipc.c"
|
||||
|
||||
static void reset_ps_state(void)
|
||||
{
|
||||
memset(g_ps_entries, 0, sizeof(g_ps_entries));
|
||||
}
|
||||
|
||||
START_TEST(test_ps_set_rejects_short_uid_vector)
|
||||
{
|
||||
psa_storage_uid_t uid = 0x1122334455667788ULL;
|
||||
psa_storage_create_flags_t flags = 0;
|
||||
uint8_t data[4] = {1, 2, 3, 4};
|
||||
psa_invec in_vec[3];
|
||||
|
||||
reset_ps_state();
|
||||
in_vec[0].base = &uid;
|
||||
in_vec[0].len = sizeof(uid) - 1;
|
||||
in_vec[1].base = data;
|
||||
in_vec[1].len = sizeof(data);
|
||||
in_vec[2].base = &flags;
|
||||
in_vec[2].len = sizeof(flags);
|
||||
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_SET, in_vec, 3, NULL, 0),
|
||||
PSA_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ps_get_rejects_short_offset_vector)
|
||||
{
|
||||
psa_storage_uid_t uid = 7;
|
||||
rot_size_t offset = 0;
|
||||
uint8_t out[8];
|
||||
psa_invec in_vec[2];
|
||||
psa_outvec out_vec[1];
|
||||
|
||||
reset_ps_state();
|
||||
g_ps_entries[0].uid = uid;
|
||||
g_ps_entries[0].size = 4;
|
||||
g_ps_entries[0].in_use = 1;
|
||||
|
||||
in_vec[0].base = &uid;
|
||||
in_vec[0].len = sizeof(uid);
|
||||
in_vec[1].base = &offset;
|
||||
in_vec[1].len = sizeof(offset) - 1;
|
||||
out_vec[0].base = out;
|
||||
out_vec[0].len = sizeof(out);
|
||||
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_GET, in_vec, 2, out_vec, 1),
|
||||
PSA_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ps_get_info_rejects_short_uid_vector)
|
||||
{
|
||||
psa_storage_uid_t uid = 9;
|
||||
struct psa_storage_info_t info;
|
||||
psa_invec in_vec[1];
|
||||
psa_outvec out_vec[1];
|
||||
|
||||
reset_ps_state();
|
||||
in_vec[0].base = &uid;
|
||||
in_vec[0].len = sizeof(uid) - 1;
|
||||
out_vec[0].base = &info;
|
||||
out_vec[0].len = sizeof(info);
|
||||
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_GET_INFO, in_vec, 1, out_vec, 1),
|
||||
PSA_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ps_remove_rejects_short_uid_vector)
|
||||
{
|
||||
psa_storage_uid_t uid = 11;
|
||||
psa_invec in_vec[1];
|
||||
|
||||
reset_ps_state();
|
||||
in_vec[0].base = &uid;
|
||||
in_vec[0].len = sizeof(uid) - 1;
|
||||
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_REMOVE, in_vec, 1, NULL, 0),
|
||||
PSA_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ps_set_get_info_remove_success_path)
|
||||
{
|
||||
psa_storage_uid_t uid = 0xA5A5A5A5U;
|
||||
psa_storage_create_flags_t flags = 0;
|
||||
rot_size_t offset = 1;
|
||||
uint8_t data[] = {0x10, 0x20, 0x30, 0x40};
|
||||
uint8_t read_buf[4] = {0};
|
||||
struct psa_storage_info_t info;
|
||||
psa_invec set_in[3];
|
||||
psa_invec get_in[2];
|
||||
psa_invec info_in[1];
|
||||
psa_invec remove_in[1];
|
||||
psa_outvec get_out[1];
|
||||
psa_outvec info_out[1];
|
||||
|
||||
reset_ps_state();
|
||||
|
||||
set_in[0].base = &uid;
|
||||
set_in[0].len = sizeof(uid);
|
||||
set_in[1].base = data;
|
||||
set_in[1].len = sizeof(data);
|
||||
set_in[2].base = &flags;
|
||||
set_in[2].len = sizeof(flags);
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_SET, set_in, 3, NULL, 0),
|
||||
PSA_SUCCESS);
|
||||
|
||||
get_in[0].base = &uid;
|
||||
get_in[0].len = sizeof(uid);
|
||||
get_in[1].base = &offset;
|
||||
get_in[1].len = sizeof(offset);
|
||||
get_out[0].base = read_buf;
|
||||
get_out[0].len = sizeof(read_buf);
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_GET, get_in, 2, get_out, 1),
|
||||
PSA_SUCCESS);
|
||||
ck_assert_uint_eq(get_out[0].len, sizeof(data) - offset);
|
||||
ck_assert_mem_eq(read_buf, data + offset, sizeof(data) - offset);
|
||||
|
||||
info_in[0].base = &uid;
|
||||
info_in[0].len = sizeof(uid);
|
||||
info_out[0].base = &info;
|
||||
info_out[0].len = sizeof(info);
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_GET_INFO, info_in, 1, info_out, 1),
|
||||
PSA_SUCCESS);
|
||||
ck_assert_uint_eq(info.size, sizeof(data));
|
||||
ck_assert_uint_eq(info.flags, flags);
|
||||
|
||||
remove_in[0].base = &uid;
|
||||
remove_in[0].len = sizeof(uid);
|
||||
ck_assert_int_eq(
|
||||
arm_tee_psa_test_ps_dispatch(ARM_TEE_PS_REMOVE, remove_in, 1, NULL, 0),
|
||||
PSA_SUCCESS);
|
||||
ck_assert_int_eq(g_ps_entries[0].in_use, 0);
|
||||
ck_assert_uint_eq(g_ps_entries[0].size, 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *arm_tee_psa_ipc_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("arm-tee-psa-ipc");
|
||||
TCase *tc = tcase_create("protected-storage");
|
||||
|
||||
tcase_add_test(tc, test_ps_set_rejects_short_uid_vector);
|
||||
tcase_add_test(tc, test_ps_get_rejects_short_offset_vector);
|
||||
tcase_add_test(tc, test_ps_get_info_rejects_short_uid_vector);
|
||||
tcase_add_test(tc, test_ps_remove_rejects_short_uid_vector);
|
||||
tcase_add_test(tc, test_ps_set_get_info_remove_success_path);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = arm_tee_psa_ipc_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return fails;
|
||||
}
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
#include <check.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define WOLFBOOT_UNIT_TEST_VA416X0_FRAM
|
||||
|
||||
#define FRAM_SIZE (256U * 1024U)
|
||||
#define ROM_SPI_BANK 0
|
||||
#define SPI_NUM_BANKS 1
|
||||
#define SPI_STATUS_TFE_Msk 0x01U
|
||||
#define SPI_STATUS_BUSY_Msk 0x02U
|
||||
#define SPI_FIFO_CLR_RXFIFO_Msk 0x01U
|
||||
#define SPI_FIFO_CLR_TXFIFO_Msk 0x02U
|
||||
#define RAMFUNCTION
|
||||
|
||||
typedef enum {
|
||||
hal_status_ok = 0,
|
||||
hal_status_badParam = 1,
|
||||
hal_status_err = 2
|
||||
} hal_status_t;
|
||||
|
||||
typedef enum {
|
||||
hal_spi_state_reset = 0,
|
||||
hal_spi_state_ready = 1
|
||||
} hal_spi_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t STATUS;
|
||||
uint32_t FIFO_CLR;
|
||||
} mock_spi_bank_t;
|
||||
|
||||
typedef struct {
|
||||
mock_spi_bank_t BANK[SPI_NUM_BANKS];
|
||||
} mock_spi_regs_t;
|
||||
|
||||
typedef struct {
|
||||
bool blockmode;
|
||||
bool bmstall;
|
||||
int clkDiv;
|
||||
bool loopback;
|
||||
bool mdlycap;
|
||||
int mode;
|
||||
int ms;
|
||||
uint8_t chipSelect;
|
||||
int wordLen;
|
||||
} hal_spi_init_t;
|
||||
|
||||
typedef struct {
|
||||
bool locked;
|
||||
hal_spi_state_t state;
|
||||
mock_spi_bank_t *spi;
|
||||
hal_spi_init_t init;
|
||||
} hal_spi_handle_t;
|
||||
|
||||
enum {
|
||||
hal_spi_clkmode_0 = 0,
|
||||
hal_spi_ms_master = 1
|
||||
};
|
||||
|
||||
static mock_spi_regs_t mock_vor_spi;
|
||||
#define VOR_SPI (&mock_vor_spi)
|
||||
|
||||
static hal_status_t transmit_script[8];
|
||||
static bool transmit_close_flags[8];
|
||||
static int transmit_script_len;
|
||||
static int transmit_call_count;
|
||||
|
||||
static void set_transmit_script(const hal_status_t *script, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(transmit_close_flags, 0, sizeof(transmit_close_flags));
|
||||
for (i = 0; i < len; i++) {
|
||||
transmit_script[i] = script[i];
|
||||
}
|
||||
transmit_script_len = len;
|
||||
transmit_call_count = 0;
|
||||
}
|
||||
|
||||
hal_status_t HAL_Spi_Init(hal_spi_handle_t *handle)
|
||||
{
|
||||
(void)handle;
|
||||
return hal_status_ok;
|
||||
}
|
||||
|
||||
hal_status_t HAL_Spi_Transmit(hal_spi_handle_t *handle, uint8_t *data,
|
||||
uint32_t len, uint32_t timeout, bool close)
|
||||
{
|
||||
(void)handle;
|
||||
(void)data;
|
||||
(void)len;
|
||||
(void)timeout;
|
||||
|
||||
ck_assert_int_lt(transmit_call_count, transmit_script_len);
|
||||
transmit_close_flags[transmit_call_count] = close;
|
||||
|
||||
return transmit_script[transmit_call_count++];
|
||||
}
|
||||
|
||||
hal_status_t HAL_Spi_TransmitReceive(hal_spi_handle_t *handle, uint8_t *tx,
|
||||
uint8_t *rx, uint32_t tx_len, uint32_t rx_skip, uint32_t rx_len,
|
||||
uint32_t timeout, bool close)
|
||||
{
|
||||
(void)handle;
|
||||
(void)tx;
|
||||
(void)rx;
|
||||
(void)tx_len;
|
||||
(void)rx_skip;
|
||||
(void)rx_len;
|
||||
(void)timeout;
|
||||
(void)close;
|
||||
return hal_status_ok;
|
||||
}
|
||||
|
||||
void HAL_Timer_DelayMs(uint32_t delay)
|
||||
{
|
||||
(void)delay;
|
||||
}
|
||||
|
||||
int wolfBoot_printf(const char *fmt, ...)
|
||||
{
|
||||
(void)fmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "../../hal/va416x0.c"
|
||||
|
||||
static void reset_spi_mocks(void)
|
||||
{
|
||||
memset(&mock_vor_spi, 0, sizeof(mock_vor_spi));
|
||||
mock_vor_spi.BANK[0].STATUS = SPI_STATUS_TFE_Msk;
|
||||
}
|
||||
|
||||
START_TEST(test_fram_write_command_failure_aborts_split_transaction)
|
||||
{
|
||||
uint8_t buf[4] = {1, 2, 3, 4};
|
||||
hal_status_t init_script[] = {
|
||||
hal_status_ok, hal_status_ok, hal_status_ok
|
||||
};
|
||||
hal_status_t fail_script[] = {
|
||||
hal_status_ok, hal_status_err
|
||||
};
|
||||
hal_status_t success_script[] = {
|
||||
hal_status_ok, hal_status_ok, hal_status_ok
|
||||
};
|
||||
|
||||
reset_spi_mocks();
|
||||
|
||||
set_transmit_script(init_script, 3);
|
||||
ck_assert_int_eq(FRAM_Init(0, 0), hal_status_ok);
|
||||
ck_assert_int_eq(spiHandle.state, hal_spi_state_ready);
|
||||
|
||||
set_transmit_script(fail_script, 2);
|
||||
ck_assert_int_eq(FRAM_Write(0, 0x20, buf, sizeof(buf)), hal_status_err);
|
||||
ck_assert_int_eq(spiHandle.state, hal_spi_state_ready);
|
||||
ck_assert_uint_eq(mock_vor_spi.BANK[0].FIFO_CLR,
|
||||
SPI_FIFO_CLR_RXFIFO_Msk | SPI_FIFO_CLR_TXFIFO_Msk);
|
||||
ck_assert_int_eq(transmit_call_count, 2);
|
||||
ck_assert_int_eq(transmit_close_flags[0], true);
|
||||
ck_assert_int_eq(transmit_close_flags[1], false);
|
||||
|
||||
set_transmit_script(success_script, 3);
|
||||
ck_assert_int_eq(FRAM_Write(0, 0x24, buf, sizeof(buf)), hal_status_ok);
|
||||
ck_assert_int_eq(transmit_call_count, 3);
|
||||
ck_assert_int_eq(transmit_close_flags[0], true);
|
||||
ck_assert_int_eq(transmit_close_flags[1], false);
|
||||
ck_assert_int_eq(transmit_close_flags[2], true);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *va416x0_fram_suite(void)
|
||||
{
|
||||
Suite *s = suite_create("va416x0-fram");
|
||||
TCase *tc = tcase_create("fram");
|
||||
|
||||
tcase_add_test(tc, test_fram_write_command_failure_aborts_split_transaction);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fails;
|
||||
Suite *s = va416x0_fram_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
fails = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return fails;
|
||||
}
|
||||
Loading…
Reference in New Issue