From cedd5b78609034ad21936908bc55cfc60a82aa6a Mon Sep 17 00:00:00 2001 From: Jaroslaw Stelter Date: Fri, 12 Jan 2024 13:46:30 +0100 Subject: [PATCH] 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 | 10 +++ src/library_manager/lib_manager.c | 105 +++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 5e0e47fdacb7..3c44755b246d 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 @@ -86,6 +89,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 f9a71ebf6cda..37692164ee4f 100644 --- a/src/library_manager/Kconfig +++ b/src/library_manager/Kconfig @@ -13,4 +13,14 @@ config LIBRARY_MANAGER Externally developed modules both for SOF and Zephyr could be used if enabled. If unsure say N. + +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 a9cd472421c4..2d5e07e180a3 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 @@ -578,6 +650,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); @@ -590,6 +672,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); @@ -699,7 +791,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; @@ -710,8 +802,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) {