From fba1f177ae77a87e76d41d853fa9b26681868b59 Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Fri, 12 Jan 2024 13:39:09 +0100 Subject: [PATCH 1/4] platform: ace: Add authentication interface For ACE platforms library authentication could be done using external entity - rom_ext. This module reside in L3 memory space and provides verification functionality. Following code expose that API to SOF. Signed-off-by: Jaroslaw Stelter --- src/include/sof/auth_api_iface.h | 149 ++++++++++++++++++ .../intel/ace/include/auth/intel_auth_api.h | 78 +++++++++ .../include/auth/intel_status_logger_api.h | 44 ++++++ .../include/auth/intel_status_logger_iface.h | 73 +++++++++ 4 files changed, 344 insertions(+) create mode 100644 src/include/sof/auth_api_iface.h create mode 100644 src/platform/intel/ace/include/auth/intel_auth_api.h create mode 100644 src/platform/intel/ace/include/auth/intel_status_logger_api.h create mode 100644 src/platform/intel/ace/include/auth/intel_status_logger_iface.h diff --git a/src/include/sof/auth_api_iface.h b/src/include/sof/auth_api_iface.h new file mode 100644 index 000000000000..ff8b1006076a --- /dev/null +++ b/src/include/sof/auth_api_iface.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Pawel Dobrowolski + */ +#ifndef __AUTH_API_IFACE_H__ +#define __AUTH_API_IFACE_H__ + +#include +#include +#include + +#define AUTH_API_VERSION_MAJOR (2) +#define AUTH_API_VERSION_MINOR (0) +#define AUTH_API_VERSION_PATCH (0) + +#define AUTH_SCRATCH_BUFF_SZ (0xA000) // 40kB + +/* + * Return codes supported by authentication engine: + * ADSP_AUTH_IMAGE_UNTRUSTED = 9040, + * ADSP_AUTH_CANNOT_ALLOCATE_SCRATCH_BUFF = 9041, + * ADSP_AUTH_INVALID_AUTH_API_CTX_PTR = 9042, + * ADSP_AUTH_SVN_VERIFICATION_FAIL = 9043, + * ADSP_AUTH_IFWI_PARTITION_FAIL = 9044, + * ADSP_AUTH_VERIFY_IMAGE_TYPE_FAIL = 9045, + * ADSP_AUTH_UNSUPPORTED_VERSION = 9046, + * ADSP_AUTH_INCOMPATIBLE_MANIFEST_VERSION = 9047, + */ + +struct auth_api_version_num { + uint8_t patch; + uint8_t minor; + uint8_t major; + uint8_t rsvd; +} __packed __aligned(4); + +enum auth_phase { + AUTH_PHASE_FIRST = 0, + AUTH_PHASE_MID = 1, + AUTH_PHASE_LAST = 2 +}; + +enum auth_result { + AUTH_NOT_COMPLETED = 0, + AUTH_IMAGE_TRUSTED = 1, + AUTH_IMAGE_UNTRUSTED = 2 +}; + +enum auth_image_type { + IMG_TYPE_ROM_EXT = 0, + IMG_TYPE_MAIN_FW = 1, + IMG_TYPE_LIB = 2 +}; + +struct auth_api_ctx; + +struct auth_api_version { + /* Interface to return authentication API version. + * Return value: version number represented by auth_api_version_num structure. + */ + struct auth_api_version_num (*version)(); +}; + +struct auth_api { + /* Interface to initialize authentication API and context. + * Parameters: + * ctx - pointer to the context instance of type auth_api_ctx. + * scratch_buff - pointer to scratch buffer. + * Scratch buffer must be located in L2 Local Memory (SHA Engine limitation). + * Caller is responsible to power up necessary L2 Local Memory banks. + * Address alignment must correspond to SHA384_IO_BUF_ALIGNMENT. + * scratch_buff_size – size must be the same as AUTH_SCRATCH_BUFF_SZ. + * Return value: + * ADSP_SUCCESS - successful initialization. + */ + int (*init)(struct auth_api_ctx *ctx, void *scratch_buff, size_t scratch_buff_size, + enum auth_image_type image_type); + + /* Interface to cleanup authentication API. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + */ + void (*cleanup)(struct auth_api_ctx *ctx); + + /* Interface for initiating signed FW image (async) authentication process. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * chunk - pointer to the chunk of signed FW image. + * chunk_size - chunk size in bytes. + * phase - authentication phase. + * Must corresponds to one of the AuthPhase values. + * In case of one time FW authentication, where signed FW image size must be + * less or equal to scratch_buff_size, the caller must pass AUTH_PHASE_LAST. + * Return value: ADSP_SUCCESS when authentication process has been initiated + * successfully, or one of ADSP_FLV_* error codes in case of failure. + */ + int (*init_auth_proc)(struct auth_api_ctx *ctx, const void *chunk, size_t chunk_size, + enum auth_phase phase); + + /* Interface to return if authentication process is busy. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * This function can be used for authentication process synchronization. + * Return value: true if authentication process is busy. + */ + bool (*busy)(struct auth_api_ctx *ctx); + + /* Interface to return authentication result + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * Return value: + * AUTH_NOT_COMPLETED - authentication is not completed, + * AUTH_IMAGE_TRUSTED - authentication completed and signed FW image is + * trusted, + * AUTH_IMAGE_UNTRUSTED - authentication completed, but signed FW image is + * untrusted. + */ + enum auth_result (*result)(struct auth_api_ctx *ctx); + + /* Interface to register status/error code logger. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + * sts_logger - pointer to status logger. + * Return value: ADSP_SUCCESS when logger has been registered successfully. + */ + int (*register_status_logger)(struct auth_api_ctx *ctx, + struct status_logger_ctx *status_logger); + + /* Interface to unregister status/error code logger. + * Parameters: + * ctx - pointer to the context instance of type AuthApiCtx. + */ + void (*unregister_status_logger)(struct auth_api_ctx *ctx); +}; + +struct auth_api_ctx { + struct auth_api_version *version_api; + void *scratch_buff; + size_t scratch_buff_size; + enum auth_result result; + struct auth_api *auth_api; + enum auth_image_type image_type; + struct status_logger_ctx *status_logger; +}; + +#endif /* __SOF_LIB_MANAGER_H__ */ diff --git a/src/platform/intel/ace/include/auth/intel_auth_api.h b/src/platform/intel/ace/include/auth/intel_auth_api.h new file mode 100644 index 000000000000..69a9e0cd8ca2 --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_auth_api.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Pawel Dobrowolski + */ +#ifndef INTEL_AUTH_API_H +#define INTEL_AUTH_API_H + +#include + +#define AUTH_API_CALLBACKS_ADDR (0x162000 + 0x140) + +/* The same as auth_api->init. */ +inline int auth_api_init(struct auth_api_ctx *ctx, + void *scratch_buff, + size_t scratch_buff_size, + enum auth_image_type image_type) +{ + struct auth_api_ctx **auth_api_callbacks = + (struct auth_api_ctx **)AUTH_API_CALLBACKS_ADDR; + + ctx->version_api = (*auth_api_callbacks)->version_api; + ctx->auth_api = (*auth_api_callbacks)->auth_api; + return ctx->auth_api->init(ctx, scratch_buff, scratch_buff_size, image_type); +} + +/* The same as auth_api->cleanup. */ +inline void auth_api_cleanup(struct auth_api_ctx *ctx) +{ + ctx->auth_api->cleanup(ctx); +} + +/* The same as auth_api->init_auth_proc. */ +inline int auth_api_init_auth_proc(struct auth_api_ctx *ctx, + const void *chunk, + size_t chunk_size, + enum auth_phase phase) +{ + return ctx->auth_api->init_auth_proc(ctx, chunk, chunk_size, phase); +} + +/* The same as auth_api->busy. */ +inline bool auth_api_busy(struct auth_api_ctx *ctx) +{ + return ctx->auth_api->busy(ctx); +} + +/* The same as auth_api->result. */ +inline enum auth_result auth_api_result(struct auth_api_ctx *ctx) +{ + return ctx->auth_api->result(ctx); +} + +/* The same as auth_api->register_status_logger. */ +inline int auth_api_register_status_logger(struct auth_api_ctx *ctx, + struct status_logger_ctx *status_logger) +{ + return ctx->auth_api->register_status_logger(ctx, status_logger); +} + +/* The same as AuthApi::UnregisterStatusLogger. */ +inline void auth_api_unregister_status_logger(struct auth_api_ctx *ctx) +{ + ctx->auth_api->unregister_status_logger(ctx); +} + +/* The same as auth_api->version. */ +inline struct auth_api_version_num auth_api_version(void) +{ + struct auth_api_ctx **auth_api_callbacks = + (struct auth_api_ctx **)AUTH_API_CALLBACKS_ADDR; + return (*auth_api_callbacks)->version_api->version(); +} + +#endif /* INTEL_AUTH_API_H */ + diff --git a/src/platform/intel/ace/include/auth/intel_status_logger_api.h b/src/platform/intel/ace/include/auth/intel_status_logger_api.h new file mode 100644 index 000000000000..eca4162219da --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_status_logger_api.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Pawel Dobrowolski + */ +#ifndef INTEL_STATUS_LOGGER_API +#define INTEL_STATUS_LOGGER_API + +#include "stdint.h" +#include "intel_status_logger_iface.h" + +inline void sts_log_init(struct status_logger_ctx *ctx) +{ + ctx->cb.init(ctx); +} + +inline void sts_log_cleanup(struct status_logger_ctx *ctx) +{ + ctx->cb.cleanup(ctx); +} + +inline void sts_log_report_error(struct status_logger_ctx *ctx, int error_code) +{ + ctx->cb.report_error(ctx, error_code); +} + +inline void sts_log_set_boot_state(struct status_logger_ctx *ctx, uint32_t state) +{ + ctx->cb.set_boot_state(ctx, state); +} + +inline void sts_log_set_wait_state(struct status_logger_ctx *ctx, uint32_t state) +{ + ctx->cb.set_wait_state(ctx, state); +} + +inline void sts_log_set_module(struct status_logger_ctx *ctx, uint32_t mod) +{ + ctx->cb.set_module(ctx, mod); +} + +#endif /*INTEL_STATUS_LOGGER_API*/ diff --git a/src/platform/intel/ace/include/auth/intel_status_logger_iface.h b/src/platform/intel/ace/include/auth/intel_status_logger_iface.h new file mode 100644 index 000000000000..4a22a072bebc --- /dev/null +++ b/src/platform/intel/ace/include/auth/intel_status_logger_iface.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + * Pawel Dobrowolski + */ +#ifndef INTEL_STATUS_LOGGER_IFACE +#define INTEL_STATUS_LOGGER_IFACE + +#include "stdint.h" + +struct status_logger_ctx; + +/* Status Logger Interface callbacks. */ +struct status_logger_iface { + /* Interface to initialize Status Logger context. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * Return value: + * 0 - SUCCESS - successful initialization. + */ + int (*init)(struct status_logger_ctx *ctx); + + /* Interface to cleanup Status Logger context. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + */ + void (*cleanup)(struct status_logger_ctx *ctx); + + /** + * Reports critical rom error. Halts execution. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param error_code - error code to report + */ + void (*report_error)(struct status_logger_ctx *ctx, int error_code); + + /** + * Reports boot status. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param uint32_t state - boot state code to report. + */ + void (*set_boot_state)(struct status_logger_ctx *ctx, uint32_t state); + + /** + * Reports that caller is waiting on some external event or action. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param uint32_t state - reason of waiting. + */ + void (*set_wait_state)(struct status_logger_ctx *ctx, uint32_t state); + + /** + * Set module type in FSR. + * Parameters: + * @param status_logger_ctx *ctx - pointer to the context instance. + * @param mod module id + */ + + void (*set_module)(struct status_logger_ctx *ctx, uint32_t mod); +} __packed __aligned(4); + +/* Design note: Compiler was not able to generate proper call assembly code using standard C++ + * inheritance in Auth API implementation. That's why we do explicit callbacks assignment, + * following C-like OOP. + */ +struct status_logger_ctx { + struct status_logger_iface cb; +}; + +#endif /*INTEL_STATUS_LOGGER_IFACE*/ From 64a132a879f8ca51e6573d5c33d7b52cdbf099b5 Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Fri, 12 Jan 2024 13:46:30 +0100 Subject: [PATCH 2/4] library_manager: auth: Add library authentication mechanizm This patch adds usage of authentication API to check library signature. If feature enabled it will block loading of library without valid signature. Signed-off-by: Jaroslaw Stelter --- src/include/sof/lib_manager.h | 7 ++ src/library_manager/Kconfig | 9 ++- src/library_manager/lib_manager.c | 105 +++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 2 deletions(-) diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 0ca21bacbb57..70d474bd8860 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -64,6 +64,9 @@ #include #include +#if CONFIG_LIBRARY_AUTH_SUPPORT +#include +#endif #define LIB_MANAGER_MAX_LIBS 16 #define LIB_MANAGER_LIB_ID_SHIFT 12 @@ -88,6 +91,10 @@ struct ext_library { uint32_t lib_notif_count; void *runtime_data; +#if CONFIG_LIBRARY_AUTH_SUPPORT + struct auth_api_ctx auth_ctx; + void *auth_buffer; +#endif }; /* lib manager context, used by lib_notification */ diff --git a/src/library_manager/Kconfig b/src/library_manager/Kconfig index 37fdd0d506a7..e167f956a37a 100644 --- a/src/library_manager/Kconfig +++ b/src/library_manager/Kconfig @@ -14,7 +14,6 @@ config LIBRARY_MANAGER could be used if enabled. If unsure say N. - config LIBCODE_MODULE_SUPPORT bool "Add support for libcode modules" default n @@ -24,6 +23,14 @@ config LIBCODE_MODULE_SUPPORT as lib_code. This modules contains code shared by a multiple modules. This option adds support for modules of this type. + +config LIBRARY_AUTH_SUPPORT + bool "Library Authentication Support" + default n + help + This is support for dynamic modules authentication. + Externally developed modules both for SOF and Zephyr + could be used if enabled. If unsure say N. endmenu diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index 80ffb0da0178..b07d8db15290 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -25,6 +25,10 @@ #include #include +#if CONFIG_LIBRARY_AUTH_SUPPORT +#include +#endif + #include #include #include @@ -47,6 +51,74 @@ struct lib_manager_dma_ext { static struct ext_library loader_ext_lib; +#if CONFIG_LIBRARY_AUTH_SUPPORT +static int lib_manager_auth_init(void) +{ + struct ext_library *ext_lib = ext_lib_get(); + int ret; + + if (auth_api_version().major != AUTH_API_VERSION_MAJOR) + return -EINVAL; + + ext_lib->auth_buffer = rballoc_align(0, SOF_MEM_CAPS_RAM, + AUTH_SCRATCH_BUFF_SZ, CONFIG_MM_DRV_PAGE_SIZE); + if (!ext_lib->auth_buffer) + return -ENOMEM; + + ret = auth_api_init(&ext_lib->auth_ctx, ext_lib->auth_buffer, + AUTH_SCRATCH_BUFF_SZ, IMG_TYPE_LIB); + if (ret != 0) { + tr_err(&lib_manager_tr, "lib_manager_auth_init() failed with error: %d", ret); + rfree(ext_lib->auth_buffer); + ret = -EACCES; + } + + return ret; +} + +static void lib_manager_auth_deinit(void) +{ + struct ext_library *ext_lib = ext_lib_get(); + + if (ext_lib->auth_buffer) + memset(ext_lib->auth_buffer, 0, AUTH_SCRATCH_BUFF_SZ); + + rfree(ext_lib->auth_buffer); + ext_lib->auth_buffer = NULL; + memset(&ext_lib->auth_ctx, 0, sizeof(struct auth_api_ctx)); +} + +static int lib_manager_auth_proc(const void *buffer_data, + size_t buffer_size, enum auth_phase phase) +{ + struct ext_library *ext_lib = ext_lib_get(); + int ret; + + ret = auth_api_init_auth_proc(&ext_lib->auth_ctx, buffer_data, buffer_size, phase); + + if (ret != 0) { + tr_err(&lib_manager_tr, "lib_manager_auth_proc() failed with error: %d", ret); + return -ENOTSUP; + } + + /* The auth_api_busy() will timeouts internally in case of failure */ + while (auth_api_busy(&ext_lib->auth_ctx)) + ; + + ret = auth_api_result(&ext_lib->auth_ctx); + + if (ret != AUTH_IMAGE_TRUSTED) { + tr_err(&lib_manager_tr, "lib_manager_auth_proc() Untrasted library!"); + return -EACCES; + } + + if (phase == AUTH_PHASE_LAST) + auth_api_cleanup(&ext_lib->auth_ctx); + + return 0; +} +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + #if IS_ENABLED(CONFIG_MM_DRV) #define PAGE_SZ CONFIG_MM_DRV_PAGE_SIZE @@ -623,6 +695,16 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, tr_dbg(&lib_manager_tr, "lib_manager_store_library(): pointer: %p", (__sparse_force void *)library_base_address); +#if CONFIG_LIBRARY_AUTH_SUPPORT + /* AUTH_PHASE_FIRST - checks library manifest only. */ + ret = lib_manager_auth_proc((__sparse_force void *)man_buffer, + MAN_MAX_SIZE_V1_8, AUTH_PHASE_FIRST); + if (ret < 0) { + rfree((__sparse_force void *)library_base_address); + return ret; + } +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + /* Copy data from temp_mft_buf to destination memory (pointed by library_base_address) */ memcpy_s((__sparse_force void *)library_base_address, MAN_MAX_SIZE_V1_8, (__sparse_force void *)man_buffer, MAN_MAX_SIZE_V1_8); @@ -635,6 +717,16 @@ static int lib_manager_store_library(struct lib_manager_dma_ext *dma_ext, return ret; } +#if CONFIG_LIBRARY_AUTH_SUPPORT + /* AUTH_PHASE_LAST - do final library authentication checks */ + ret = lib_manager_auth_proc((__sparse_force void *)library_base_address, + preload_size - MAN_MAX_SIZE_V1_8, AUTH_PHASE_LAST); + if (ret < 0) { + rfree((__sparse_force void *)library_base_address); + return ret; + } +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + /* Now update sof context with new library */ lib_manager_update_sof_ctx((__sparse_force void *)library_base_address, lib_id); @@ -744,7 +836,7 @@ int lib_manager_load_library(uint32_t dma_id, uint32_t lib_id, uint32_t type) /* allocate temporary manifest buffer */ man_tmp_buffer = (__sparse_force void __sparse_cache *) rballoc_align(0, SOF_MEM_CAPS_DMA, - MAN_MAX_SIZE_V1_8, dma_ext->addr_align); + MAN_MAX_SIZE_V1_8, CONFIG_MM_DRV_PAGE_SIZE); if (!man_tmp_buffer) { ret = -ENOMEM; goto cleanup; @@ -755,8 +847,19 @@ int lib_manager_load_library(uint32_t dma_id, uint32_t lib_id, uint32_t type) if (ret < 0) goto stop_dma; +#if CONFIG_LIBRARY_AUTH_SUPPORT + /* Initialize authentication support */ + ret = lib_manager_auth_init(); + if (ret < 0) + goto stop_dma; +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + ret = lib_manager_store_library(dma_ext, man_tmp_buffer, lib_id); +#if CONFIG_LIBRARY_AUTH_SUPPORT + lib_manager_auth_deinit(); +#endif /* CONFIG_LIBRARY_AUTH_SUPPORT */ + stop_dma: ret2 = dma_stop(dma_ext->chan->dma->z_dev, dma_ext->chan->index); if (ret2 < 0) { From abb49d551e4b91fd12d4b7cf1a4ed95b50fffca5 Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Fri, 12 Jan 2024 13:52:33 +0100 Subject: [PATCH 3/4] mtl: conf: Enable library authentication on MTL This enables library authentication on MTL platforms. Signed-off-by: Jaroslaw Stelter --- app/boards/intel_adsp_ace15_mtpm.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/intel_adsp_ace15_mtpm.conf b/app/boards/intel_adsp_ace15_mtpm.conf index 3a4422ad7fb9..d48f91e0a654 100644 --- a/app/boards/intel_adsp_ace15_mtpm.conf +++ b/app/boards/intel_adsp_ace15_mtpm.conf @@ -39,6 +39,7 @@ CONFIG_DMA_DW_LLI_POOL_SIZE=50 CONFIG_DMA_DW_SUSPEND_DRAIN=y CONFIG_INTEL_MODULES=y CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_AUTH_SUPPORT=y CONFIG_INTEL_ADSP_TIMER=y CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y CONFIG_AMS=y From 55a520a55fa84a8d3a50cbfcfe33fee4ce9faf09 Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Tue, 23 Jan 2024 17:17:16 +0100 Subject: [PATCH 4/4] lnl: conf: Enable Library authentication on LNL This enables library authentication on LNL platforms. Signed-off-by: Jaroslaw Stelter --- app/boards/intel_adsp_ace20_lnl.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf index 2d45466913a4..fa9acb84d377 100644 --- a/app/boards/intel_adsp_ace20_lnl.conf +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -33,6 +33,7 @@ CONFIG_DMA=y CONFIG_DMA_INTEL_ADSP_GPDMA=n CONFIG_INTEL_MODULES=y CONFIG_LIBRARY_MANAGER=y +CONFIG_LIBRARY_AUTH_SUPPORT=y CONFIG_INTEL_ADSP_TIMER=y CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y CONFIG_AMS=y