Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
suit: Split fetch tests into app and SDFW
Browse files Browse the repository at this point in the history
Add tests that verify fetching into MEM component from both Application
and SDFW contexts.
Add smoke tests for IPUCs as MEM driver as well as cache backend.

Ref: NCSDK-30809

Signed-off-by: Tomasz Chyrowicz <[email protected]>
tomchy committed Jan 30, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 47ba23e commit e347557
Showing 14 changed files with 995 additions and 267 deletions.
10 changes: 8 additions & 2 deletions tests/subsys/suit/fetch/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -11,8 +11,14 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(integration_test_fetch)
include(../cmake/test_template.cmake)

target_include_directories(app PRIVATE mocks)

zephyr_library_link_libraries(suit_memptr_storage_interface)
zephyr_library_link_libraries(suit_platform_interface)
zephyr_library_link_libraries(suit_ipuc)
zephyr_library_link_libraries(suit_stream_filters_interface)
zephyr_library_link_libraries(suit_decrypt_test_utils)

zephyr_library_link_libraries_ifdef(CONFIG_TEST_SUIT_PLATFORM_FETCH_VARIANT_APP suit_memory_layout_interface)
zephyr_library_link_libraries_ifdef(CONFIG_TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW suit_decrypt_test_utils)
zephyr_library_link_libraries_ifdef(CONFIG_TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW suit_stream_filters_interface)

zephyr_compile_definitions(CONFIG_SOC_NRF54H20_CPUAPP)
34 changes: 34 additions & 0 deletions tests/subsys/suit/fetch/Kconfig
Original file line number Diff line number Diff line change
@@ -7,4 +7,38 @@
# Include and define MOCK_* Kconfigs
rsource "../mocks/Kconfig"

choice TEST_SUIT_PLATFORM_FETCH_VARIANT
prompt "SUIT platform implementation variant to test"
default TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW

config TEST_SUIT_PLATFORM_FETCH_VARIANT_APP
bool "Local or application"
depends on SUIT_PLATFORM_VARIANT_APP
select FLASH_IPUC
select SUIT_ENVELOPE_INFO
select SUIT_CACHE_RW
select SUIT_STREAM_SINK_CACHE
select SUIT_STREAM_FETCH_SOURCE_MGR

config TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW
bool "Bootloader or SDFW"
depends on SUIT_PLATFORM_VARIANT_SDFW
select MOCK_SDFW_ARBITER
select SUIT_EXECUTION_MODE
select SUIT_MCI
select SUIT_STREAM_FILTER_DECRYPT
select SUIT_CRYPTO

endchoice # TEST_SUIT_PLATFORM_FETCH_VARIANT

if TEST_SUIT_PLATFORM_FETCH_VARIANT_APP

config SUIT_CACHE_SDFW_IPUC_ID
default 254

config SUIT_CACHE_APP_IPUC_ID
default 255

endif # TEST_SUIT_PLATFORM_FETCH_VARIANT_APP

source "Kconfig.zephyr"
8 changes: 8 additions & 0 deletions tests/subsys/suit/fetch/boards/native_sim.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_FLASH_SIMULATOR=y
CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y
32 changes: 32 additions & 0 deletions tests/subsys/suit/fetch/boards/native_sim.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = < 0x1 >;
#size-cells = < 0x1 >;

dfu_partition: partition@f5000 {
reg = < 0xf5000 DT_SIZE_K(4) >;
};

dfu_cache_partition_1: partition@f6000 {
reg = <0xf6000 DT_SIZE_K(4)>;
};

dfu_cache_partition_3: partition@f7000 {
reg = <0xf7000 DT_SIZE_K(4)>;
};
};
};

/ {
sram0: memory@20000000 {
compatible = "mmio-sram";
reg = <0x20000000 DT_SIZE_K(256)>;
};
};
8 changes: 8 additions & 0 deletions tests/subsys/suit/fetch/boards/native_sim_64.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_FLASH_SIMULATOR=y
CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y
32 changes: 32 additions & 0 deletions tests/subsys/suit/fetch/boards/native_sim_64.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = < 0x1 >;
#size-cells = < 0x1 >;

dfu_partition: partition@f5000 {
reg = < 0xf5000 DT_SIZE_K(4) >;
};

