From f995034f4c197135f0ac89227f424ac8eae5949a Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 9 Jan 2025 16:39:24 +0100 Subject: [PATCH] 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; }