From 37de702e973ff2d0777bd16292aa19228dc85967 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Wed, 11 Dec 2024 02:35:26 +0530 Subject: [PATCH] feat(nvs_flash): Enable the usage of mbedtls from ROM for bootloader NVS decryption Bootloader NVS decryption uses hardware ROM APIs to decrypt the NVS contents, but for targets that do not support AES hardware we could benefit by using the software mbedtls library that is present in the ROM directly. --- components/esp_rom/CMakeLists.txt | 7 ++ components/mbedtls/CMakeLists.txt | 13 ++- components/mbedtls/Kconfig | 11 +++ .../port/mbedtls_rom/mbedtls_rom_osi.h | 17 +++- .../mbedtls_rom/mbedtls_rom_osi_bootloader.c | 58 +++++++++++ components/nvs_flash/CMakeLists.txt | 1 + .../private_include/nvs_bootloader_aes.h | 19 +++- components/nvs_flash/src/nvs_bootloader_aes.c | 74 +++++++++++++- .../nvs_flash/src/nvs_bootloader_xts_aes.c | 99 +++++++++++++++++++ 9 files changed, 289 insertions(+), 10 deletions(-) create mode 100644 components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi_bootloader.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 580a5bfc48..0570c4de84 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -156,6 +156,13 @@ if(BOOTLOADER_BUILD) endif() endif() + if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) + rom_linker_script("mbedtls") + # For ESP32C2(ECO4), mbedTLS in ROM has been updated to v3.6.0-LTS + if(CONFIG_ESP32C2_REV_MIN_FULL GREATER_EQUAL 200) + rom_linker_script("mbedtls.eco4") + endif() + endif() else() # Regular app build if(target STREQUAL "esp32") diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 8bc72f6179..8662869c89 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -5,6 +5,18 @@ idf_build_get_property(esp_tee_build ESP_TEE_BUILD) if(esp_tee_build) include(${COMPONENT_DIR}/esp_tee/esp_tee_mbedtls.cmake) return() + +elseif(BOOTLOADER_BUILD) # TODO: IDF-11673 + if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) + set(include_dirs "${COMPONENT_DIR}/mbedtls/include" + "port/mbedtls_rom") + set(srcs "port/mbedtls_rom/mbedtls_rom_osi_bootloader.c") + endif() + + idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "${include_dirs}" + PRIV_REQUIRES hal) + return() endif() if(NOT ${IDF_TARGET} STREQUAL "linux") @@ -88,7 +100,6 @@ if(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE) "${crt_bundle}") endif() - # Only build mbedtls libraries set(ENABLE_TESTING CACHE BOOL OFF) set(ENABLE_PROGRAMS CACHE BOOL OFF) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 7fd3d87ab6..b1edb31fba 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -1212,6 +1212,17 @@ menu "mbedTLS" Disabling this config can save some code/rodata size as the error string conversion implementation is replaced with an empty stub. + config MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER + bool "Use ROM implementation of the crypto algorithm in the bootloader" + depends on ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB + default "n" + select MBEDTLS_AES_C + help + Enable this flag to use mbedtls crypto algorithm from ROM instead of ESP-IDF + in case of a bootloader build. + Similar to the MBEDTLS_USE_CRYPTO_ROM_IMPL config but enables usage of the + mbedtls crypto algorithm from ROM for the bootloader build. + config MBEDTLS_USE_CRYPTO_ROM_IMPL bool "Use ROM implementation of the crypto algorithm" depends on ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB diff --git a/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi.h b/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi.h index b612adfa55..52fe58de3e 100644 --- a/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi.h +++ b/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi.h @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include #include "mbedtls/aes.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" @@ -43,6 +44,7 @@ extern "C" { #endif +#ifndef BOOTLOADER_BUILD #if (!defined(CONFIG_MBEDTLS_THREADING_C)) #error CONFIG_MBEDTLS_THREADING_C #endif @@ -51,6 +53,9 @@ typedef void (*_rom_mbedtls_threading_set_alt_t)(void (*mutex_init)(mbedtls_thre void (*mutex_free)(mbedtls_threading_mutex_t *), int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)); +#else /* BOOTLOADER_BUILD */ +typedef void mbedtls_threading_mutex_t; +#endif /* BOOTLOADER_BUILD */ typedef struct mbedtls_rom_funcs { void (*_rom_mbedtls_aes_init)( mbedtls_aes_context *ctx ); @@ -659,8 +664,8 @@ typedef struct mbedtls_rom_eco4_funcs { #define STRUCT_OFFSET_CHECK(x, y, z) _Static_assert((offsetof(x,y)==(z)), "The variables type of "#x" before "#y" should be "#z) #define STRUCT_SIZE_CHECK(x, y) _Static_assert((sizeof(x)==(y)), "The sizeof "#x" should be "#y) -#if (!defined(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL)) -#error "CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL" +#if (!defined(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) && !defined(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER)) +#error "Please enable CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL or CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER" #endif /* platform_util.c */ @@ -668,6 +673,7 @@ typedef struct mbedtls_rom_eco4_funcs { #error "MBEDTLS_PLATFORM_ZEROIZE_ALT" #endif +#ifndef BOOTLOADER_BUILD /* sha1.c */ STRUCT_OFFSET_CHECK(mbedtls_sha1_context, total, 0); STRUCT_OFFSET_CHECK(mbedtls_sha1_context, state, 8); @@ -788,6 +794,11 @@ STRUCT_OFFSET_CHECK(mbedtls_md5_context, MBEDTLS_PRIVATE(state), 8); STRUCT_OFFSET_CHECK(mbedtls_md5_context, MBEDTLS_PRIVATE(buffer), 24); STRUCT_SIZE_CHECK(mbedtls_md5_context, 88); #endif +#endif /* BOOTLOADER_BUILD */ + +#if BOOTLOADER_BUILD +void mbedtls_rom_osi_functions_init_bootloader(void); +#endif /* BOOTLOADER_BUILD */ #ifdef __cplusplus } diff --git a/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi_bootloader.c b/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi_bootloader.c new file mode 100644 index 0000000000..2c730a9ff7 --- /dev/null +++ b/components/mbedtls/port/mbedtls_rom/mbedtls_rom_osi_bootloader.c @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" +#include "mbedtls_rom_osi.h" + +/* This structure can be automatically generated by the script with rom.mbedtls.ld. */ +static const mbedtls_rom_funcs_t mbedtls_rom_funcs_table = { + /* Fill the ROM functions into mbedtls rom function table. */ + /* aes module */ + ._rom_mbedtls_aes_init = mbedtls_aes_init, + ._rom_mbedtls_aes_free = mbedtls_aes_free, + ._rom_mbedtls_aes_setkey_enc = mbedtls_aes_setkey_enc, + ._rom_mbedtls_aes_setkey_dec = mbedtls_aes_setkey_dec, + ._rom_mbedtls_aes_crypt_ecb = mbedtls_aes_crypt_ecb, + ._rom_mbedtls_aes_crypt_cbc = mbedtls_aes_crypt_cbc, + ._rom_mbedtls_internal_aes_encrypt = mbedtls_internal_aes_encrypt, + ._rom_mbedtls_internal_aes_decrypt = mbedtls_internal_aes_decrypt, +}; + +/* This structure can be automatically generated by the script with rom.mbedtls.ld. */ +static const mbedtls_rom_eco4_funcs_t mbedtls_rom_eco4_funcs_table = { + /* Fill the ROM functions into mbedtls rom function table. */ + /* aes module */ + ._rom_mbedtls_aes_init = mbedtls_aes_init, + ._rom_mbedtls_aes_free = mbedtls_aes_free, + ._rom_mbedtls_aes_setkey_enc = mbedtls_aes_setkey_enc, + ._rom_mbedtls_aes_setkey_dec = mbedtls_aes_setkey_dec, + ._rom_mbedtls_aes_crypt_ecb = mbedtls_aes_crypt_ecb, + ._rom_mbedtls_aes_crypt_cbc = mbedtls_aes_crypt_cbc, + ._rom_mbedtls_internal_aes_encrypt = mbedtls_internal_aes_encrypt, + ._rom_mbedtls_internal_aes_decrypt = mbedtls_internal_aes_decrypt, + + ._rom_mbedtls_aes_xts_init = mbedtls_aes_xts_init, + ._rom_mbedtls_aes_xts_free = mbedtls_aes_xts_free, + ._rom_mbedtls_aes_xts_setkey_enc = mbedtls_aes_xts_setkey_enc, + ._rom_mbedtls_aes_xts_setkey_dec = mbedtls_aes_xts_setkey_dec, + ._rom_mbedtls_aes_crypt_xts = mbedtls_aes_crypt_xts, +}; + +void mbedtls_rom_osi_functions_init_bootloader(void) +{ + // /* Export the rom mbedtls functions table pointer */ + extern void *mbedtls_rom_osi_funcs_ptr; + + unsigned chip_version = efuse_hal_chip_revision(); + if ( ESP_CHIP_REV_ABOVE(chip_version, 200) ) { + /* Initialize the pointer of rom eco4 mbedtls functions table. */ + mbedtls_rom_osi_funcs_ptr = (mbedtls_rom_eco4_funcs_t *)&mbedtls_rom_eco4_funcs_table; + } else { + /* Initialize the pointer of rom mbedtls functions table. */ + mbedtls_rom_osi_funcs_ptr = (mbedtls_rom_funcs_t *)&mbedtls_rom_funcs_table; + } +} diff --git a/components/nvs_flash/CMakeLists.txt b/components/nvs_flash/CMakeLists.txt index 6f43b478bb..281ff63d8d 100644 --- a/components/nvs_flash/CMakeLists.txt +++ b/components/nvs_flash/CMakeLists.txt @@ -10,6 +10,7 @@ if(BOOTLOADER_BUILD) idf_component_register(SRCS "${srcs}" REQUIRES "${requires}" + PRIV_REQUIRES "mbedtls" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "private_include" ) diff --git a/components/nvs_flash/private_include/nvs_bootloader_aes.h b/components/nvs_flash/private_include/nvs_bootloader_aes.h index be05e9d4eb..97fc6230be 100644 --- a/components/nvs_flash/private_include/nvs_bootloader_aes.h +++ b/components/nvs_flash/private_include/nvs_bootloader_aes.h @@ -6,18 +6,31 @@ #pragma once #include +#include "soc/soc_caps.h" #include "sdkconfig.h" -#include "rom/aes.h" -#if CONFIG_IDF_TARGET_ESP32 +#if defined(CONFIG_IDF_TARGET_ESP32) || !defined(SOC_AES_SUPPORTED) enum AES_TYPE { AES_ENC, AES_DEC, }; -#endif /* CONFIG_IDF_TARGET_ESP32 */ + +#if !SOC_AES_SUPPORTED +enum AES_BITS { + AES128, + AES192, + AES256 +}; +#endif /* !SOC_AES_SUPPORTED */ +#endif /* CONFIG_IDF_TARGET_ESP32 || !SOC_AES_SUPPORTED */ + +#if SOC_AES_SUPPORTED +#include "rom/aes.h" int nvs_bootloader_aes_crypt_ecb(enum AES_TYPE mode, const unsigned char *key, enum AES_BITS key_bits, const unsigned char input[16], unsigned char output[16]); + +#endif /* SOC_AES_SUPPORTED */ diff --git a/components/nvs_flash/src/nvs_bootloader_aes.c b/components/nvs_flash/src/nvs_bootloader_aes.c index c6a2e20cf0..5cbbab5ad0 100644 --- a/components/nvs_flash/src/nvs_bootloader_aes.c +++ b/components/nvs_flash/src/nvs_bootloader_aes.c @@ -1,13 +1,16 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include +#include "esp_log.h" +#include "soc/soc_caps.h" #include "nvs_bootloader_aes.h" #include "sdkconfig.h" +#if SOC_AES_SUPPORTED int nvs_bootloader_aes_crypt_ecb(enum AES_TYPE mode, const unsigned char *key, enum AES_BITS key_bits, @@ -30,14 +33,79 @@ int nvs_bootloader_aes_crypt_ecb(enum AES_TYPE mode, // whereas for other targets ets_aes_setkey return 0 on success ret = 0; } -#else /* !CONFIG_IDF_TARGET_ESP32m*/ +#else /* CONFIG_IDF_TARGET_ESP32 */ ret = ets_aes_setkey(mode, key, key_bits); if (ret == 0) { ets_aes_block(input, output); } -#endif /* CONFIG_IDF_TARGET_ESP32 */ +#endif /* !CONFIG_IDF_TARGET_ESP32 */ ets_aes_disable(); return ret; } + +#else /* SOC_AES_SUPPORTED */ +#if BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER +#if CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB +#error "Enable `CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER` for non SOC_AES_SUPPORTED targets for supporting NVS encryption in bootloader build" +#else /* !CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB */ +// TODO: IDF-11673 +// Due to unavailability of an software AES layer for bootloader build, +// we cannot support the below NVS bootloader's AES operations +// Thus we are adding stub APIs to indicate that the following operation fail. + +static const char *TAG = "nvs_bootloader_aes"; +static const char *op_unsupported_error = "AES operation in bootloader unsupported for this target"; + +int nvs_bootloader_aes_crypt_ecb(enum AES_TYPE mode, + const unsigned char *key, + enum AES_BITS key_bits, + const unsigned char input[16], + unsigned char output[16]) +{ + ESP_EARLY_LOGE(TAG, "%s", op_unsupported_error); + abort(); + return -1; +} +#endif /* CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB */ +#else /* BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER */ +#include "mbedtls/aes.h" + +int nvs_bootloader_aes_crypt_ecb(enum AES_TYPE mode, + const unsigned char *key, + enum AES_BITS key_bits, + const unsigned char input[16], + unsigned char output[16]) +{ + int ret = -1; + + uint16_t keybits = key_bits == AES256 ? 256 : key_bits == AES192 ? 192 : 128; + int mbedtls_aes_mode = mode == AES_ENC ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT; + + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + + if (mode == AES_ENC) { + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + } else { + ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); + } + + if (ret != 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + ret = mbedtls_aes_crypt_ecb(&ctx, mbedtls_aes_mode, input, output); + + if (ret != 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + mbedtls_aes_free(&ctx); + return ret; +} +#endif /* !(BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) */ +#endif /* !SOC_AES_SUPPORTED */ diff --git a/components/nvs_flash/src/nvs_bootloader_xts_aes.c b/components/nvs_flash/src/nvs_bootloader_xts_aes.c index bd7500f537..ce204f6a9d 100644 --- a/components/nvs_flash/src/nvs_bootloader_xts_aes.c +++ b/components/nvs_flash/src/nvs_bootloader_xts_aes.c @@ -7,10 +7,15 @@ #include #include #include "esp_err.h" +#include "esp_log.h" #include "nvs_bootloader_aes.h" #include "nvs_bootloader_xts_aes.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#if SOC_AES_SUPPORTED /* * NOTE: The implementation of the below APIs have been copied * from the mbedtls (v3.6.2) implementation of the XTS-AES APIs. @@ -198,3 +203,97 @@ int nvs_bootloader_aes_crypt_xts(nvs_bootloader_xts_aes_context *ctx, return 0; } +#else /* SOC_AES_SUPPORTED */ +#if BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER +#if CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB +#error "Enable `CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER` for non SOC_AES_SUPPORTED targets for supporting NVS encryption in bootloader build" +#else /* !CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB */ +// TODO: IDF-11673 +// Due to unavailability of an software AES layer for bootloader build, +// we cannot support the below NVS bootloader's AES operations +// Thus we are adding stub APIs to indicate that the following operation fail. + +static const char *TAG = "nvs_bootloader_xts_aes"; +static const char *op_unsupported_error = "XTS-AES operation in bootloader unsupported for this target"; + +void nvs_bootloader_xts_aes_init(nvs_bootloader_xts_aes_context *ctx) +{ + (void) ctx; + ESP_EARLY_LOGE(TAG, "%s", op_unsupported_error); + abort(); +} + +void nvs_bootloader_xts_aes_free(nvs_bootloader_xts_aes_context *ctx) +{ + (void) ctx; + ESP_EARLY_LOGE(TAG, "%s", op_unsupported_error); + abort(); +} + +int nvs_bootloader_xts_aes_setkey(nvs_bootloader_xts_aes_context *ctx, + const unsigned char *key, + unsigned int key_bytes) +{ + (void) ctx; + ESP_EARLY_LOGE(TAG, "%s", op_unsupported_error); + abort(); + return -1; +} +/* + * XTS-AES buffer encryption/decryption + */ +int nvs_bootloader_aes_crypt_xts(nvs_bootloader_xts_aes_context *ctx, + enum AES_TYPE mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output) +{ + (void) ctx; + ESP_EARLY_LOGE(TAG, "XTS-AES operation in bootloader unsupported"); + abort(); + return -1; +} + +#endif /* CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB */ +#else /* BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER */ +#include "mbedtls/aes.h" + +static mbedtls_aes_xts_context ctx_xts; + +void nvs_bootloader_xts_aes_init(nvs_bootloader_xts_aes_context *ctx) +{ + (void) ctx; + mbedtls_aes_xts_init(&ctx_xts); +} + +void nvs_bootloader_xts_aes_free(nvs_bootloader_xts_aes_context *ctx) +{ + (void) ctx; + mbedtls_aes_xts_free(&ctx_xts); +} + +int nvs_bootloader_xts_aes_setkey(nvs_bootloader_xts_aes_context *ctx, + const unsigned char *key, + unsigned int key_bytes) +{ + (void) ctx; + return mbedtls_aes_xts_setkey_dec(&ctx_xts, key, key_bytes * 8); +} +/* + * XTS-AES buffer encryption/decryption + */ +int nvs_bootloader_aes_crypt_xts(nvs_bootloader_xts_aes_context *ctx, + enum AES_TYPE mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output) +{ + (void) ctx; + + int mbedtls_aes_mode = mode == AES_ENC ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT; + return mbedtls_aes_crypt_xts(&ctx_xts, mbedtls_aes_mode, length, data_unit, input, output); +} +#endif /* !(BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) */ +#endif /* !SOC_AES_SUPPORTED */