dfu_cache_partition_1: partition@f6000 {
reg = <0xf6000 DT_SIZE_K(4)>;
};

dfu_cache_partition_3: partition@f7000 {
reg = <0xf7000 DT_SIZE_K(4)>;
};
};
};

/ {
sram0: memory@20000000 {
compatible = "mmio-sram";
reg = <0x20000000 DT_SIZE_K(256)>;
};
};
16 changes: 16 additions & 0 deletions tests/subsys/suit/fetch/boards/nrf54h20dk_nrf54h20_cpuapp.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

#Logging and printk is using standard UART.
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_BACKEND_UART=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_BUFFER_SIZE=8192
38 changes: 38 additions & 0 deletions tests/subsys/suit/fetch/boards/nrf54h20dk_nrf54h20_cpuapp.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

/* Split DFU partition into a smaller one and DFU caches. */
/delete-node/ &dfu_partition;

&mram1x {
erase-block-size = < 0x10 >;
/* Hardcoded inside the soc_flash_nrf_mram.c (MRAM_WORD_SIZE) */
write-block-size = < 0x10 >;

cpuapp_rw_partitions: cpuapp-rw-partitions {
compatible = "nordic,owned-partitions", "fixed-partitions";
status = "okay";
nordic,access = <NRF_OWNER_ID_APPLICATION NRF_PERM_RW>;
#address-cells = < 0x1 >;
#size-cells = < 0x1 >;

dfu_partition: partition@19d000 {
reg = < 0x19d000 DT_SIZE_K(1) >;
};

dfu_cache_partition_1: partition@19d400 {
reg = <0x19d400 DT_SIZE_K(1)>;
};

dfu_cache_partition_3: partition@19d800 {
reg = <0x19d800 DT_SIZE_K(1)>;
};

__mpc_override_align: partition@19dc00 {
reg = <0x19dc00 DT_SIZE_K(1)>;
};
};
};
29 changes: 29 additions & 0 deletions tests/subsys/suit/fetch/mocks/mock_suit_ipuc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef MOCK_SUIT_IPUC_H__
#define MOCK_SUIT_IPUC_H__

#include <suit_ipuc.h>
#include <zephyr/fff.h>

DEFINE_FFF_GLOBALS;

FAKE_VALUE_FUNC(int, suit_ipuc_get_count, size_t *);
FAKE_VALUE_FUNC(int, suit_ipuc_get_info, size_t, struct zcbor_string *, suit_manifest_role_t *);
FAKE_VALUE_FUNC(int, suit_ipuc_write_setup, struct zcbor_string *, struct zcbor_string *,
struct zcbor_string *);
FAKE_VALUE_FUNC(int, suit_ipuc_write, struct zcbor_string *, size_t, uintptr_t, size_t, bool);

static inline void mock_suit_ipuc_reset(void)
{
RESET_FAKE(suit_ipuc_get_count);
RESET_FAKE(suit_ipuc_get_info);
RESET_FAKE(suit_ipuc_write_setup);
RESET_FAKE(suit_ipuc_write);
}

#endif /* MOCK_SUIT_IPUC_H__ */
8 changes: 2 additions & 6 deletions tests/subsys/suit/fetch/prj.conf
Original file line number Diff line number Diff line change
@@ -22,16 +22,12 @@ CONFIG_SUIT_UTILS=y
CONFIG_SUIT_CACHE=y
CONFIG_SUIT_MEMPTR_STORAGE=y

CONFIG_SUIT_LOG_LEVEL_DBG=y

CONFIG_ZCBOR=y
CONFIG_ZCBOR_CANONICAL=y

CONFIG_FLASH=y
CONFIG_FLASH_MAP=y

CONFIG_SUIT_IPUC=y
CONFIG_MOCK_SDFW_ARBITER=y

CONFIG_SUIT_EXECUTION_MODE=y
CONFIG_SUIT_MCI=y
CONFIG_SUIT_STREAM_FILTER_DECRYPT=y
CONFIG_SUIT_CRYPTO=y
262 changes: 3 additions & 259 deletions tests/subsys/suit/fetch/src/main.c
Original file line number Diff line number Diff line change
@@ -8,15 +8,7 @@
#include <suit_platform.h>
#include <suit_memptr_storage.h>
#include <suit_platform_internal.h>
#include <suit_ipuc_sdfw.h>
#include <suit_dfu_cache.h>
#include <mocks_sdfw.h>
#include <psa/crypto.h>
#include <suit_decrypt_filter.h>
#include <decrypt_test_utils.h>

