From 973bbe0ff0474959cf37f30a9c8743674221515e Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 9 Jan 2025 16:39:24 +0100 Subject: [PATCH 1/2] suit: Split fetch implementation Split suit_plat_fetch implementation into app-specific and sdfw-specific parts. Ref: NCSDK-30809 Signed-off-by: Tomasz Chyrowicz --- .../app/src/suit_plat_fetch_app_specific.c | 219 +++++--- .../include/suit_plat_fetch_domain_specific.h | 30 +- .../sdfw/src/suit_plat_fetch_sdfw_specific.c | 491 +++++++++++++---- subsys/suit/platform/src/suit_plat_fetch.c | 507 ++++++++---------- 4 files changed, 785 insertions(+), 462 deletions(-) diff --git a/subsys/suit/platform/app/src/suit_plat_fetch_app_specific.c b/subsys/suit/platform/app/src/suit_plat_fetch_app_specific.c index a948e8dd2fc0..f26f8e9a7ff9 100644 --- a/subsys/suit/platform/app/src/suit_plat_fetch_app_specific.c +++ b/subsys/suit/platform/app/src/suit_plat_fetch_app_specific.c @@ -4,109 +4,196 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#include #include -#include -#include -#ifdef CONFIG_SUIT_STREAM +#include +#include +#include +#include +#include +#ifdef CONFIG_SUIT_STREAM_SINK_CACHE #include -#include -#include +#endif /* CONFIG_SUIT_STREAM_SINK_CACHE */ #ifdef CONFIG_SUIT_STREAM_FETCH_SOURCE_MGR #include "suit_fetch_source_streamer.h" #endif /* CONFIG_SUIT_STREAM_FETCH_SOURCE_MGR */ -#ifdef CONFIG_SUIT_STREAM_SOURCE_CACHE -#include -#endif /* CONFIG_SUIT_STREAM_SOURCE_CACHE */ LOG_MODULE_REGISTER(suit_plat_fetch_app, CONFIG_SUIT_LOG_LEVEL); -bool suit_plat_fetch_domain_specific_is_type_supported(suit_component_type_t component_type) +#ifdef CONFIG_SUIT_STREAM_SINK_CACHE +static int suit_plat_fetch_cache(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info, bool dry_run) { - if ((component_type == SUIT_COMPONENT_TYPE_CAND_IMG) || - (component_type == SUIT_COMPONENT_TYPE_CAND_MFST) || - (component_type == SUIT_COMPONENT_TYPE_CACHE_POOL)) { - return true; +#ifndef CONFIG_SUIT_STREAM_FETCH_SOURCE_MGR + return SUIT_ERR_UNSUPPORTED_COMMAND; +#else + suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; + struct stream_sink dst_sink = {0}; + struct zcbor_string *component_id = NULL; + int ret = SUIT_SUCCESS; + uint32_t number; + + /* + * Validate streaming operation. + */ + ret = suit_plat_component_id_get(dst_handle, &component_id); + if (ret != SUIT_SUCCESS) { + LOG_ERR("Failed to parse component ID from handle: %d", ret); + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; } - return false; + if (suit_plat_decode_component_number(component_id, &number) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Missing component id number in cache pool component"); + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + } + + if (enc_info != NULL) { + LOG_ERR("Decryption while streaming to cache pool is not supported"); + (void)manifest_component_id; + return SUIT_ERR_UNSUPPORTED_PARAMETER; + } + + /* + * Construct the stream. + */ + + plat_ret = suit_dfu_cache_sink_get(&dst_sink, number, uri->value, uri->len, !dry_run); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Unable to create cache sink: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + + if (!dry_run) { + /* + * Stream the data. + */ + + /* Erase the destination memory area. */ + if ((ret == SUIT_SUCCESS) && (dst_sink.erase != NULL)) { + plat_ret = dst_sink.erase(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink erase failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + } + + /* Start streaming the data. */ + if (ret == SUIT_SUCCESS) { + plat_ret = suit_fetch_source_stream(uri->value, uri->len, &dst_sink); + if (plat_ret == SUIT_PLAT_SUCCESS) { + suit_dfu_cache_sink_commit(dst_sink.ctx); + } else { + LOG_ERR("Streaming to cache failed: %d", plat_ret); + } + + /* Failures of fetch_source streamer are treated as "unavailable payload" + * failures. These are cases where suit-condition-image-match will detect + * the failure, however suit-plat-fetch should return success to allow + * soft failures. + */ + ret = SUIT_SUCCESS; + } + + if ((ret == SUIT_SUCCESS) && (dst_sink.flush != NULL)) { + plat_ret = dst_sink.flush(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink flush failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + } + } + + /* + * Destroy the stream. + */ + + plat_ret = release_sink(&dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink release failed: %d", plat_ret); + } + + if (ret == SUIT_SUCCESS) { + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + + return ret; +#endif /* CONFIG_SUIT_STREAM_FETCH_SOURCE_MGR */ } +#endif /* CONFIG_SUIT_STREAM_SINK_CACHE */ -bool suit_plat_fetch_integrated_domain_specific_is_type_supported( - suit_component_type_t component_type) +bool suit_plat_fetch_domain_specific_is_type_supported(suit_component_type_t dst_component_type) { - if ((component_type == SUIT_COMPONENT_TYPE_CAND_IMG) || - (component_type == SUIT_COMPONENT_TYPE_CAND_MFST)) { +#ifdef CONFIG_SUIT_STREAM_SINK_CACHE + if (dst_component_type == SUIT_COMPONENT_TYPE_CACHE_POOL) { return true; } +#endif /* CONFIG_SUIT_STREAM_SINK_CACHE */ return false; } +int suit_plat_check_fetch_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ + switch (dst_component_type) { +#ifdef CONFIG_SUIT_STREAM_SINK_CACHE + case SUIT_COMPONENT_TYPE_CACHE_POOL: + return suit_plat_fetch_cache(dst_handle, uri, manifest_component_id, enc_info, + true); +#endif /* CONFIG_SUIT_STREAM_SINK_CACHE */ + default: + break; + } + + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} + int suit_plat_fetch_domain_specific(suit_component_t dst_handle, suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, struct zcbor_string *uri) + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) { - int ret = SUIT_SUCCESS; - bool hard_failure = false; - - /* Select streamer */ switch (dst_component_type) { -#ifdef CONFIG_SUIT_STREAM_FETCH_SOURCE_MGR +#ifdef CONFIG_SUIT_STREAM_SINK_CACHE case SUIT_COMPONENT_TYPE_CACHE_POOL: - case SUIT_COMPONENT_TYPE_MEM: { - ret = suit_fetch_source_stream(uri->value, uri->len, dst_sink); - ret = suit_plat_err_to_processor_err_convert(ret); - } break; -#endif /* SUIT_STREAM_FETCH_SOURCE_MGR */ -#if defined(CONFIG_SUIT_CACHE_RW) || defined(SUIT_CACHE) - case SUIT_COMPONENT_TYPE_CAND_MFST: - case SUIT_COMPONENT_TYPE_CAND_IMG: { - ret = suit_dfu_cache_streamer_stream(uri->value, uri->len, dst_sink); - ret = suit_plat_err_to_processor_err_convert(ret); - } break; -#endif + return suit_plat_fetch_cache(dst_handle, uri, manifest_component_id, enc_info, + false); +#endif /* CONFIG_SUIT_STREAM_SINK_CACHE */ default: - ret = SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - hard_failure = true; break; } - if (ret == SUIT_SUCCESS && dst_component_type == SUIT_COMPONENT_TYPE_CACHE_POOL) { - suit_dfu_cache_sink_commit(dst_sink->ctx); - } + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} - if (!hard_failure) { - /* Failures without hard_failure flag set are treated as "unavailable payload" - * failures. These are cases where suit-condition-image-match will detect - * the failure, however suit-plat-fetch should return success to allow - * soft failures. - */ - ret = SUIT_SUCCESS; - } +bool suit_plat_fetch_integrated_domain_specific_is_type_supported( + suit_component_type_t component_type) +{ + return false; +} - return ret; +int suit_plat_check_fetch_integrated_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ + return SUIT_ERR_UNSUPPORTED_COMMAND; } int suit_plat_fetch_integrated_domain_specific(suit_component_t dst_handle, suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, - struct zcbor_string *payload) + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) { - suit_plat_err_t ret = SUIT_PLAT_SUCCESS; - - (void)dst_handle; - (void)dst_component_type; - - if (payload == NULL) { - return SUIT_ERR_UNAVAILABLE_PAYLOAD; - } - - ret = suit_generic_address_streamer_stream(payload->value, payload->len, dst_sink); - - return suit_plat_err_to_processor_err_convert(ret); + return SUIT_ERR_UNSUPPORTED_COMMAND; } - -#endif /* CONFIG_SUIT_STREAM */ diff --git a/subsys/suit/platform/include/suit_plat_fetch_domain_specific.h b/subsys/suit/platform/include/suit_plat_fetch_domain_specific.h index 85f5c2f3dea7..67cd0fadf660 100644 --- a/subsys/suit/platform/include/suit_plat_fetch_domain_specific.h +++ b/subsys/suit/platform/include/suit_plat_fetch_domain_specific.h @@ -10,8 +10,6 @@ #include #include #include -#ifdef CONFIG_SUIT_STREAM -#include #ifdef __cplusplus extern "C" { @@ -28,24 +26,44 @@ bool suit_plat_fetch_domain_specific_is_type_supported(suit_component_type_t com bool suit_plat_fetch_integrated_domain_specific_is_type_supported( suit_component_type_t component_type); +/** + * @brief Domain specific part of the core part of the suit_plat_fetch function. + */ +int suit_plat_check_fetch_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info); + /** * @brief Domain specific part of the core part of the suit_plat_fetch function. */ int suit_plat_fetch_domain_specific(suit_component_t dst_handle, suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, struct zcbor_string *uri); + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info); + +/** + * @brief Domain specific part of the core part of the suit_plat_fetch_integrated function + */ +int suit_plat_check_fetch_integrated_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info); /** * @brief Domain specific part of the core part of the suit_plat_fetch_integrated function */ int suit_plat_fetch_integrated_domain_specific(suit_component_t dst_handle, suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, - struct zcbor_string *payload); + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info); #ifdef __cplusplus } #endif -#endif /* CONFIG_SUIT_STREAM */ #endif /* SUIT_PLAT_FETCH_DOMAIN_SPECIFIC_H__ */ diff --git a/subsys/suit/platform/sdfw/src/suit_plat_fetch_sdfw_specific.c b/subsys/suit/platform/sdfw/src/suit_plat_fetch_sdfw_specific.c index 407655cf7742..745fe6dbb14d 100644 --- a/subsys/suit/platform/sdfw/src/suit_plat_fetch_sdfw_specific.c +++ b/subsys/suit/platform/sdfw/src/suit_plat_fetch_sdfw_specific.c @@ -4,78 +4,79 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#include #include + +#include #include +#include #include #include #ifdef CONFIG_SUIT_STREAM +#include +#endif /* CONFIG_SUIT_STREAM */ + +#ifdef CONFIG_SUIT_SINK_SELECTOR +#include +#endif /* CONFIG_SUIT_SINK_SELECTOR */ + +#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT +#include +#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ -#include #ifdef CONFIG_SUIT_STREAM_SOURCE_CACHE #include #endif /* CONFIG_SUIT_STREAM_SOURCE_CACHE */ + +#ifdef CONFIG_SUIT_STREAM_SOURCE_MEMPTR +#include +#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ + #ifdef CONFIG_SUIT_STREAM_IPC_REQUESTOR #include #endif /* CONFIG_SUIT_STREAM_IPC_REQUESTOR */ -LOG_MODULE_REGISTER(suit_plat_fetch_sdfw, CONFIG_SUIT_LOG_LEVEL); +#if CONFIG_SUIT_DIGEST_CACHE +#include +#endif /* CONFIG_SUIT_DIGEST_CACHE */ -static bool is_type_supported(suit_component_type_t component_type) -{ - if ((component_type == SUIT_COMPONENT_TYPE_CAND_IMG) || - (component_type == SUIT_COMPONENT_TYPE_CAND_MFST) || - (component_type == SUIT_COMPONENT_TYPE_SOC_SPEC) || - (component_type == SUIT_COMPONENT_TYPE_MEM)) { - return true; - } +#if defined(CONFIG_SUIT_IPUC) +#include +#endif /* CONFIG_SUIT_IPUC */ - return false; -} - -static bool is_type_supported_by_ipc(suit_component_type_t component_type) -{ - if (component_type == SUIT_COMPONENT_TYPE_MEM) { - return true; - } - - return false; -} - -bool suit_plat_fetch_domain_specific_is_type_supported(suit_component_type_t component_type) -{ - if (IS_ENABLED(CONFIG_SUIT_STREAM_SOURCE_CACHE) || - (IS_ENABLED(CONFIG_SUIT_STREAM_IPC_REQUESTOR) && - is_type_supported_by_ipc(component_type))) { - return is_type_supported(component_type); - } - - return false; -} +LOG_MODULE_REGISTER(suit_plat_fetch_sdfw, CONFIG_SUIT_LOG_LEVEL); -bool suit_plat_fetch_integrated_domain_specific_is_type_supported( - suit_component_type_t component_type) -{ - return is_type_supported(component_type); -} +#ifdef CONFIG_SUIT_STREAM +/** @brief A common data streamer type for both integrated and non-integrated fetch. + * + * @details The streamer API may receive either URI or the raw payload, depending on the + * context. This type is defined only to simplify/shorten the implementation. + * It is possible to use it here because the only part of the fetch logic, + * that depends on the input source (URI/payload) is the streamer. + * + * @param[in] src Pointer to the URI/payload to stream. + * @param[in] lin Length of the URI/payload. + * @param[in] sink Output sink to write streamed data. + * + * @returns SUIT_SUCCESS on success, streamer-specific error code otherwise. + */ +typedef int (*data_streamer)(const uint8_t *src, size_t len, struct stream_sink *sink); -int suit_plat_fetch_domain_specific(suit_component_t dst_handle, - suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, struct zcbor_string *uri) +/** @brief Streamer function for non-integrated fetches into MEM components. */ +static int external_streamer(const uint8_t *uri, size_t uri_len, struct stream_sink *sink) { - /* If cache is disabled, act as thou uri was not found in cache */ - suit_plat_err_t ret = SUIT_PLAT_ERR_NOT_FOUND; + int ret = SUIT_PLAT_ERR_NOT_FOUND; #ifdef CONFIG_SUIT_STREAM_SOURCE_CACHE /* Check if requested uri exists in cache and get streamer */ - ret = suit_dfu_cache_streamer_stream(uri->value, uri->len, dst_sink); + ret = suit_dfu_cache_streamer_stream(uri, uri_len, sink); #endif /* CONFIG_SUIT_STREAM_SOURCE_CACHE */ #ifdef CONFIG_SUIT_STREAM_IPC_REQUESTOR - if ((ret == SUIT_PLAT_ERR_NOT_FOUND) && /* URI was not found in cache */ - is_type_supported_by_ipc(dst_component_type)) { /* component type is supported */ + if (ret == SUIT_PLAT_ERR_NOT_FOUND) { /* URI was not found in cache */ /* Request uri through ipc streamer */ - ret = suit_ipc_streamer_stream(uri->value, uri->len, dst_sink, + ret = suit_ipc_streamer_stream(uri, uri_len, sink, CONFIG_SUIT_STREAM_IPC_STREAMER_CHUNK_TIMEOUT, CONFIG_SUIT_STREAM_IPC_STREAMER_REQUESTING_PERIOD); if (ret != SUIT_PLAT_SUCCESS) { @@ -87,88 +88,388 @@ int suit_plat_fetch_domain_specific(suit_component_t dst_handle, if (ret == SUIT_PLAT_ERR_NOT_FOUND) { /* If we arrived here we can treat the source data as unavailable. * This is a case where suit-condition-image-match will detect - * the failure, however suit-plat-fetch should return success to allow - * soft failures. + * the failure, however suit-plat-fetch should return success to + * allow soft failures. + */ + return SUIT_SUCCESS; + } + + return ret; +} + +/** @brief Streamer function for non-integrated fetches into SoC-specific components. */ +static int external_sdfw_streamer(const uint8_t *uri, size_t uri_len, struct stream_sink *sink) +{ + int ret = SUIT_PLAT_ERR_NOT_FOUND; + +#ifdef CONFIG_SUIT_STREAM_SOURCE_CACHE + /* Check if requested uri exists in cache and get streamer */ + ret = suit_dfu_cache_streamer_stream(uri, uri_len, sink); +#endif /* CONFIG_SUIT_STREAM_SOURCE_CACHE */ + + if (ret == SUIT_PLAT_ERR_NOT_FOUND) { + /* If we arrived here we can treat the source data as unavailable. + * This is a case where suit-condition-image-match will detect + * the failure, however suit-plat-fetch should return success to + * allow soft failures. */ return SUIT_SUCCESS; } - if (ret == SUIT_PLAT_SUCCESS) { - /* Flush any remaining data before reading used storage size */ - if (dst_sink->flush != NULL) { - ret = dst_sink->flush(dst_sink->ctx); - if (ret != SUIT_PLAT_SUCCESS) { - return suit_plat_err_to_processor_err_convert(ret); + return ret; +} + +/** @brief Streamer function for integrated payload fetches. */ +#define internal_streamer suit_memptr_streamer_stream + +/** @brief Common implementation for fetching data into MEM components. */ +static int suit_plat_fetch_mem(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info, data_streamer streamer, + bool dry_run) +{ + suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; + struct stream_sink dst_sink = {0}; + int ret = SUIT_SUCCESS; + + /* + * Validate streaming operation. + */ + + /* + * Construct the stream. + */ + + /* Select sink */ + ret = suit_sink_select(dst_handle, &dst_sink); + if (ret != SUIT_SUCCESS) { + LOG_ERR("Selecting sink failed: %i", ret); + return ret; + } + + /* Append decryption filter if encryption info is provided. */ + if (enc_info != NULL) { +#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT + suit_manifest_class_id_t *class_id = NULL; + + if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != + SUIT_PLAT_SUCCESS) { + LOG_ERR("Manifest component ID is not a manifest class"); + ret = SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + } + + if (ret == SUIT_SUCCESS) { + plat_ret = + suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Selecting decryption filter failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); } } +#else + LOG_ERR("Decryption while streaming to MEM component is not supported"); + (void)manifest_component_id; + ret = SUIT_ERR_UNSUPPORTED_PARAMETER; +#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ + } - /* Update size in memptr for MEM component */ - if (dst_component_type == SUIT_COMPONENT_TYPE_MEM) { - size_t new_size = 0; + if (!dry_run) { + /* + * Stream the data. + */ - ret = dst_sink->used_storage(dst_sink->ctx, &new_size); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Getting used storage on destination sink failed"); +#if CONFIG_SUIT_IPUC + suit_ipuc_sdfw_revoke(dst_handle); +#endif /* CONFIG_SUIT_IPUC */ - return suit_plat_err_to_processor_err_convert(ret); +#if CONFIG_SUIT_DIGEST_CACHE + /* Invalidate digest cache for the destination component. */ + if (ret == SUIT_SUCCESS) { + ret = suit_plat_digest_cache_remove_by_handle(dst_handle); + if (ret != SUIT_SUCCESS) { + LOG_ERR("Invalidating digest cache failed: %i", ret); + } + } +#endif + + /* Erase the destination memory area. */ + if ((ret == SUIT_SUCCESS) && (dst_sink.erase != NULL)) { + plat_ret = dst_sink.erase(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink erase failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); } + } - ret = suit_plat_memptr_size_update(dst_handle, new_size); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Failed to update destination MEM component size: %i", ret); + /* Start streaming the data. */ + if (ret == SUIT_SUCCESS) { + ret = streamer(uri->value, uri->len, &dst_sink); + } - return suit_plat_err_to_processor_err_convert(ret); + if ((ret == SUIT_SUCCESS) && (dst_sink.flush != NULL)) { + plat_ret = dst_sink.flush(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink flush failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); } } + + /* Update size in memptr for MEM component */ + if (ret == SUIT_SUCCESS) { + size_t new_size = 0; + + plat_ret = dst_sink.used_storage(dst_sink.ctx, &new_size); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Getting used storage on destination sink failed: %d", + plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + + if (ret == SUIT_SUCCESS) { + plat_ret = suit_plat_memptr_size_update(dst_handle, new_size); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Failed to update destination MEM component size: " + "%i", + plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + } + } + } + + /* + * Destroy the stream. + */ + + plat_ret = release_sink(&dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink release failed: %d", plat_ret); } - return suit_plat_err_to_processor_err_convert(ret); + if (ret == SUIT_SUCCESS) { + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + + return ret; } -int suit_plat_fetch_integrated_domain_specific(suit_component_t dst_handle, - suit_component_type_t dst_component_type, - struct stream_sink *dst_sink, - struct zcbor_string *payload) +/** @brief Common implementation for fetching data into SoC specific components. */ +static int suit_plat_fetch_soc(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info, data_streamer streamer, + bool dry_run) { - if (payload == NULL) { - return SUIT_ERR_UNAVAILABLE_PAYLOAD; + suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; + struct stream_sink dst_sink = {0}; + int ret = SUIT_SUCCESS; + + /* + * Validate streaming operation. + */ + + /* + * Construct the stream. + */ + + /* Create destination sink. */ + ret = suit_sink_select(dst_handle, &dst_sink); + if (ret != SUIT_SUCCESS) { + LOG_ERR("Selecting sink failed: %d", ret); + return ret; } - suit_plat_err_t ret = - suit_generic_address_streamer_stream(payload->value, payload->len, dst_sink); + /* Append decryption filter if encryption info is provided. */ + if (enc_info != NULL) { +#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT + suit_manifest_class_id_t *class_id = NULL; - if (ret != SUIT_PLAT_SUCCESS) { - return suit_plat_err_to_processor_err_convert(ret); - } + if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != + SUIT_PLAT_SUCCESS) { + LOG_ERR("Manifest component ID is not a manifest class"); + ret = SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + } - /* Flush any remaining data before reading used storage size */ - if (dst_sink->flush != NULL) { - ret = dst_sink->flush(dst_sink->ctx); - if (ret != SUIT_PLAT_SUCCESS) { - return suit_plat_err_to_processor_err_convert(ret); + if (ret == SUIT_SUCCESS) { + plat_ret = + suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Selecting decryption filter failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } } +#else + LOG_ERR("Decryption while streaming to SoC specific component is not supported"); + (void)manifest_component_id; + ret = SUIT_ERR_UNSUPPORTED_PARAMETER; +#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ } - /* Update size in memptr for MEM component */ - if (dst_component_type == SUIT_COMPONENT_TYPE_MEM) { - size_t new_size = 0; - - ret = dst_sink->used_storage(dst_sink->ctx, &new_size); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Getting used storage on destination sink failed"); + if (!dry_run) { + /* + * Stream the data. + */ - return suit_plat_err_to_processor_err_convert(ret); + /* Erase the destination memory area. */ + if ((ret == SUIT_SUCCESS) && (dst_sink.erase != NULL)) { + plat_ret = dst_sink.erase(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink erase failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } } - ret = suit_plat_memptr_size_update(dst_handle, new_size); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Failed to update destination MEM component size: %i", ret); + /* Start streaming the data. */ + if (ret == SUIT_SUCCESS) { + ret = streamer(uri->value, uri->len, &dst_sink); + } - return suit_plat_err_to_processor_err_convert(ret); + if ((ret == SUIT_SUCCESS) && (dst_sink.flush != NULL)) { + plat_ret = dst_sink.flush(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink flush failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } } } - return suit_plat_err_to_processor_err_convert(ret); + /* + * Destroy the stream. + */ + + plat_ret = release_sink(&dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink release failed: %d", plat_ret); + } + + if (ret == SUIT_SUCCESS) { + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + + return ret; } +#endif /* CONFIG_SUIT_STREAM */ + +bool suit_plat_fetch_domain_specific_is_type_supported(suit_component_type_t dst_component_type) +{ + if (!IS_ENABLED(CONFIG_SUIT_STREAM_SOURCE_CACHE) && + (!IS_ENABLED(CONFIG_SUIT_STREAM_IPC_REQUESTOR) || + (dst_component_type != SUIT_COMPONENT_TYPE_MEM))) { + return false; + } +#ifdef CONFIG_SUIT_STREAM + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return true; + default: + break; + } #endif /* CONFIG_SUIT_STREAM */ + + return false; +} + +int suit_plat_check_fetch_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ +#ifdef CONFIG_SUIT_STREAM + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + return suit_plat_fetch_mem(dst_handle, uri, manifest_component_id, enc_info, + external_streamer, true); + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return suit_plat_fetch_soc(dst_handle, uri, manifest_component_id, enc_info, + external_sdfw_streamer, true); + default: + break; + } +#endif /* CONFIG_SUIT_STREAM */ + + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} + +int suit_plat_fetch_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ +#ifdef CONFIG_SUIT_STREAM + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + return suit_plat_fetch_mem(dst_handle, uri, manifest_component_id, enc_info, + external_streamer, false); + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return suit_plat_fetch_soc(dst_handle, uri, manifest_component_id, enc_info, + external_sdfw_streamer, false); + default: + break; + } +#endif /* CONFIG_SUIT_STREAM */ + + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} + +bool suit_plat_fetch_integrated_domain_specific_is_type_supported( + suit_component_type_t dst_component_type) +{ +#ifdef CONFIG_SUIT_STREAM + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return true; + default: + break; + } +#endif /* CONFIG_SUIT_STREAM */ + + return false; +} + +int suit_plat_check_fetch_integrated_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ +#ifdef CONFIG_SUIT_STREAM_SOURCE_MEMPTR + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + return suit_plat_fetch_mem(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, true); + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return suit_plat_fetch_soc(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, true); + default: + break; + } +#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ + + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} + +int suit_plat_fetch_integrated_domain_specific(suit_component_t dst_handle, + suit_component_type_t dst_component_type, + struct zcbor_string *payload, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ +#ifdef CONFIG_SUIT_STREAM_SOURCE_MEMPTR + switch (dst_component_type) { + case SUIT_COMPONENT_TYPE_MEM: + return suit_plat_fetch_mem(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, false); + case SUIT_COMPONENT_TYPE_SOC_SPEC: + return suit_plat_fetch_soc(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, false); + default: + break; + } +#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ + + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} diff --git a/subsys/suit/platform/src/suit_plat_fetch.c b/subsys/suit/platform/src/suit_plat_fetch.c index c14d93ee0a35..86ffe99a5766 100644 --- a/subsys/suit/platform/src/suit_plat_fetch.c +++ b/subsys/suit/platform/src/suit_plat_fetch.c @@ -4,119 +4,132 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ +#include #include + +#include #include +#include #include +#include #include -#if CONFIG_SUIT_DIGEST_CACHE -#include -#endif /* CONFIG_SUIT_DIGEST_CACHE */ - -#if defined(CONFIG_SUIT_IPUC) && defined(CONFIG_SUIT_PLATFORM_VARIANT_SDFW) -#include -#endif - #ifdef CONFIG_SUIT_STREAM #include -#include #endif /* CONFIG_SUIT_STREAM */ #ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR +#include #include #endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ -#ifdef CONFIG_SUIT_CACHE_RW -#include -#endif #ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT #include #endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ -#include -#include -#include -#include +#ifdef CONFIG_SUIT_STREAM_SOURCE_CACHE +#include +#endif /* CONFIG_SUIT_STREAM_SOURCE_CACHE */ + +#ifdef CONFIG_SUIT_STREAM_SOURCE_MEMPTR +#include +#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ LOG_MODULE_REGISTER(suit_plat_fetch, CONFIG_SUIT_LOG_LEVEL); -#ifdef CONFIG_SUIT_STREAM +#ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR +/** @brief A common data streamer type for both integrated and non-integrated fetch. + * + * @details The streamer API may receive either URI or the raw payload, depending on the + * context. This type is defined only to simplify/shorten the implementation. + * It is possible to use it here because the only part of the fetch logic, + * that depends on the input source (URI/payload) is the streamer. + * + * @param[in] src Pointer to the URI/payload to stream. + * @param[in] lin Length of the URI/payload. + * @param[in] sink Output sink to write streamed data. + * + * @returns SUIT_SUCCESS on success, streamer-specific error code otherwise. + */ +typedef int (*data_streamer)(const uint8_t *src, size_t len, struct stream_sink *sink); -static int verify_and_get_sink(suit_component_t dst_handle, struct stream_sink *sink, - struct zcbor_string *uri, suit_component_type_t *component_type, - bool write_enabled) +/** @brief Streamer function for non-integrated fetches. */ +static int external_streamer(const uint8_t *uri, size_t uri_len, struct stream_sink *sink) { - int ret = suit_plat_component_type_get(dst_handle, component_type); +#ifndef CONFIG_SUIT_STREAM_SOURCE_CACHE + return SUIT_ERR_UNSUPPORTED_COMMAND; +#else + suit_plat_err_t plat_ret = suit_dfu_cache_streamer_stream(uri, uri_len, sink); - if (ret != SUIT_SUCCESS) { - LOG_ERR("Failed to decode component type: %i", ret); - return ret; - } - if (!suit_plat_fetch_domain_specific_is_type_supported(*component_type)) { - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Streaming from cache failed: %d", plat_ret); } - /* Select sink */ -#ifdef CONFIG_SUIT_CACHE_RW - if (*component_type == SUIT_COMPONENT_TYPE_CACHE_POOL) { - uint32_t number; - struct zcbor_string *component_id; - - int ret = suit_plat_component_id_get(dst_handle, &component_id); - - if (ret != SUIT_SUCCESS) { - LOG_ERR("suit_plat_component_id_get failed: %i", ret); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } - - if (suit_plat_decode_component_number(component_id, &number) != SUIT_PLAT_SUCCESS) { - LOG_ERR("Missing component id number in candidate image component"); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } - - suit_plat_err_t plat_ret = - suit_dfu_cache_sink_get(sink, number, uri->value, uri->len, write_enabled); - - if (plat_ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Getting cache sink failed"); - } + /* Failures of dfu_cache streamer are treated as "unavailable payload" + * failures. These are cases where suit-condition-image-match will detect + * the failure, however suit-plat-fetch should return success to allow + * soft failures. + */ + return SUIT_SUCCESS; +#endif +} - return suit_plat_err_to_processor_err_convert(plat_ret); - } +/** @brief Streamer function for integrated payload fetches. */ +static inline int internal_streamer(const uint8_t *payload, size_t payload_len, + struct stream_sink *sink) +{ +#ifndef CONFIG_SUIT_STREAM_SOURCE_MEMPTR + return SUIT_ERR_UNSUPPORTED_COMMAND; #else - (void)write_enabled; -#endif /* CONFIG_SUIT_CACHE_RW */ - - return suit_sink_select(dst_handle, sink); + return suit_memptr_streamer_stream(payload, payload_len, sink); +#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ } -#endif /* CONFIG_SUIT_STREAM */ -int suit_plat_check_fetch(suit_component_t dst_handle, struct zcbor_string *uri, - struct zcbor_string *manifest_component_id, - struct suit_encryption_info *enc_info) +/** @brief Common implementation for fetching data into candidate components. */ +static int suit_plat_fetch_memptr(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info, data_streamer streamer, + bool dry_run) { -#ifdef CONFIG_SUIT_STREAM - suit_component_type_t dst_component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - struct stream_sink dst_sink = {0}; suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; + struct stream_sink dst_sink = {0}; + struct zcbor_string *component_id = NULL; + memptr_storage_handle_t handle; int ret = SUIT_SUCCESS; -#if !defined(CONFIG_SUIT_STREAM_FILTER_DECRYPT) - (void)manifest_component_id; -#endif + uint32_t number; /* * Validate streaming operation. */ - ret = verify_and_get_sink(dst_handle, &dst_sink, uri, &dst_component_type, false); + + ret = suit_plat_component_id_get(dst_handle, &component_id); if (ret != SUIT_SUCCESS) { - LOG_ERR("Failed to verify component and get end sink"); + LOG_ERR("Failed to parse component ID from handle: %d", ret); + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + } + + if (suit_plat_decode_component_number(component_id, &number) != SUIT_PLAT_SUCCESS) { + LOG_ERR("Missing component id number in candidate component"); + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + } + + ret = suit_plat_component_impl_data_get(dst_handle, &handle); + if (ret != SUIT_SUCCESS) { + LOG_ERR("Unable to get component data for candidate component: %d", ret); return ret; } /* - * Try to Construct the stream. + * Construct the stream. */ + plat_ret = suit_memptr_sink_get(&dst_sink, handle); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Unable to create memptr sink: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + return ret; + } + /* Append decryption filter if encryption info is provided. */ if (enc_info != NULL) { #ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT @@ -124,314 +137,218 @@ int suit_plat_check_fetch(suit_component_t dst_handle, struct zcbor_string *uri, if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != SUIT_PLAT_SUCCESS) { - LOG_ERR("Component ID is not a manifest class"); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + LOG_ERR("Manifest component ID is not a manifest class"); + ret = SUIT_ERR_UNSUPPORTED_COMPONENT_ID; } - ret = suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Selecting decryption filter failed: %i", ret); + if (ret == SUIT_SUCCESS) { + plat_ret = + suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Selecting decryption filter failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } } #else + LOG_ERR("Decryption while streaming to candidate component is not supported"); + (void)manifest_component_id; ret = SUIT_ERR_UNSUPPORTED_PARAMETER; #endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ } + if (!dry_run) { + /* + * Stream the data. + */ + + /* Erase the destination memory area. */ + if ((ret == SUIT_SUCCESS) && (dst_sink.erase != NULL)) { + plat_ret = dst_sink.erase(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink erase failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + } + + /* Start streaming the data. */ + if (ret == SUIT_SUCCESS) { + ret = streamer(uri->value, uri->len, &dst_sink); + } + + if ((ret == SUIT_SUCCESS) && (dst_sink.flush != NULL)) { + plat_ret = dst_sink.flush(dst_sink.ctx); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink flush failed: %d", plat_ret); + ret = suit_plat_err_to_processor_err_convert(plat_ret); + } + } + } + /* * Destroy the stream. */ plat_ret = release_sink(&dst_sink); + if (plat_ret != SUIT_PLAT_SUCCESS) { + LOG_ERR("Sink release failed: %d", plat_ret); + } + if (ret == SUIT_SUCCESS) { ret = suit_plat_err_to_processor_err_convert(plat_ret); } return ret; -#endif /* CONFIG_SUIT_STREAM */ - - return SUIT_ERR_UNSUPPORTED_COMMAND; } +#endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ -int suit_plat_fetch(suit_component_t dst_handle, struct zcbor_string *uri, - struct zcbor_string *manifest_component_id, - struct suit_encryption_info *enc_info) +int suit_plat_check_fetch(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) { -#ifdef CONFIG_SUIT_STREAM - struct stream_sink dst_sink = {0}; suit_component_type_t dst_component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; - int ret = SUIT_SUCCESS; -#if !defined(CONFIG_SUIT_STREAM_FILTER_DECRYPT) - (void)manifest_component_id; -#endif - /* - * Validate streaming operation. - */ + /* Decode destination component type based on component handle. */ + int ret = suit_plat_component_type_get(dst_handle, &dst_component_type); - ret = verify_and_get_sink(dst_handle, &dst_sink, uri, &dst_component_type, true); if (ret != SUIT_SUCCESS) { - LOG_ERR("Failed to verify component end get end sink"); + LOG_ERR("Failed to decode component type: %d", ret); return ret; } - /* - * Construct the stream. - */ - - /* Append decryption filter if encryption info is provided. */ - if (enc_info != NULL) { -#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT - suit_manifest_class_id_t *class_id = NULL; + if (uri == NULL) { + LOG_ERR("Empty URI"); + return SUIT_ERR_UNAVAILABLE_PAYLOAD; + } - if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != - SUIT_PLAT_SUCCESS) { - LOG_ERR("Component ID is not a manifest class"); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } + switch (dst_component_type) { +#ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR + case SUIT_COMPONENT_TYPE_CAND_IMG: + case SUIT_COMPONENT_TYPE_CAND_MFST: + return suit_plat_fetch_memptr(dst_handle, uri, manifest_component_id, enc_info, + external_streamer, true); +#endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ + default: + break; + } - ret = suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Selecting decryption filter failed: %i", ret); - } -#else - ret = SUIT_ERR_UNSUPPORTED_PARAMETER; -#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ + if (suit_plat_fetch_domain_specific_is_type_supported(dst_component_type)) { + return suit_plat_check_fetch_domain_specific(dst_handle, dst_component_type, uri, + manifest_component_id, enc_info); } - /* - * Stream the data. - */ + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; +} -#if defined(CONFIG_SUIT_IPUC) && defined(CONFIG_SUIT_PLATFORM_VARIANT_SDFW) - suit_ipuc_sdfw_revoke(dst_handle); -#endif +int suit_plat_fetch(suit_component_t dst_handle, struct zcbor_string *uri, + struct zcbor_string *manifest_component_id, + struct suit_encryption_info *enc_info) +{ + suit_component_type_t dst_component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; -#if CONFIG_SUIT_DIGEST_CACHE - /* Invalidate digest cache for the destination component. */ - ret = suit_plat_digest_cache_remove_by_handle(dst_handle); + /* Decode destination component type based on component handle. */ + int ret = suit_plat_component_type_get(dst_handle, &dst_component_type); if (ret != SUIT_SUCCESS) { + LOG_ERR("Failed to decode component type: %d", ret); return ret; } -#endif - /* Erase the destination memory area. */ - if (dst_sink.erase != NULL) { - ret = dst_sink.erase(dst_sink.ctx); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Sink mem erase failed: %i", ret); - } + if (uri == NULL) { + LOG_ERR("Empty URI"); + return SUIT_ERR_UNAVAILABLE_PAYLOAD; } - /* Start streaming the data. */ - if (ret == SUIT_SUCCESS) { - ret = suit_plat_fetch_domain_specific(dst_handle, dst_component_type, &dst_sink, - uri); + switch (dst_component_type) { +#ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR + case SUIT_COMPONENT_TYPE_CAND_IMG: + case SUIT_COMPONENT_TYPE_CAND_MFST: + return suit_plat_fetch_memptr(dst_handle, uri, manifest_component_id, enc_info, + external_streamer, false); +#endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ + default: + break; } - /* - * Destroy the stream. - */ - - plat_ret = release_sink(&dst_sink); - if (ret == SUIT_SUCCESS) { - ret = suit_plat_err_to_processor_err_convert(plat_ret); + if (suit_plat_fetch_domain_specific_is_type_supported(dst_component_type)) { + return suit_plat_fetch_domain_specific(dst_handle, dst_component_type, uri, + manifest_component_id, enc_info); } - return ret; -#else - return SUIT_ERR_UNSUPPORTED_COMMAND; -#endif /* CONFIG_SUIT_STREAM */ + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; } int suit_plat_check_fetch_integrated(suit_component_t dst_handle, struct zcbor_string *payload, struct zcbor_string *manifest_component_id, struct suit_encryption_info *enc_info) { -#ifdef CONFIG_SUIT_STREAM - struct stream_sink dst_sink; suit_component_type_t dst_component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; - int ret = SUIT_SUCCESS; -#if !defined(CONFIG_SUIT_STREAM_FILTER_DECRYPT) - (void)manifest_component_id; -#endif - - /* - * Validate streaming operation. - */ /* Decode destination component type based on component handle. */ - ret = suit_plat_component_type_get(dst_handle, &dst_component_type); + int ret = suit_plat_component_type_get(dst_handle, &dst_component_type); + if (ret != SUIT_SUCCESS) { LOG_ERR("Failed to decode component type: %i", ret); return ret; } - /* Check if destination component is supported by the fetch operation. */ - if (!suit_plat_fetch_integrated_domain_specific_is_type_supported(dst_component_type)) { - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; + if (payload == NULL) { + LOG_ERR("Empty payload"); + return SUIT_ERR_UNAVAILABLE_PAYLOAD; } -#ifndef CONFIG_SUIT_STREAM_SOURCE_MEMPTR - return SUIT_ERR_UNSUPPORTED_COMMAND; -#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ - - /* - * Try to construct the stream. - */ - - /* Create destination sink. */ - ret = suit_sink_select(dst_handle, &dst_sink); - if (ret != SUIT_SUCCESS) { - LOG_ERR("Selecting sink failed: %i", ret); - return ret; - } - - /* Append decryption filter if encryption info is provided. */ - if (enc_info != NULL) { -#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT - suit_manifest_class_id_t *class_id = NULL; - - if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != - SUIT_PLAT_SUCCESS) { - LOG_ERR("Component ID is not a manifest class"); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } - - ret = suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Selecting decryption filter failed: %i", ret); - } -#else - ret = SUIT_ERR_UNSUPPORTED_PARAMETER; -#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ + switch (dst_component_type) { +#ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR + case SUIT_COMPONENT_TYPE_CAND_IMG: + case SUIT_COMPONENT_TYPE_CAND_MFST: + return suit_plat_fetch_memptr(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, true); +#endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ + default: + break; } - /* - * Destroy the stream. - */ - - plat_ret = release_sink(&dst_sink); - if (ret == SUIT_SUCCESS) { - ret = suit_plat_err_to_processor_err_convert(plat_ret); + if (suit_plat_fetch_integrated_domain_specific_is_type_supported(dst_component_type)) { + return suit_plat_check_fetch_integrated_domain_specific( + dst_handle, dst_component_type, payload, manifest_component_id, enc_info); } - return ret; -#else - return SUIT_ERR_UNSUPPORTED_COMMAND; -#endif /* CONFIG_SUIT_STREAM */ + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; } int suit_plat_fetch_integrated(suit_component_t dst_handle, struct zcbor_string *payload, struct zcbor_string *manifest_component_id, struct suit_encryption_info *enc_info) { -#ifdef CONFIG_SUIT_STREAM - struct stream_sink dst_sink; suit_component_type_t dst_component_type = SUIT_COMPONENT_TYPE_UNSUPPORTED; - suit_plat_err_t plat_ret = SUIT_PLAT_SUCCESS; - int ret = SUIT_SUCCESS; -#if !defined(CONFIG_SUIT_STREAM_FILTER_DECRYPT) - (void)manifest_component_id; -#endif - - /* - * Validate streaming operation. - */ /* Decode destination component type based on component handle. */ - ret = suit_plat_component_type_get(dst_handle, &dst_component_type); - if (ret != SUIT_SUCCESS) { - LOG_ERR("Failed to decode component type: %i", ret); - return ret; - } - - /* Check if destination component is supported by the fetch operation. */ - if (!suit_plat_fetch_integrated_domain_specific_is_type_supported(dst_component_type)) { - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } + int ret = suit_plat_component_type_get(dst_handle, &dst_component_type); -#ifndef CONFIG_SUIT_STREAM_SOURCE_MEMPTR - return SUIT_ERR_UNSUPPORTED_COMMAND; -#endif /* CONFIG_SUIT_STREAM_SOURCE_MEMPTR */ - - /* - * Construct the stream. - */ - - /* Create destination sink. */ - ret = suit_sink_select(dst_handle, &dst_sink); if (ret != SUIT_SUCCESS) { - LOG_ERR("Selecting sink failed: %i", ret); + LOG_ERR("Failed to decode component type: %i", ret); return ret; } - /* Append decryption filter if encryption info is provided. */ - if (enc_info != NULL) { -#ifdef CONFIG_SUIT_STREAM_FILTER_DECRYPT - suit_manifest_class_id_t *class_id = NULL; - - if (suit_plat_decode_manifest_class_id(manifest_component_id, &class_id) != - SUIT_PLAT_SUCCESS) { - LOG_ERR("Component ID is not a manifest class"); - return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; - } - - ret = suit_decrypt_filter_get(&dst_sink, enc_info, class_id, &dst_sink); - if (ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Selecting decryption filter failed: %i", ret); - } -#else - ret = SUIT_ERR_UNSUPPORTED_PARAMETER; -#endif /* CONFIG_SUIT_STREAM_FILTER_DECRYPT */ - } - - /* - * Stream the data. - */ - -#if defined(CONFIG_SUIT_IPUC) && defined(CONFIG_SUIT_PLATFORM_VARIANT_SDFW) - suit_ipuc_sdfw_revoke(dst_handle); -#endif - -#if CONFIG_SUIT_DIGEST_CACHE - /* Invalidate digest cache for the destination component. */ - if (ret == SUIT_SUCCESS) { - ret = suit_plat_digest_cache_remove_by_handle(dst_handle); - if (ret != SUIT_SUCCESS) { - LOG_ERR("Invalidating digest cache failed: %i", ret); - } + if (payload == NULL) { + LOG_ERR("Empty payload"); + return SUIT_ERR_UNAVAILABLE_PAYLOAD; } -#endif - /* Erase the destination memory area. */ - if ((ret == SUIT_SUCCESS) && (dst_sink.erase != NULL)) { - plat_ret = dst_sink.erase(dst_sink.ctx); - if (plat_ret != SUIT_PLAT_SUCCESS) { - LOG_ERR("Sink mem erase failed, err code: %d", plat_ret); - ret = suit_plat_err_to_processor_err_convert(plat_ret); - } + switch (dst_component_type) { +#ifdef CONFIG_SUIT_STREAM_SINK_MEMPTR + case SUIT_COMPONENT_TYPE_CAND_IMG: + case SUIT_COMPONENT_TYPE_CAND_MFST: + return suit_plat_fetch_memptr(dst_handle, payload, manifest_component_id, enc_info, + internal_streamer, false); +#endif /* CONFIG_SUIT_STREAM_SINK_MEMPTR */ + default: + break; } - /* Start streaming the data. */ - if (ret == SUIT_SUCCESS) { - ret = suit_plat_fetch_integrated_domain_specific(dst_handle, dst_component_type, - &dst_sink, payload); + if (suit_plat_fetch_integrated_domain_specific_is_type_supported(dst_component_type)) { + return suit_plat_fetch_integrated_domain_specific( + dst_handle, dst_component_type, payload, manifest_component_id, enc_info); } - /* - * Destroy the stream. - */ - - plat_ret = release_sink(&dst_sink); - if (ret == SUIT_SUCCESS) { - ret = suit_plat_err_to_processor_err_convert(plat_ret); - } - - return ret; -#else /* CONFIG_SUIT_STREAM */ - return SUIT_ERR_UNSUPPORTED_COMMAND; -#endif /* CONFIG_SUIT_STREAM */ + return SUIT_ERR_UNSUPPORTED_COMPONENT_ID; } From a643479eefd03801b1e6c20a5185d7af4bc6ffc7 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Fri, 10 Jan 2025 15:31:07 +0100 Subject: [PATCH 2/2] tests: Align suit_plat_fetch APP tests Remove tests that verify common implementation. Ref: NCSDK-30809 Signed-off-by: Tomasz Chyrowicz --- .../app_specific/suit_plat_fetch_app/prj.conf | 1 + .../suit_plat_fetch_app/src/main.c | 228 +++++------------- tests/subsys/suit/unit/mocks/CMakeLists.txt | 2 +- 3 files changed, 66 insertions(+), 165 deletions(-) diff --git a/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/prj.conf b/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/prj.conf index ef7b5abe82d7..338eac6f2f43 100644 --- a/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/prj.conf +++ b/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/prj.conf @@ -10,3 +10,4 @@ CONFIG_MOCK_DFU_CACHE_STREAMER=y CONFIG_MOCK_DFU_CACHE_SINK=y CONFIG_MOCK_FETCH_SOURCE_STREAMER=y CONFIG_MOCK_GENERIC_ADDRESS_STREAMER=y +CONFIG_MOCK_SUIT_UTILS=y diff --git a/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/src/main.c b/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/src/main.c index 0281ba768adf..9000d2e5e021 100644 --- a/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/src/main.c +++ b/tests/subsys/suit/unit/app_specific/suit_plat_fetch_app/src/main.c @@ -11,6 +11,39 @@ #define TEST_COMPONENT_HANDLE ((suit_component_t)0x123) +/* 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 */ + /* RFC4122 uuid5(nordic_vid, 'test_sample_root') */ + 0x97, 0x05, 0x48, 0x23, 0x4c, 0x3d, 0x59, 0xa1, + 0x89, 0x86, 0xa5, 0x46, 0x60, 0xa1, 0x4b, 0x0a, + +}; +/* clang-format on */ + +static struct zcbor_string valid_manifest_component_id = { + .value = valid_manifest_component, + .len = sizeof(valid_manifest_component), +}; + +static suit_plat_err_t suit_dfu_cache_sink_get_dummy(struct stream_sink *sink, + uint8_t cache_partition_id, const uint8_t *uri, + size_t uri_size, bool write_enabled) +{ + struct stream_sink dummy_sink = {0}; + + zassert_not_equal(sink, NULL, + "The API must provide a valid pointer, to fill sink structure"); + zassert_equal(write_enabled, true, "Dry-run flag enabled in regular scenario"); + *sink = dummy_sink; + + return SUIT_PLAT_SUCCESS; +} + static void test_before(void *data) { /* Reset mocks */ @@ -24,11 +57,11 @@ ZTEST_SUITE(suit_platform_app_fetch_tests, NULL, NULL, test_before, NULL, NULL); ZTEST(suit_platform_app_fetch_tests, test_fetch_type_supported) { - zassert_true( + zassert_false( suit_plat_fetch_domain_specific_is_type_supported(SUIT_COMPONENT_TYPE_CAND_IMG), "suit_plat_fetch_domain_specific_is_type_supported returned false for supported " "type"); - zassert_true( + zassert_false( suit_plat_fetch_domain_specific_is_type_supported(SUIT_COMPONENT_TYPE_CAND_MFST), "suit_plat_fetch_domain_specific_is_type_supported returned false for supported " "type"); @@ -56,14 +89,14 @@ ZTEST(suit_platform_app_fetch_tests, test_fetch_type_supported) ZTEST(suit_platform_app_fetch_tests, test_fetch_integrated_type_supported) { - zassert_true(suit_plat_fetch_integrated_domain_specific_is_type_supported( - SUIT_COMPONENT_TYPE_CAND_IMG), - "suit_plat_fetch_integrated_domain_specific_is_type_supported returned false " - "for supported type"); - zassert_true(suit_plat_fetch_integrated_domain_specific_is_type_supported( - SUIT_COMPONENT_TYPE_CAND_MFST), - "suit_plat_fetch_integrated_domain_specific_is_type_supported returned false " - "for supported type"); + zassert_false(suit_plat_fetch_integrated_domain_specific_is_type_supported( + SUIT_COMPONENT_TYPE_CAND_IMG), + "suit_plat_fetch_integrated_domain_specific_is_type_supported returned false " + "for supported type"); + zassert_false(suit_plat_fetch_integrated_domain_specific_is_type_supported( + SUIT_COMPONENT_TYPE_CAND_MFST), + "suit_plat_fetch_integrated_domain_specific_is_type_supported returned false " + "for supported type"); zassert_false(suit_plat_fetch_integrated_domain_specific_is_type_supported( SUIT_COMPONENT_TYPE_CACHE_POOL), @@ -89,200 +122,67 @@ ZTEST(suit_platform_app_fetch_tests, test_fetch_integrated_type_supported) ZTEST(suit_platform_app_fetch_tests, test_fetch_unsupported_component_type) { - struct stream_sink dummy_sink = {0}; struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_UNSUPPORTED, &dummy_sink, - &dummy_uri), + SUIT_COMPONENT_TYPE_UNSUPPORTED, &dummy_uri, + &valid_manifest_component_id, NULL), SUIT_ERR_UNSUPPORTED_COMPONENT_ID, "Unsupported component type returned incorrect error code"); } -ZTEST(suit_platform_app_fetch_tests, test_fetch_dfu_cache_streamer_fail) -{ - struct stream_sink dummy_sink = {0}; - struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; - - suit_dfu_cache_streamer_stream_fake.return_val = SUIT_PLAT_ERR_IO; - - zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CAND_IMG, &dummy_sink, - &dummy_uri), - SUIT_SUCCESS, "Failed when URI not found in cache (should succeed)"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.call_count, 1, - "Incorrect number of suit_dfu_cache_streamer_stream() calls"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg0_val, dummy_uri.value, - "Incorrect value streamer argument"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg1_val, dummy_uri.len, - "Incorrect value of streamer argument"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg2_val, &dummy_sink, - "Incorrect value of streamer argument"); - - zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 0, - "Incorrect number of suit_dfu_cache_sink_commit() calls"); - zassert_equal(suit_fetch_source_stream_fake.call_count, 0, - "Incorrect number of suit_fetch_source_stream() calls"); -} - -ZTEST(suit_platform_app_fetch_tests, test_fetch_dfu_cache_streamer_success) -{ - struct stream_sink dummy_sink = {0}; - struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; - - suit_component_type_t types[] = {SUIT_COMPONENT_TYPE_CAND_IMG, - SUIT_COMPONENT_TYPE_CAND_MFST}; - - for (size_t i = 0; i < ARRAY_SIZE(types); i++) { - mocks_reset(); - FFF_RESET_HISTORY(); - - suit_dfu_cache_streamer_stream_fake.return_val = SUIT_PLAT_SUCCESS; - - zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, types[i], - &dummy_sink, &dummy_uri), - SUIT_SUCCESS, "suit_plat_fetch_domain_specific() failed"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.call_count, 1, - "Incorrect number of suit_dfu_cache_streamer_stream() calls"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg0_val, dummy_uri.value, - "Incorrect value streamer argument"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg1_val, dummy_uri.len, - "Incorrect value of streamer argument"); - zassert_equal(suit_dfu_cache_streamer_stream_fake.arg2_val, &dummy_sink, - "Incorrect value of streamer argument"); - - zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 0, - "Incorrect number of suit_dfu_cache_sink_commit() calls"); - zassert_equal(suit_fetch_source_stream_fake.call_count, 0, - "Incorrect number of suit_fetch_source_stream() calls"); - } -} - ZTEST(suit_platform_app_fetch_tests, test_fetch_fetch_source_streamer_fail) { - struct stream_sink dummy_sink = {0}; struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; + /* Pretend that component handle is valid. */ + suit_plat_component_id_get_fake.return_val = SUIT_SUCCESS; + suit_plat_decode_component_number_fake.return_val = SUIT_PLAT_SUCCESS; + suit_dfu_cache_sink_get_fake.custom_fake = suit_dfu_cache_sink_get_dummy; suit_fetch_source_stream_fake.return_val = SUIT_PLAT_ERR_IO; zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CACHE_POOL, &dummy_sink, - &dummy_uri), - SUIT_SUCCESS, "Failed when unable to fetch payload (should succeed)"); + SUIT_COMPONENT_TYPE_CACHE_POOL, &dummy_uri, + &valid_manifest_component_id, NULL), + SUIT_SUCCESS, "Failed when URI not found in cache (should succeed)"); zassert_equal(suit_fetch_source_stream_fake.call_count, 1, "Incorrect number of suit_fetch_source_stream() calls"); zassert_equal(suit_fetch_source_stream_fake.arg0_val, dummy_uri.value, "Incorrect value streamer argument"); zassert_equal(suit_fetch_source_stream_fake.arg1_val, dummy_uri.len, "Incorrect value of streamer argument"); - zassert_equal(suit_fetch_source_stream_fake.arg2_val, &dummy_sink, - "Incorrect value of streamer argument"); zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 0, "Incorrect number of suit_dfu_cache_sink_commit() calls"); zassert_equal(suit_dfu_cache_streamer_stream_fake.call_count, 0, - "Incorrect number of suit_fetch_source_stream() calls"); + "Incorrect number of suit_dfu_cache_streamer_stream() calls"); } -ZTEST(suit_platform_app_fetch_tests, test_fetch_cache_pool_type) +ZTEST(suit_platform_app_fetch_tests, test_fetch_fetch_source_streamer_success) { - uint8_t dummy_ctx = 0; - struct stream_sink dummy_sink = {.ctx = &dummy_ctx}; struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; - suit_fetch_source_stream_fake.return_val = SUIT_PLAT_SUCCESS; - - zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CACHE_POOL, &dummy_sink, - &dummy_uri), - SUIT_SUCCESS, "Failed to return correct error code"); - zassert_equal(suit_fetch_source_stream_fake.call_count, 1, - "Incorrect number of suit_fetch_source_stream() calls"); - zassert_equal(suit_fetch_source_stream_fake.arg0_val, dummy_uri.value, - "Incorrect value streamer argument"); - zassert_equal(suit_fetch_source_stream_fake.arg1_val, dummy_uri.len, - "Incorrect value of streamer argument"); - zassert_equal(suit_fetch_source_stream_fake.arg2_val, &dummy_sink, - "Incorrect value of streamer argument"); - - zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 1, - "Incorrect number of suit_dfu_cache_sink_commit() calls"); - zassert_equal(suit_dfu_cache_sink_commit_fake.arg0_val, &dummy_ctx, - "Incorrect value suit_dfu_cache_sink_commit argument"); - - zassert_equal(suit_dfu_cache_streamer_stream_fake.call_count, 0, - "Incorrect number of suit_fetch_source_stream() calls"); -} - -ZTEST(suit_platform_app_fetch_tests, test_fetch_mem_type) -{ - uint8_t dummy_ctx = 0; - struct stream_sink dummy_sink = {.ctx = &dummy_ctx}; - struct zcbor_string dummy_uri = {.value = (const uint8_t *)"test", .len = 4}; + suit_dfu_cache_streamer_stream_fake.return_val = SUIT_PLAT_SUCCESS; + /* Pretend that component handle is valid. */ + suit_plat_component_id_get_fake.return_val = SUIT_SUCCESS; + suit_plat_decode_component_number_fake.return_val = SUIT_PLAT_SUCCESS; + suit_dfu_cache_sink_get_fake.custom_fake = suit_dfu_cache_sink_get_dummy; suit_fetch_source_stream_fake.return_val = SUIT_PLAT_SUCCESS; zassert_equal(suit_plat_fetch_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_MEM, &dummy_sink, - &dummy_uri), - SUIT_SUCCESS, "Failed to return correct error code"); + SUIT_COMPONENT_TYPE_CACHE_POOL, &dummy_uri, + &valid_manifest_component_id, NULL), + SUIT_SUCCESS, "suit_plat_fetch_domain_specific() failed"); zassert_equal(suit_fetch_source_stream_fake.call_count, 1, "Incorrect number of suit_fetch_source_stream() calls"); zassert_equal(suit_fetch_source_stream_fake.arg0_val, dummy_uri.value, "Incorrect value streamer argument"); zassert_equal(suit_fetch_source_stream_fake.arg1_val, dummy_uri.len, "Incorrect value of streamer argument"); - zassert_equal(suit_fetch_source_stream_fake.arg2_val, &dummy_sink, - "Incorrect value of streamer argument"); - - zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 0, + zassert_equal(suit_dfu_cache_sink_commit_fake.call_count, 1, "Incorrect number of suit_dfu_cache_sink_commit() calls"); zassert_equal(suit_dfu_cache_streamer_stream_fake.call_count, 0, - "Incorrect number of suit_fetch_source_stream() calls"); -} - -ZTEST(suit_platform_app_fetch_tests, test_fetch_integrated_domain_specific_no_payload) -{ - struct stream_sink dummy_sink = {0}; - - zassert_equal(suit_plat_fetch_integrated_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CACHE_POOL, - &dummy_sink, NULL), - SUIT_ERR_UNAVAILABLE_PAYLOAD, - "suit_plat_fetch_integrated_domain_specific did not fail"); -} - -ZTEST(suit_platform_app_fetch_tests, test_fetch_integrated_domain_specific_streamer_fail) -{ - struct stream_sink dummy_sink = {0}; - uint8_t dummy_payload[] = {0, 1, 2, 3, 4}; - struct zcbor_string payload = { - .value = dummy_payload, - .len = sizeof(dummy_payload), - }; - - suit_generic_address_streamer_stream_fake.return_val = SUIT_PLAT_ERR_NOT_FOUND; - - zassert_equal(suit_plat_fetch_integrated_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CACHE_POOL, - &dummy_sink, &payload), - SUIT_ERR_CRASH, "suit_plat_fetch_integrated_domain_specific did not fail"); -} - -ZTEST(suit_platform_app_fetch_tests, test_fetch_integrated_domain_specific) -{ - struct stream_sink dummy_sink = {0}; - uint8_t dummy_payload[] = {0, 1, 2, 3, 4}; - struct zcbor_string payload = { - .value = dummy_payload, - .len = sizeof(dummy_payload), - }; - - suit_generic_address_streamer_stream_fake.return_val = SUIT_PLAT_SUCCESS; - - zassert_equal(suit_plat_fetch_integrated_domain_specific(TEST_COMPONENT_HANDLE, - SUIT_COMPONENT_TYPE_CACHE_POOL, - &dummy_sink, &payload), - SUIT_SUCCESS, "suit_plat_fetch_integrated_domain_specific ail"); + "Incorrect number of suit_dfu_cache_streamer_stream() calls"); } diff --git a/tests/subsys/suit/unit/mocks/CMakeLists.txt b/tests/subsys/suit/unit/mocks/CMakeLists.txt index b17d1c3ca037..8eb28f8e4f30 100644 --- a/tests/subsys/suit/unit/mocks/CMakeLists.txt +++ b/tests/subsys/suit/unit/mocks/CMakeLists.txt @@ -113,7 +113,7 @@ if (CONFIG_MOCK_DFU_CACHE_STREAMER) endif() if (CONFIG_MOCK_DFU_CACHE_SINK) - target_compile_options(test_interface INTERFACE -DCONFIG_SUIT_STREAM) + target_compile_options(test_interface INTERFACE -DCONFIG_SUIT_STREAM -DCONFIG_SUIT_STREAM_SINK_CACHE) target_include_directories(testbinary PRIVATE ${SUIT_SUBSYS_DIR}/stream/stream_sinks/include) endif()