diff --git a/tests/subsys/suit/common/CMakeLists.txt b/tests/subsys/suit/common/CMakeLists.txt index 2ed45207c82c..800247a93f2c 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) @@ -20,6 +21,7 @@ endif() if (CONFIG_SUIT_STREAM_FILTER_DECRYPT) target_link_libraries(suit_stream_filters_interface INTERFACE mbedTLS) +target_link_libraries(suit_decrypt_test_utils INTERFACE mbedTLS) endif() if (CONFIG_SUIT_STORAGE_LAYOUT_NRF54H20) 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..8a1b07065048 --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/CMakeLists.txt @@ -0,0 +1,11 @@ +# 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) +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..dfcbb7d88399 --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.c @@ -0,0 +1,132 @@ +/* + * 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[0] = 0x1A; + 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..bb7a20ddee09 --- /dev/null +++ b/tests/subsys/suit/common/decrypt_utils/decrypt_test_utils.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#ifndef DECRYPT_TEST_UTILS_H_ +#define DECRYPT_TEST_UTILS_H_ + +#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. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* 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; + +/** + * @brief Initialize encryption key with given binary data. + * The key is initialized as PSA_KEY_TYPE_AES. + * + * @param[in] data binary key data. + * @param[in] size size of @a data. + * @param[out] key_id key ID of imported key. + * @param[in] alg encryption algorithm. + * @param[out] cbor_key_id key ID of imported key in cbor format. + * + * @retval PSA_SUCCESS successfuly imported given key. + * @retval PSA_ERROR_* returned error from dependent PSA calls. + */ +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); + +#ifdef __cplusplus +} +#endif + +#endif /* DECRYPT_TEST_UTILS_H_ */ diff --git a/tests/subsys/suit/copy/CMakeLists.txt b/tests/subsys/suit/copy/CMakeLists.txt index 3959466e84f5..dcc256d5f107 100644 --- a/tests/subsys/suit/copy/CMakeLists.txt +++ b/tests/subsys/suit/copy/CMakeLists.txt @@ -18,3 +18,4 @@ 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_ipuc) +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 45f6e12f289e..d6dc71a7d4cf 100644 --- a/tests/subsys/suit/copy/prj.conf +++ b/tests/subsys/suit/copy/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/copy/src/main.c b/tests/subsys/suit/copy/src/main.c index a0a528575d2c..39590a23b203 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 @@ -654,3 +655,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..99af0cd8cc45 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, + zassert_equal(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, + zassert_equal(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, + zassert_equal(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 97ca8c37a211..a89f4f225a89 100644 --- a/tests/subsys/suit/fetch/CMakeLists.txt +++ b/tests/subsys/suit/fetch/CMakeLists.txt @@ -14,3 +14,5 @@ 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_ipuc) +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 6e77fe14039f..547c080ae02a 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) @@ -341,3 +356,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 5f320ea13772..111e74aac1df 100644 --- a/tests/subsys/suit/write/CMakeLists.txt +++ b/tests/subsys/suit/write/CMakeLists.txt @@ -19,3 +19,4 @@ 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_ipuc) +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 eeda24bccae7..083120b8e7c4 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)) @@ -112,6 +113,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)};