#define TEST_DATA_SIZE 64
#define WRITE_ADDR 0x1A00080000

static uint8_t test_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -91,58 +83,14 @@ static void setup_cache_with_sample_entries(void)
dfu_caches.pools[1].size = (size_t)cache2_len;
dfu_caches.pools_count = 2;

suit_dfu_cache_deinitialize();

suit_plat_err_t rc = suit_dfu_cache_initialize(&dfu_caches);

zassert_equal(rc, SUIT_PLAT_SUCCESS, "Failed to initialize cache: %i", rc);
}

static void test_before(void *data)
{
/* Reset mocks */
mocks_sdfw_reset();

/* Reset common FFF internal structures */
FFF_RESET_HISTORY();
}

ZTEST_SUITE(fetch_tests, NULL, NULL, test_before, NULL, NULL);

ZTEST(fetch_tests, test_integrated_fetch_to_msink_OK)
{
struct zcbor_string source = {.value = test_data, .len = sizeof(test_data)};
/* Create handle that will be used as destination */
suit_component_t dst_handle;
/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_dst_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_dst_component_id = {
.value = valid_dst_value,
.len = sizeof(valid_dst_value),
};

int ipc_client_id = 1234;
int ret = suit_plat_create_component_handle(&valid_dst_component_id, false, &dst_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);
ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found");

ret = suit_ipuc_sdfw_declare(dst_handle, SUIT_MANIFEST_UNKNOWN);
zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - error %i", ret);

ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - error %i", ret);

ret = suit_plat_fetch_integrated(dst_handle, &source, &valid_dst_component_id, NULL);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found");

ret = suit_plat_release_component_handle(dst_handle);
zassert_equal(ret, SUIT_SUCCESS, "dst_handle release failed - error %i", ret);
}
ZTEST_SUITE(fetch_tests, NULL, NULL, NULL, NULL, NULL);

ZTEST(fetch_tests, test_integrated_fetch_to_memptr_OK)
{
@@ -356,207 +304,3 @@ ZTEST(fetch_tests, test_integrated_fetch_to_memptr_NOK_handle_NULL)
ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);
}

ZTEST(fetch_tests, test_integrated_fetch_to_msink_encrypted_OK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {
.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)
};

/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

status = decrypt_test_init_encryption_key(decrypt_test_key_data,
sizeof(decrypt_test_key_data), &cek_key_id,
PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info =
DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source,
&valid_manifest_component_id, &enc_info);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;


ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_equal(memcmp(decrypt_test_plaintext, payload,
strlen(decrypt_test_plaintext)), 0,
"Retrieved decrypted payload doesn't mach decrypt_test_plaintext");
zassert_equal(sizeof(decrypt_test_plaintext), payload_size,
"Retrieved payload_size doesn't mach size of decrypt_test_plaintext");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}

ZTEST(fetch_tests, test_integrated_fetch_to_memptr_encrypted_NOK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {
.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)
};

/* [h'CAND_IMG', h'02'] */
uint8_t valid_value[] = {0x82, 0x49, 0x68, 'C', 'A', 'N', 'D',
'_', 'I', 'M', 'G', 0x41, 0x02};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

status = decrypt_test_init_encryption_key(decrypt_test_key_data,
sizeof(decrypt_test_key_data), &cek_key_id,
PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info =
DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source,
&valid_manifest_component_id, &enc_info);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;


ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_not_equal(memcmp(decrypt_test_plaintext, payload,
strlen(decrypt_test_plaintext)), 0,
"Retrieved decrypted payload should not mach decrypt_test_plaintext");
zassert_equal(sizeof(decrypt_test_plaintext), payload_size,
"Retrieved payload_size doesn't mach size of decrypt_test_plaintext");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}

ZTEST(fetch_tests, test_integrated_fetch_to_msink_encrypted_wrong_key_NOK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {
.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)
};

/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

uint8_t wrong_test_key_data[sizeof(decrypt_test_key_data)];

memcpy(wrong_test_key_data, decrypt_test_key_data, sizeof(wrong_test_key_data));
/* Corrupt CEK that we store.*/
wrong_test_key_data[10] = 0x00;

