From 224ee0d8e98dfba0cc0e42e34a03785c5559542e Mon Sep 17 00:00:00 2001 From: Michal Kozikowski Date: Wed, 8 Jan 2025 14:32:13 +0100 Subject: [PATCH] tests: Extend SUIT tests for fetch, copy and write with decryption This commit extends integration tests for fetch, copy and write SUIT directives with test cases for payload decryption. Common test module decrypt_test_utils.c was added with default constants and utilities for decryption tests to use. Refactor of decrypt_filter/src/main.c was made because of this common module. Ref: NCSDK-31276 Signed-off-by: Michal Kozikowski --- tests/subsys/suit/common/CMakeLists.txt | 1 + .../suit/common/decrypt_utils/CMakeLists.txt | 18 ++ .../common/decrypt_utils/decrypt_test_utils.c | 133 +++++++++++ .../common/decrypt_utils/decrypt_test_utils.h | 65 +++++ tests/subsys/suit/copy/CMakeLists.txt | 1 + tests/subsys/suit/copy/prj.conf | 2 + tests/subsys/suit/copy/src/main.c | 99 ++++++++ .../subsys/suit/decrypt_filter/CMakeLists.txt | 1 + tests/subsys/suit/decrypt_filter/src/main.c | 219 ++++------------- tests/subsys/suit/fetch/CMakeLists.txt | 3 + tests/subsys/suit/fetch/prj.conf | 5 + tests/subsys/suit/fetch/src/main.c | 223 +++++++++++++++++- tests/subsys/suit/write/CMakeLists.txt | 1 + tests/subsys/suit/write/prj.conf | 2 + tests/subsys/suit/write/src/main.c | 51 ++++ 15 files changed, 653 insertions(+), 171 deletions(-) create mode 100644 tests/subsys/suit/common/decrypt_utils/CMakeLists.txt create mode 100644 tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.c create mode 100644 tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.h diff --git a/tests/subsys/suit/common/CMakeLists.txt b/tests/subsys/suit/common/CMakeLists.txt index 2ed45207c82c..0ed6db18c310 100644 --- a/tests/subsys/suit/common/CMakeLists.txt +++ b/tests/subsys/suit/common/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(mci_test) add_subdirectory(validator_test) +add_subdirectory(decrypt_utils) zephyr_include_directories(${CMAKE_CURRENT_LIST_DIR}/include) if (CONFIG_MBEDTLS) diff --git a/tests/subsys/suit/common/decrypt_utils/CMakeLists.txt b/tests/subsys/suit/common/decrypt_utils/CMakeLists.txt new file mode 100644 index 000000000000..e72dd241605c --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/CMakeLists.txt @@ -0,0 +1,18 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if (CONFIG_SUIT_STREAM_FILTER_DECRYPT) + zephyr_library_named(suit_decrypt_test_utils) + zephyr_include_directories(.) + zephyr_library_sources(decrypt_test_utils.c) + zephyr_library_link_libraries(suit_metadata) + + + if (CONFIG_MBEDTLS) + # Link MCI (incl. crypto) module with mbedTLS library, that provides PSA crypto APIs. + zephyr_library_link_libraries(mbedTLS) + endif() # CONFIG_MBEDTLS + +endif() diff --git a/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.c b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.c new file mode 100644 index 000000000000..07aad2f34f7b --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + +#include "decrypt_test_utils.h" + +/* This module holds common utilities for SUIT decrypt filter tests. + * It defines default encryption key data, plaintext and ciphertext along with other + * suit_encryption_info struct members that can be used while testing. + * + * WARNING: All of the const values defined in this module CAN be changed freely. + * This also means that any test depending on them should expect it. + */ + + +/** + * The master key used by these tests can be imported into the local KMS backend by running: + * + * nrfkms import_keyvalue -k TEST_AES_KEY -t aes -v aHWJdIkl5hdXw4SS1nTdVYE/q7ycMOZm2mR6qx/KvKw= + * + * The KEK below is derived from context "test" + * To acquire it run: + * nrfkms export_derived -k TEST_AES_KEY -c test --format native + * hexdump -e '16/1 "0x%02x, " "\n"' kms_output/derived_key_native_test_from_TEST_AES_KEY.bin + */ +const uint8_t decrypt_test_key_data[] = { + 0xf8, 0xfa, 0x8e, 0x7b, 0xed, 0x32, 0xd0, 0xc7, 0x15, 0x1f, 0xd9, 0xab, 0x0d, + 0x8d, 0xed, 0x95, 0x26, 0xa8, 0x6a, 0x15, 0x34, 0x16, 0x01, 0xcf, 0x9c, 0x6b, + 0xba, 0x00, 0x6a, 0xab, 0xaa, 0x9a, +}; + +const uint8_t decrypt_test_plaintext[] = { + "This is a sample plaintext for testing the decryption filter", +}; + +const uint8_t decrypt_test_aad[] = { + "sample aad" +}; + +/** + * Encryption and using wrapped CEK achieved by running: + * + * echo "This is a sample plaintext for testing the decryption filter" > plaintext.txt + * nrfkms wrap -k TEST_AES_KEY -c test -f plaintext.txt --format native -t aes --aad "sample aad" + * + * Wrapped CEK stored in the resulting wrapped_aek-aes-... file + * + * Ciphertext and NONCE (IV) taken from the encrypted_asset-... file, which is in format + * |nonce (12 bytes)|ciphertext|tag (16 bytes)| + * + */ +const uint8_t decrypt_test_wrapped_cek[] = { + 0x7d, 0xd6, 0xf4, 0xd3, 0x52, 0x44, 0x5a, 0x3a, 0x67, 0xb8, 0xcc, + 0x74, 0x5b, 0x4b, 0x6f, 0x70, 0x62, 0xc3, 0xf2, 0x7b, 0x6b, 0x14, + 0xf1, 0x06, 0x57, 0xa3, 0x68, 0x32, 0x44, 0xc3, 0x85, 0x77, 0x86, + 0xe7, 0xda, 0x15, 0xbf, 0xf8, 0x9e, 0x63, +}; + +const uint8_t decrypt_test_ciphertext_aes_kw[] = { + /* tag (16 bytes) */ + 0xdc, 0xe6, 0x95, 0xac, 0x0f, 0x61, 0x87, 0x17, 0x51, 0x48, 0xb4, 0xa1, + 0x8e, 0x09, 0x89, 0xb4, + /* ciphertext */ + 0x8b, 0xfb, 0xd9, 0xe4, 0xcf, 0xde, 0xf8, 0xcf, 0xe5, 0x69, 0x9d, 0x6d, + 0x92, 0x8a, 0x04, 0xf8, 0x26, 0x22, 0xd5, 0xd8, 0xe8, 0x77, 0x18, 0x5a, + 0x01, 0x13, 0xba, 0xd5, 0x23, 0x72, 0xae, 0x80, 0x44, 0xed, 0xea, 0xdf, + 0x74, 0x79, 0x8a, 0x83, 0x52, 0x72, 0x2f, 0x43, 0x06, 0xe9, 0xd4, 0xbb, + 0x54, 0x8a, 0x0d, 0xea, 0x7f, 0xe6, 0x48, 0xf0, 0xfd, 0x0e, 0xbb, 0xaa, + 0xa3, +}; + +const uint8_t decrypt_test_iv_aes_kw[] = { + 0x61, 0xb4, 0x70, 0x53, 0xa5, 0xe2, 0x05, 0x68, 0xfe, 0x77, 0x12, 0x89, +}; + +/** + * Encryption without wrapping CEK achieved by running: + * + * echo "This is a sample plaintext for testing the decryption filter" > plaintext.txt + * nrfkms encrypt -k TEST_AES_KEY -c test -f plaintext.txt --aad "sample aad" --format native + * + * Ciphertext and NONCE (IV) taken from the encrypted_data_using_TEST_AES_KEY-test.bin file, + * which is in format |nonce (12 bytes)|tag (16 bytes)|ciphertext| + */ + +const uint8_t decrypt_test_ciphertext_direct[] = { + /* tag (16 bytes) */ + 0x4d, 0x21, 0x30, 0xb7, 0xce, 0x8a, 0xd6, 0x00, 0xe4, 0x04, 0xbb, 0x32, + 0x72, 0x7a, 0xbb, 0x7c, + /* ciphertext */ + 0xf0, 0x72, 0xdb, 0x63, 0x03, 0xdd, 0x24, 0x69, + 0xd4, 0xbf, 0xd7, 0xa0, 0xec, 0xfa, 0x66, 0x58, 0x95, 0x2b, 0xc1, 0xc2, + 0x9d, 0x82, 0x02, 0x1a, 0xd7, 0x5b, 0xc0, 0x01, 0xce, 0x0b, 0x79, 0x53, + 0xe7, 0xdb, 0x0d, 0x35, 0xab, 0xef, 0x81, 0xc8, 0x68, 0xc5, 0xa7, 0x22, + 0x90, 0xea, 0xd0, 0x7f, 0x36, 0xed, 0x14, 0xbe, 0x30, 0xf2, 0x81, 0x56, + 0x7e, 0x2e, 0x5f, 0xd8, 0x7c, +}; + +const uint8_t decrypt_test_iv_direct[] = { + 0x60, 0x90, 0x6d, 0xb2, 0xfe, 0xc3, 0xc8, 0x5a, 0xf0, 0x28, 0xb1, 0xb6, +}; + +const suit_manifest_class_id_t decrypt_test_sample_class_id = { + {0x5b, 0x46, 0x9f, 0xd1, 0x90, 0xee, 0x53, 0x9c, 0xa3, 0x18, 0x68, 0x1b, 0x03, 0x69, 0x5e, + 0x36}}; + +psa_status_t decrypt_test_init_encryption_key(const uint8_t *data, size_t size, + psa_key_id_t *key_id, psa_key_id_t alg, uint8_t *cbor_key_id) +{ + psa_status_t status; + + /* Configure the key attributes */ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); + psa_set_key_algorithm(&key_attributes, alg); + psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&key_attributes, 256); + + status = psa_import_key(&key_attributes, data, size, key_id); + + /* Encode KEK key ID as CBOR unsigned int */ + cbor_key_id[1] = ((*key_id >> 24) & 0xFF); + cbor_key_id[2] = ((*key_id >> 16) & 0xFF); + cbor_key_id[3] = ((*key_id >> 8) & 0xFF); + cbor_key_id[4] = ((*key_id >> 0) & 0xFF); + + return status; +} diff --git a/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.h b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.h new file mode 100644 index 000000000000..4cc3a9d12c41 --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include + +/* This module holds common utilities for SUIT decrypt filter tests. + * It defines default encryption key data, plaintext and ciphertext along with other + * suit_encryption_info struct members that can be used while testing. + * + * WARNING: All of the const values defined in this module CAN be changed freely. + * This also means that any test depending on them should expect it. + */ + + +/* Default initalization for suit_encryption_info struct. + * 'cek_key_id_cbor' - should be taken from init_encryption_key() call. + */ +#define DECRYPT_TEST_ENC_INFO_DEFAULT_INIT(cek_key_id_cbor) \ + { \ + .enc_alg_id = suit_cose_aes256_gcm, \ + .IV = { \ + .value = decrypt_test_iv_direct, \ + .len = sizeof(decrypt_test_iv_direct), \ + }, \ + .aad = { \ + .value = decrypt_test_aad, \ + .len = strlen(decrypt_test_aad), \ + }, \ + .kw_alg_id = suit_cose_direct, \ + .kw_key.direct = {.key_id = {.value = (cek_key_id_cbor), \ + .len = sizeof((cek_key_id_cbor))},} \ + } + +#define DECRYPT_TEST_KEY_LENGTH 32 +extern const uint8_t decrypt_test_key_data[DECRYPT_TEST_KEY_LENGTH]; + +#define DECRYPT_TEST_PLAINTEXT_LENGTH 61 +extern const uint8_t decrypt_test_plaintext[DECRYPT_TEST_PLAINTEXT_LENGTH]; + +#define DECRYPT_TEST_AAD_LENGTH 11 +extern const uint8_t decrypt_test_aad[DECRYPT_TEST_AAD_LENGTH]; + +#define DECRYPT_TEST_WRAPPED_CEK_LENGTH 40 +extern const uint8_t decrypt_test_wrapped_cek[DECRYPT_TEST_WRAPPED_CEK_LENGTH]; + +#define DECRYPT_TEST_CIPHERTEXT_AES_KW_LENGTH (DECRYPT_TEST_PLAINTEXT_LENGTH + 16) +extern const uint8_t decrypt_test_ciphertext_aes_kw[DECRYPT_TEST_CIPHERTEXT_AES_KW_LENGTH]; + +#define DECRYPT_TEST_IV_AES_KW_LENGTH 12 +extern const uint8_t decrypt_test_iv_aes_kw[DECRYPT_TEST_IV_AES_KW_LENGTH]; + +#define DECRYPT_TEST_CIPHERTEXT_DIRECT_LENGTH (DECRYPT_TEST_PLAINTEXT_LENGTH + 16) +extern const uint8_t decrypt_test_ciphertext_direct[DECRYPT_TEST_CIPHERTEXT_DIRECT_LENGTH]; + +#define DECRYPT_TEST_IV_DIRECT_LENGTH 12 +extern const uint8_t decrypt_test_iv_direct[DECRYPT_TEST_IV_DIRECT_LENGTH]; + +extern const suit_manifest_class_id_t decrypt_test_sample_class_id; + +psa_status_t decrypt_test_init_encryption_key(const uint8_t *data, size_t size, + psa_key_id_t *key_id, psa_key_id_t alg, uint8_t *cbor_key_id); diff --git a/tests/subsys/suit/copy/CMakeLists.txt b/tests/subsys/suit/copy/CMakeLists.txt index 11c0b22fb8df..baa1290af4d2 100644 --- a/tests/subsys/suit/copy/CMakeLists.txt +++ b/tests/subsys/suit/copy/CMakeLists.txt @@ -17,3 +17,4 @@ zephyr_library_link_libraries(suit_memptr_storage_interface) zephyr_library_link_libraries(suit_sink_selector_interface) zephyr_library_link_libraries(suit_storage_interface) zephyr_library_link_libraries(suit_manifest_variables) +zephyr_library_link_libraries(suit_decrypt_test_utils) diff --git a/tests/subsys/suit/copy/prj.conf b/tests/subsys/suit/copy/prj.conf index 96c394a2708e..76474a28c947 100644 --- a/tests/subsys/suit/copy/prj.conf +++ b/tests/subsys/suit/copy/prj.conf @@ -35,3 +35,5 @@ CONFIG_FLASH_MAP=y CONFIG_SUIT_IPUC=y CONFIG_MOCK_SDFW_ARBITER=y + +CONFIG_SUIT_STREAM_FILTER_DECRYPT=y diff --git a/tests/subsys/suit/copy/src/main.c b/tests/subsys/suit/copy/src/main.c index c5dda79b6a08..69575dbf098c 100644 --- a/tests/subsys/suit/copy/src/main.c +++ b/tests/subsys/suit/copy/src/main.c @@ -16,6 +16,7 @@ #include #include #include +#include #define WRITE_ADDR 0x1A00080000 #define TEST_MFST_VAR_NVM_ID 1 @@ -653,3 +654,101 @@ ZTEST(copy_tests, test_mfst_nvm_var_to_mram_NOK) zassert_equal(ret, SUIT_SUCCESS, "Failed to release destination component handle after the test: %d", ret); } + +ZTEST(copy_tests, test_integrated_fetch_and_copy_to_msink_encrypted_OK) +{ + memptr_storage_handle_t handle; + struct zcbor_string source = { + .value = decrypt_test_ciphertext_direct, + .len = sizeof(decrypt_test_ciphertext_direct) + }; + + suit_component_t src_handle; + /* [h'CAND_IMG', h'02'] */ + uint8_t valid_src_value[] = {0x82, 0x49, 0x68, 'C', 'A', 'N', 'D', + '_', 'I', 'M', 'G', 0x41, 0x02}; + + struct zcbor_string valid_src_component_id = { + .value = valid_src_value, + .len = sizeof(valid_src_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_src_component_id, false, &src_handle); + + zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); + + ret = suit_plat_fetch_integrated(src_handle, &source, &valid_manifest_component_id, NULL); + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_fetch failed - error %i", ret); + + ret = suit_plat_component_impl_data_get(src_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_ptr(decrypt_test_ciphertext_direct, payload, + "Retrieved payload doesn't mach ciphertext_direct"); + zassert_equal(sizeof(decrypt_test_ciphertext_direct), payload_size, + "Retrieved payload_size doesn't mach size of ciphertext_direct"); + zassert_not_null(payload, "Retrieved payload is NULL"); + + /* 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), + }; + + 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_plat_copy(dst_handle, src_handle, &valid_manifest_component_id, &enc_info); + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_copy failed - error %i", ret); + + ret = suit_plat_component_impl_data_get(dst_handle, &handle); + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_component_impl_data_get failed - error %i", + ret); + + 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(dst_handle); + zassert_equal(ret, SUIT_SUCCESS, "dst_handle release failed - error %i", ret); + + ret = suit_plat_release_component_handle(src_handle); + zassert_equal(ret, SUIT_SUCCESS, "src_handle release failed - error %i", ret); + + ret = suit_memptr_storage_release(handle); + zassert_equal(ret, SUIT_PLAT_SUCCESS, "memptr_storage handle release failed - error %i", + ret); + + psa_destroy_key(cek_key_id); +} diff --git a/tests/subsys/suit/decrypt_filter/CMakeLists.txt b/tests/subsys/suit/decrypt_filter/CMakeLists.txt index 9035df0f3090..43ddc6065698 100644 --- a/tests/subsys/suit/decrypt_filter/CMakeLists.txt +++ b/tests/subsys/suit/decrypt_filter/CMakeLists.txt @@ -18,3 +18,4 @@ target_include_directories(suit_mci INTERFACE ${ZEPHYR_NRF_MODULE_DIR}/subsys/su zephyr_library_link_libraries(suit_stream_filters_interface) zephyr_library_link_libraries(suit_stream_sources_interface) zephyr_library_link_libraries(suit_mci) +zephyr_library_link_libraries(suit_decrypt_test_utils) diff --git a/tests/subsys/suit/decrypt_filter/src/main.c b/tests/subsys/suit/decrypt_filter/src/main.c index f285d2712485..3c5b6d064f4c 100644 --- a/tests/subsys/suit/decrypt_filter/src/main.c +++ b/tests/subsys/suit/decrypt_filter/src/main.c @@ -11,6 +11,7 @@ #include #include #include +#include /* Forward declaration of the internal, temporary AES key-unwrap implementation. */ psa_status_t suit_aes_key_unwrap_manual(psa_key_id_t kek_key_id, const uint8_t *wrapped_cek, @@ -22,22 +23,6 @@ DEFINE_FFF_GLOBALS; FAKE_VALUE_FUNC(int, suit_mci_fw_encryption_key_id_validate, const suit_manifest_class_id_t *, uint32_t); -/** - * The master key used by these tests can be imported into the local KMS backend by running: - * - * nrfkms import_keyvalue -k TEST_AES_KEY -t aes -v aHWJdIkl5hdXw4SS1nTdVYE/q7ycMOZm2mR6qx/KvKw= - * - * The KEK below is derived from context "test" - * To acquire ut run: - * nrfkms export_derived -k TEST_AES_KEY -c test --format native - * hexdump -e '16/1 "0x%02x, " "\n"' kms_output/derived_key_native_test_from_TEST_AES_KEY.bin - */ -static const uint8_t test_key_data[] = { - 0xf8, 0xfa, 0x8e, 0x7b, 0xed, 0x32, 0xd0, 0xc7, 0x15, 0x1f, 0xd9, 0xab, 0x0d, - 0x8d, 0xed, 0x95, 0x26, 0xa8, 0x6a, 0x15, 0x34, 0x16, 0x01, 0xcf, 0x9c, 0x6b, - 0xba, 0x00, 0x6a, 0xab, 0xaa, 0x9a, -}; - static uint8_t kek_key_id_cbor[] = { 0x1A, 0x00, 0x00, 0x00, 0x00, }; @@ -47,109 +32,8 @@ struct suit_decrypt_filter_tests_fixture { psa_key_id_t key_id; }; -static const uint8_t plaintext[] = { - "This is a sample plaintext for testing the decryption filter", -}; - -static const uint8_t aad[] = { - "sample aad" -}; - -/** - * Encryption and using wrapped CEK achieved by running: - * - * echo "This is a sample plaintext for testing the decryption filter" > plaintext.txt - * nrfkms wrap -k TEST_AES_KEY -c test -f plaintext.txt --format native -t aes --aad "sample aad" - * - * Wrapped CEK stored in the resulting wrapped_aek-aes-... file - * - * Ciphertext and NONCE (IV) taken from the encrypted_asset-... file, which is in format - * |nonce (12 bytes)|ciphertext|tag (16 bytes)| - * - */ -static const uint8_t wrapped_cek[] = { - 0x7d, 0xd6, 0xf4, 0xd3, 0x52, 0x44, 0x5a, 0x3a, 0x67, 0xb8, 0xcc, - 0x74, 0x5b, 0x4b, 0x6f, 0x70, 0x62, 0xc3, 0xf2, 0x7b, 0x6b, 0x14, - 0xf1, 0x06, 0x57, 0xa3, 0x68, 0x32, 0x44, 0xc3, 0x85, 0x77, 0x86, - 0xe7, 0xda, 0x15, 0xbf, 0xf8, 0x9e, 0x63 -}; - -static const uint8_t ciphertext_aes_kw[] = { - /* tag (16 bytes) */ - 0xdc, 0xe6, 0x95, 0xac, 0x0f, 0x61, 0x87, 0x17, 0x51, 0x48, 0xb4, 0xa1, - 0x8e, 0x09, 0x89, 0xb4, - /* ciphertext */ - 0x8b, 0xfb, 0xd9, 0xe4, 0xcf, 0xde, 0xf8, 0xcf, 0xe5, 0x69, 0x9d, 0x6d, - 0x92, 0x8a, 0x04, 0xf8, 0x26, 0x22, 0xd5, 0xd8, 0xe8, 0x77, 0x18, 0x5a, - 0x01, 0x13, 0xba, 0xd5, 0x23, 0x72, 0xae, 0x80, 0x44, 0xed, 0xea, 0xdf, - 0x74, 0x79, 0x8a, 0x83, 0x52, 0x72, 0x2f, 0x43, 0x06, 0xe9, 0xd4, 0xbb, - 0x54, 0x8a, 0x0d, 0xea, 0x7f, 0xe6, 0x48, 0xf0, 0xfd, 0x0e, 0xbb, 0xaa, - 0xa3, -}; - -static const uint8_t iv_aes_kw[] = { - 0x61, 0xb4, 0x70, 0x53, 0xa5, 0xe2, 0x05, 0x68, 0xfe, 0x77, 0x12, 0x89, -}; - -/** - * Encryption without wrapping CEK achieved by running: - * - * echo "This is a sample plaintext for testing the decryption filter" > plaintext.txt - * nrfkms encrypt -k TEST_AES_KEY -c test -f plaintext.txt --aad "sample aad" --format native - * - * Ciphertext and NONCE (IV) taken from the encrypted_data_using_TEST_AES_KEY-test.bin file, - * which is in format |nonce (12 bytes)|tag (16 bytes)|ciphertext| - */ - -static const uint8_t ciphertext_direct[] = { - /* tag (16 bytes) */ - 0x4d, 0x21, 0x30, 0xb7, 0xce, 0x8a, 0xd6, 0x00, 0xe4, 0x04, 0xbb, 0x32, - 0x72, 0x7a, 0xbb, 0x7c, - /* ciphertext */ - 0xf0, 0x72, 0xdb, 0x63, 0x03, 0xdd, 0x24, 0x69, - 0xd4, 0xbf, 0xd7, 0xa0, 0xec, 0xfa, 0x66, 0x58, 0x95, 0x2b, 0xc1, 0xc2, - 0x9d, 0x82, 0x02, 0x1a, 0xd7, 0x5b, 0xc0, 0x01, 0xce, 0x0b, 0x79, 0x53, - 0xe7, 0xdb, 0x0d, 0x35, 0xab, 0xef, 0x81, 0xc8, 0x68, 0xc5, 0xa7, 0x22, - 0x90, 0xea, 0xd0, 0x7f, 0x36, 0xed, 0x14, 0xbe, 0x30, 0xf2, 0x81, 0x56, - 0x7e, 0x2e, 0x5f, 0xd8, 0x7c, -}; - - -static const uint8_t iv_direct[] = { - 0x60, 0x90, 0x6d, 0xb2, 0xfe, 0xc3, 0xc8, 0x5a, 0xf0, 0x28, 0xb1, 0xb6, -}; - -static const suit_manifest_class_id_t sample_class_id = { - {0x5b, 0x46, 0x9f, 0xd1, 0x90, 0xee, 0x53, 0x9c, 0xa3, 0x18, 0x68, 0x1b, 0x03, 0x69, 0x5e, - 0x36}}; - static uint8_t output_buffer[128] = {0}; -static void init_encryption_key(const uint8_t *data, size_t size, psa_key_id_t *key_id, - psa_key_id_t alg, uint8_t *cbor_key_id) -{ - psa_status_t status; - - /* Configure the key attributes */ - psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; - - psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); - psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); - psa_set_key_algorithm(&key_attributes, alg); - psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES); - psa_set_key_bits(&key_attributes, 256); - - status = psa_import_key(&key_attributes, data, size, key_id); - - zassert_equal(status, PSA_SUCCESS, "Failed to import key"); - - /* Encode KEK key ID as CBOR unsigned int */ - cbor_key_id[1] = ((*key_id >> 24) & 0xFF); - cbor_key_id[2] = ((*key_id >> 16) & 0xFF); - cbor_key_id[3] = ((*key_id >> 8) & 0xFF); - cbor_key_id[4] = ((*key_id >> 0) & 0xFF); -} - static void *test_suite_setup(void) { static struct suit_decrypt_filter_tests_fixture fixture = {0}; @@ -159,8 +43,11 @@ static void *test_suite_setup(void) zassert_equal(status, PSA_SUCCESS, "Failed to init psa crypto"); /* Init the KEK key */ - init_encryption_key(test_key_data, sizeof(test_key_data), &fixture.key_id, - PSA_ALG_ECB_NO_PADDING, kek_key_id_cbor); + status = decrypt_test_init_encryption_key(decrypt_test_key_data, + sizeof(decrypt_test_key_data), &fixture.key_id, + PSA_ALG_ECB_NO_PADDING, kek_key_id_cbor); + zassert_equal(status, PSA_SUCCESS, "Failed to import key"); + kek_key_id = fixture.key_id; return &fixture; @@ -192,8 +79,8 @@ ZTEST_F(suit_decrypt_filter_tests, test_aes_unwrap_smoke) mbedtls_svc_key_id_t unwrapped_cek_key_id; psa_status_t status = - suit_aes_key_unwrap_manual(fixture->key_id, wrapped_cek, 256, PSA_KEY_TYPE_AES, - PSA_ALG_GCM, &unwrapped_cek_key_id); + suit_aes_key_unwrap_manual(fixture->key_id, decrypt_test_wrapped_cek, + 256, PSA_KEY_TYPE_AES, PSA_ALG_GCM, &unwrapped_cek_key_id); zassert_equal(status, PSA_SUCCESS, "Failed to unwrap CEK"); } @@ -205,18 +92,18 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_aes_kw) struct suit_encryption_info enc_info = { .enc_alg_id = suit_cose_aes256_gcm, .IV = { - .value = iv_aes_kw, - .len = sizeof(iv_aes_kw), + .value = decrypt_test_iv_aes_kw, + .len = sizeof(decrypt_test_iv_aes_kw), }, .aad = { - .value = aad, - .len = strlen(aad), + .value = decrypt_test_aad, + .len = strlen(decrypt_test_aad), }, .kw_alg_id = suit_cose_aes256_kw, .kw_key.aes = {.key_id = {.value = kek_key_id_cbor, .len = sizeof(kek_key_id_cbor)}, .ciphertext = { - .value = wrapped_cek, - .len = sizeof(wrapped_cek), + .value = decrypt_test_wrapped_cek, + .len = sizeof(decrypt_test_wrapped_cek), }}, }; suit_mci_fw_encryption_key_id_validate_fake.return_val = SUIT_PLAT_SUCCESS; @@ -225,17 +112,20 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_aes_kw) zassert_equal(err, SUIT_PLAT_SUCCESS, "Unable to create RAM sink"); - err = suit_decrypt_filter_get(&dec_sink, &enc_info, &sample_class_id, &ram_sink); + err = suit_decrypt_filter_get(&dec_sink, &enc_info, + &decrypt_test_sample_class_id, &ram_sink); zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to create decrypt filter"); zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.call_count, 1, "Invalid number of calls to suit_mci_fw_encryption_key_id_validate"); - zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, &sample_class_id, + zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, + &decrypt_test_sample_class_id, "Invalid class ID passed to suit_mci_fw_encryption_key_id_validate"); zassert_equal(suit_mci_fw_encryption_key_id_validate_fake.arg1_val, kek_key_id, "Invalid key ID passed to suit_mci_fw_encryption_key_id_validate"); - err = suit_memptr_streamer_stream(ciphertext_aes_kw, sizeof(ciphertext_aes_kw), &dec_sink); + err = suit_memptr_streamer_stream(decrypt_test_ciphertext_aes_kw, + sizeof(decrypt_test_ciphertext_aes_kw), &dec_sink); zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to decrypt ciphertext"); @@ -247,7 +137,8 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_aes_kw) zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to release decrypt filter"); - zassert_equal(memcmp(output_buffer, plaintext, strlen(plaintext)), 0, + zassert_equal(memcmp(output_buffer, decrypt_test_plaintext, + strlen(decrypt_test_plaintext)), 0, "Decrypted plaintext does not match"); } @@ -261,23 +152,15 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_direct) psa_key_id_t cek_key_id; - init_encryption_key(test_key_data, sizeof(test_key_data), &cek_key_id, - PSA_ALG_GCM, cek_key_id_cbor); + psa_status_t const 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); - struct suit_encryption_info enc_info = { - .enc_alg_id = suit_cose_aes256_gcm, - .IV = { - .value = iv_direct, - .len = sizeof(iv_direct), - }, - .aad = { - .value = aad, - .len = strlen(aad), - }, - .kw_alg_id = suit_cose_direct, - .kw_key.aes = {.key_id = {.value = cek_key_id_cbor, - .len = sizeof(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); suit_mci_fw_encryption_key_id_validate_fake.return_val = SUIT_PLAT_SUCCESS; @@ -285,19 +168,22 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_direct) zassert_equal(err, SUIT_PLAT_SUCCESS, "Unable to create RAM sink"); - err = suit_decrypt_filter_get(&dec_sink, &enc_info, &sample_class_id, &ram_sink); + err = suit_decrypt_filter_get(&dec_sink, &enc_info, + &decrypt_test_sample_class_id, &ram_sink); zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to create decrypt filter"); zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.call_count, 1, "Invalid number of calls to suit_mci_fw_encryption_key_id_validate"); - zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, &sample_class_id, + zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, + &decrypt_test_sample_class_id, "Invalid class ID passed to suit_mci_fw_encryption_key_id_validate"); zassert_equal(suit_mci_fw_encryption_key_id_validate_fake.arg1_val, cek_key_id, "Invalid key ID passed to suit_mci_fw_encryption_key_id_validate"); - err = suit_memptr_streamer_stream(ciphertext_direct, sizeof(ciphertext_direct), &dec_sink); + err = suit_memptr_streamer_stream(decrypt_test_ciphertext_direct, + sizeof(decrypt_test_ciphertext_direct), &dec_sink); zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to decrypt ciphertext"); @@ -309,7 +195,8 @@ ZTEST_F(suit_decrypt_filter_tests, test_filter_smoke_direct) zassert_equal(err, SUIT_PLAT_SUCCESS, "Failed to release decrypt filter"); - zassert_equal(memcmp(output_buffer, plaintext, strlen(plaintext)), 0, + zassert_equal(memcmp(output_buffer, decrypt_test_plaintext, + strlen(decrypt_test_plaintext)), 0, "Decrypted plaintext does not match"); psa_destroy_key(cek_key_id); @@ -325,23 +212,15 @@ ZTEST_F(suit_decrypt_filter_tests, test_key_id_validation_fail) psa_key_id_t cek_key_id; - init_encryption_key(test_key_data, sizeof(test_key_data), &cek_key_id, - PSA_ALG_GCM, cek_key_id_cbor); + psa_status_t const 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); - struct suit_encryption_info enc_info = { - .enc_alg_id = suit_cose_aes256_gcm, - .IV = { - .value = iv_direct, - .len = sizeof(iv_direct), - }, - .aad = { - .value = aad, - .len = strlen(aad), - }, - .kw_alg_id = suit_cose_direct, - .kw_key.aes = {.key_id = {.value = cek_key_id_cbor, - .len = sizeof(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); suit_mci_fw_encryption_key_id_validate_fake.return_val = MCI_ERR_WRONGKEYID; @@ -349,13 +228,15 @@ ZTEST_F(suit_decrypt_filter_tests, test_key_id_validation_fail) zassert_equal(err, SUIT_PLAT_SUCCESS, "Unable to create RAM sink"); - err = suit_decrypt_filter_get(&dec_sink, &enc_info, &sample_class_id, &ram_sink); + err = suit_decrypt_filter_get(&dec_sink, &enc_info, + &decrypt_test_sample_class_id, &ram_sink); zassert_equal(err, SUIT_PLAT_ERR_AUTHENTICATION, "Incorrect error code when getting decrypt filter"); zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.call_count, 1, "Invalid number of calls to suit_mci_fw_encryption_key_id_validate"); - zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, &sample_class_id, + zassert_equal_ptr(suit_mci_fw_encryption_key_id_validate_fake.arg0_val, + &decrypt_test_sample_class_id, "Invalid class ID passed to suit_mci_fw_encryption_key_id_validate"); zassert_equal(suit_mci_fw_encryption_key_id_validate_fake.arg1_val, cek_key_id, "Invalid key ID passed to suit_mci_fw_encryption_key_id_validate"); diff --git a/tests/subsys/suit/fetch/CMakeLists.txt b/tests/subsys/suit/fetch/CMakeLists.txt index b7545f8f23b0..8e972818576a 100644 --- a/tests/subsys/suit/fetch/CMakeLists.txt +++ b/tests/subsys/suit/fetch/CMakeLists.txt @@ -11,5 +11,8 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(integration_test_fetch) include(../cmake/test_template.cmake) + zephyr_library_link_libraries(suit_memptr_storage_interface) zephyr_library_link_libraries(suit_platform_interface) +zephyr_library_link_libraries(suit_stream_filters_interface) +zephyr_library_link_libraries(suit_decrypt_test_utils) diff --git a/tests/subsys/suit/fetch/prj.conf b/tests/subsys/suit/fetch/prj.conf index 7d88f215895c..3424e6bebbab 100644 --- a/tests/subsys/suit/fetch/prj.conf +++ b/tests/subsys/suit/fetch/prj.conf @@ -30,3 +30,8 @@ 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 diff --git a/tests/subsys/suit/fetch/src/main.c b/tests/subsys/suit/fetch/src/main.c index 266807b60261..2e17419ef6ef 100644 --- a/tests/subsys/suit/fetch/src/main.c +++ b/tests/subsys/suit/fetch/src/main.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #define TEST_DATA_SIZE 64 #define WRITE_ADDR 0x1A00080000 @@ -57,9 +60,21 @@ static const uint8_t cache2[] = { 0x90, 0x70, 0x18, 0x92, 0x36, 0x51, 0x92, 0x83, 0x09, 0x86, 0x70, 0x19, 0x23}; static const size_t cache2_len = sizeof(cache2); +/* 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 = (const uint8_t *)0x1234, - .len = 123, + .value = valid_manifest_component, + .len = sizeof(valid_manifest_component), }; static void setup_cache_with_sample_entries(void) @@ -340,3 +355,207 @@ 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); +} diff --git a/tests/subsys/suit/write/CMakeLists.txt b/tests/subsys/suit/write/CMakeLists.txt index 97f6de2e989e..87d12b7b5e1f 100644 --- a/tests/subsys/suit/write/CMakeLists.txt +++ b/tests/subsys/suit/write/CMakeLists.txt @@ -18,3 +18,4 @@ zephyr_library_link_libraries(suit_sink_selector_interface) zephyr_library_link_libraries(suit_memory_layout_interface) zephyr_library_link_libraries(suit_storage_interface) zephyr_library_link_libraries(suit_manifest_variables) +zephyr_library_link_libraries(suit_decrypt_test_utils) diff --git a/tests/subsys/suit/write/prj.conf b/tests/subsys/suit/write/prj.conf index 79a0199ac1f9..4d7a3d1eb657 100644 --- a/tests/subsys/suit/write/prj.conf +++ b/tests/subsys/suit/write/prj.conf @@ -36,3 +36,5 @@ CONFIG_FLASH_MAP=y CONFIG_SUIT_IPUC=y CONFIG_MOCK_SDFW_ARBITER=y + +CONFIG_SUIT_STREAM_FILTER_DECRYPT=y diff --git a/tests/subsys/suit/write/src/main.c b/tests/subsys/suit/write/src/main.c index 984fd83e64ee..3821b8b10b4b 100644 --- a/tests/subsys/suit/write/src/main.c +++ b/tests/subsys/suit/write/src/main.c @@ -18,6 +18,7 @@ #include #include #include +#include #define DFU_PARTITION_OFFSET FIXED_PARTITION_OFFSET(dfu_partition) #define FLASH_WRITE_ADDR (suit_plat_mem_nvm_ptr_get(DFU_PARTITION_OFFSET)) @@ -111,6 +112,56 @@ ZTEST(write_tests, test_write_to_flash_sink_OK) "Data in destination is invalid"); } +ZTEST(write_tests, test_write_to_flash_sink_encrypted_OK) +{ + struct zcbor_string source = { + .value = decrypt_test_ciphertext_direct, + .len = sizeof(decrypt_test_ciphertext_direct) + }; + + /* Create handle that will be used as destination */ + suit_component_t dst_handle; + /* [h'MEM', h'02', h'1A000F0000', h'191000'] */ + uint8_t valid_dst_value[] = {0x84, 0x44, 0x63, 'M', 'E', 'M', 0x41, 0x02, 0x45, + 0x1A, 0x00, 0x0F, 0x00, 0x00, 0x43, 0x19, 0x10, 0x00}; + + struct zcbor_string valid_dst_component_id = { + .value = valid_dst_value, + .len = sizeof(valid_dst_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_dst_component_id, false, &dst_handle); + + zassert_equal(ret, SUIT_SUCCESS, "create_component_handle failed - error %i", ret); + + ret = suit_plat_write(dst_handle, &source, &valid_manifest_component_id, &enc_info); + zassert_equal(ret, SUIT_SUCCESS, "suit_plat_write failed - error %i", ret); + + ret = suit_plat_release_component_handle(dst_handle); + zassert_equal(ret, SUIT_SUCCESS, "dst_handle release failed - error %i", ret); + zassert_mem_equal(FLASH_WRITE_ADDR, decrypt_test_plaintext, strlen(decrypt_test_plaintext), + "Data in destination is invalid"); + + psa_destroy_key(cek_key_id); +} + ZTEST(write_tests, test_write_to_ram_sink_OK) { struct zcbor_string source = {.value = test_data, .len = sizeof(test_data)};