status = decrypt_test_init_encryption_key(wrong_test_key_data,
sizeof(wrong_test_key_data), &cek_key_id,
PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info =
DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source,
&valid_manifest_component_id, &enc_info);
zassert_equal(ret, SUIT_ERR_AUTHENTICATION,
"suit_plat_fetch should have failed with SUIT_ERR_AUTHENTICATION");

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;

ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_not_equal(memcmp(decrypt_test_plaintext, payload,
strlen(decrypt_test_plaintext)), 0,
"Retrieved decrypted payload should not mach decrypt_test_plaintext");
zassert_equal(payload_size, 0,
"Retrieved payload_size is not 0");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}
494 changes: 494 additions & 0 deletions tests/subsys/suit/fetch/src/test_app_ipuc.c

Large diffs are not rendered by default.

276 changes: 276 additions & 0 deletions tests/subsys/suit/fetch/src/test_sdfw_mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifdef CONFIG_TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW
#include <zephyr/ztest.h>
#include <suit_platform.h>
#include <suit_memptr_storage.h>
#include <suit_platform_internal.h>
#include <suit_dfu_cache.h>
#include <suit_ipuc_sdfw.h>
#include <mocks_sdfw.h>
#include <psa/crypto.h>
#include <suit_decrypt_filter.h>
#include <decrypt_test_utils.h>

static uint8_t test_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};

/* clang-format off */
static const uint8_t valid_manifest_component[] = {
0x82, /* array: 2 elements */
0x4c, /* byte string: 12 bytes */
0x6b, /* string: 11 characters */
'I', 'N', 'S', 'T', 'L', 'D', '_', 'M', 'F', 'S', 'T',
0x50, /* byte string: 16 bytes */
0x5b, 0x46, 0x9f, 0xd1, 0x90, 0xee, 0x53, 0x9c,
0xa3, 0x18, 0x68, 0x1b, 0x03, 0x69, 0x5e, 0x36
};
/* clang-format on */

static struct zcbor_string valid_manifest_component_id = {
.value = valid_manifest_component,
.len = sizeof(valid_manifest_component),
};

static void test_before(void *data)
{
/* Reset mocks */
mocks_sdfw_reset();

/* Reset common FFF internal structures */
FFF_RESET_HISTORY();
}

ZTEST_SUITE(fetch_sdfw_mem_tests, NULL, NULL, test_before, NULL, NULL);

ZTEST(fetch_sdfw_mem_tests, test_integrated_fetch_to_msink_OK)
{
struct zcbor_string source = {.value = test_data, .len = sizeof(test_data)};
/* Create handle that will be used as destination */
suit_component_t dst_handle;
/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_dst_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_dst_component_id = {
.value = valid_dst_value,
.len = sizeof(valid_dst_value),
};

int ipc_client_id = 1234;
int ret = suit_plat_create_component_handle(&valid_dst_component_id, false, &dst_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);
ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found");

ret = suit_ipuc_sdfw_declare(dst_handle, SUIT_MANIFEST_UNKNOWN);
zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_declare failed - error %i", ret);

ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_SUCCESS, "suit_ipuc_sdfw_write_setup failed - error %i", ret);

ret = suit_plat_fetch_integrated(dst_handle, &source, &valid_dst_component_id, NULL);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_ipuc_sdfw_write_setup(ipc_client_id, &valid_dst_component_id, NULL, NULL);
zassert_equal(ret, SUIT_PLAT_ERR_NOT_FOUND, "in-place updateable component found");

ret = suit_plat_release_component_handle(dst_handle);
zassert_equal(ret, SUIT_SUCCESS, "dst_handle release failed - error %i", ret);
}

ZTEST(fetch_tests, test_integrated_fetch_to_msink_encrypted_OK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)};

/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

status = decrypt_test_init_encryption_key(decrypt_test_key_data,
sizeof(decrypt_test_key_data), &cek_key_id,
PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info = DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source, &valid_manifest_component_id,
&enc_info);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;

ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_equal(memcmp(decrypt_test_plaintext, payload, strlen(decrypt_test_plaintext)), 0,
"Retrieved decrypted payload doesn't mach decrypt_test_plaintext");
zassert_equal(sizeof(decrypt_test_plaintext), payload_size,
"Retrieved payload_size doesn't mach size of decrypt_test_plaintext");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}

ZTEST(fetch_tests, test_integrated_fetch_to_memptr_encrypted_NOK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)};

/* [h'CAND_IMG', h'02'] */
uint8_t valid_value[] = {0x82, 0x49, 0x68, 'C', 'A', 'N', 'D',
'_', 'I', 'M', 'G', 0x41, 0x02};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

status = decrypt_test_init_encryption_key(decrypt_test_key_data,
sizeof(decrypt_test_key_data), &cek_key_id,
PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info = DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source, &valid_manifest_component_id,
&enc_info);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret);

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;

ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_not_equal(memcmp(decrypt_test_plaintext, payload, strlen(decrypt_test_plaintext)),
0, "Retrieved decrypted payload should not mach decrypt_test_plaintext");
zassert_equal(sizeof(decrypt_test_plaintext), payload_size,
"Retrieved payload_size doesn't mach size of decrypt_test_plaintext");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}

ZTEST(fetch_tests, test_integrated_fetch_to_msink_encrypted_wrong_key_NOK)
{
suit_component_t component_handle;
memptr_storage_handle_t handle = NULL;
struct zcbor_string source = {.value = decrypt_test_ciphertext_direct,
.len = sizeof(decrypt_test_ciphertext_direct)};

/* [h'MEM', h'02', h'1A00080000', h'191000'] */
uint8_t valid_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45,
0x1A, 0x00, 0x08, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00};

struct zcbor_string valid_component_id = {
.value = valid_value,
.len = sizeof(valid_value),
};

psa_key_id_t cek_key_id;
uint8_t cek_key_id_cbor[] = {
0x1A, 0x00, 0x00, 0x00, 0x00,
};

psa_status_t status = psa_crypto_init();

zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto");

uint8_t wrong_test_key_data[sizeof(decrypt_test_key_data)];

memcpy(wrong_test_key_data, decrypt_test_key_data, sizeof(wrong_test_key_data));
/* Corrupt CEK that we store.*/
wrong_test_key_data[10] = 0x00;

status = decrypt_test_init_encryption_key(wrong_test_key_data, sizeof(wrong_test_key_data),
&cek_key_id, PSA_ALG_GCM, cek_key_id_cbor);
zassert_equal(status, PSA_SUCCESS, "Failed to import key");

struct suit_encryption_info enc_info = DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor);

int ret = suit_plat_create_component_handle(&valid_component_id, false, &component_handle);

zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret);

ret = suit_plat_fetch_integrated(component_handle, &source, &valid_manifest_component_id,
&enc_info);
zassert_equal(ret, SUIT_ERR_AUTHENTICATION,
"suit_plat_fetch should have failed with SUIT_ERR_AUTHENTICATION");

ret = suit_plat_component_impl_data_get(component_handle, &handle);
zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i",
ret);

const uint8_t *payload;
size_t payload_size = 0;

ret = suit_memptr_storage_ptr_get(handle, &payload, &payload_size);

zassert_equal(ret, SUIT_PLAT_SUCCESS, "storage.get failed - error %i", ret);
zassert_not_equal(memcmp(decrypt_test_plaintext, payload, strlen(decrypt_test_plaintext)),
0, "Retrieved decrypted payload should not mach decrypt_test_plaintext");
zassert_equal(payload_size, 0, "Retrieved payload_size is not 0");

ret = suit_plat_release_component_handle(component_handle);
zassert_equal(ret, SUIT_SUCCESS, "Handle release failed - error %i", ret);

psa_destroy_key(cek_key_id);
}
#endif /* CONFIG_TEST_SUIT_PLATFORM_FETCH_VARIANT_SDFW */
15 changes: 15 additions & 0 deletions tests/subsys/suit/fetch/testcase.yaml
Original file line number Diff line number Diff line change
@@ -13,3 +13,18 @@ tests:
- nrf52840dk/nrf52840
- native_sim
- native_sim/native/64

suit-platform.integration.fetch.app:
platform_allow:
- native_sim
- native_sim/native/64
tags:
- suit-processor
- suit_platform
- suit
- ci_tests_subsys_suit
extra_configs:
- CONFIG_SUIT_PLATFORM_VARIANT_APP=y
integration_platforms:
- native_sim
- native_sim/native/64

0 comments on commit e347557

Please sign in to comment.