From a9a7160cb64a67c926b62d173902add1d2698768 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 28 Dec 2021 12:04:05 +0800 Subject: [PATCH 1/2] MPI: add kconfig option for doing intr-based exp-mod operations --- components/mbedtls/Kconfig | 10 ++ components/mbedtls/port/esp32/bignum.c | 10 ++ components/mbedtls/port/esp32c3/bignum.c | 11 ++ components/mbedtls/port/esp32h2/bignum.c | 11 ++ components/mbedtls/port/esp32s2/bignum.c | 11 ++ components/mbedtls/port/esp32s3/bignum.c | 10 ++ components/mbedtls/port/esp_bignum.c | 101 +++++++++++++++++- components/mbedtls/port/include/bignum_impl.h | 13 +++ tools/unit-test-app/configs/aes_no_hw | 1 + 9 files changed, 176 insertions(+), 2 deletions(-) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 690718623c..ff71da1e57 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -282,6 +282,16 @@ menu "mbedTLS" These operations are used by RSA. + config MBEDTLS_MPI_USE_INTERRUPT + bool "Use interrupt for MPI exp-mod operations" + depends on !IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_MPI + default n + help + Use an interrupt to coordinate long MPI operations. + + This allows other code to run on the CPU while an MPI operation is pending. + Otherwise the CPU busy-waits. + config MBEDTLS_HARDWARE_SHA bool "Enable hardware SHA acceleration" default y diff --git a/components/mbedtls/port/esp32/bignum.c b/components/mbedtls/port/esp32/bignum.c index ec2ff1cf75..6246729858 100644 --- a/components/mbedtls/port/esp32/bignum.c +++ b/components/mbedtls/port/esp32/bignum.c @@ -64,6 +64,16 @@ void esp_mpi_disable_hardware_hw_op( void ) } +void esp_mpi_interrupt_enable( bool enable ) +{ + DPORT_REG_WRITE(RSA_INTERRUPT_REG, enable); +} + +void esp_mpi_interrupt_clear( void ) +{ + DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); +} + /* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. If hw_words is higher than the number of words in the bignum then diff --git a/components/mbedtls/port/esp32c3/bignum.c b/components/mbedtls/port/esp32c3/bignum.c index dd61535ba0..a5d13077e2 100644 --- a/components/mbedtls/port/esp32c3/bignum.c +++ b/components/mbedtls/port/esp32c3/bignum.c @@ -48,6 +48,8 @@ void esp_mpi_enable_hardware_hw_op( void ) while (REG_READ(RSA_QUERY_CLEAN_REG) != 1) { } // Note: from enabling RSA clock to here takes about 1.3us + + REG_WRITE(RSA_INTERRUPT_REG, 0); } void esp_mpi_disable_hardware_hw_op( void ) @@ -60,6 +62,15 @@ void esp_mpi_disable_hardware_hw_op( void ) esp_crypto_mpi_lock_release(); } +void esp_mpi_interrupt_enable( bool enable ) +{ + REG_WRITE(RSA_INTERRUPT_REG, enable); +} + +void esp_mpi_interrupt_clear( void ) +{ + REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); +} /* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. diff --git a/components/mbedtls/port/esp32h2/bignum.c b/components/mbedtls/port/esp32h2/bignum.c index 458d7d1b2c..a2c56b68c5 100644 --- a/components/mbedtls/port/esp32h2/bignum.c +++ b/components/mbedtls/port/esp32h2/bignum.c @@ -48,6 +48,8 @@ void esp_mpi_enable_hardware_hw_op( void ) while (REG_READ(RSA_QUERY_CLEAN_REG) != 1) { } // Note: from enabling RSA clock to here takes about 1.3us + + REG_WRITE(RSA_INTERRUPT_REG, 0); } void esp_mpi_disable_hardware_hw_op( void ) @@ -60,6 +62,15 @@ void esp_mpi_disable_hardware_hw_op( void ) esp_crypto_mpi_lock_release(); } +void esp_mpi_interrupt_enable( bool enable ) +{ + REG_WRITE(RSA_INTERRUPT_REG, enable); +} + +void esp_mpi_interrupt_clear( void ) +{ + REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); +} /* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. diff --git a/components/mbedtls/port/esp32s2/bignum.c b/components/mbedtls/port/esp32s2/bignum.c index 6b23e91098..419afa4e88 100644 --- a/components/mbedtls/port/esp32s2/bignum.c +++ b/components/mbedtls/port/esp32s2/bignum.c @@ -46,6 +46,8 @@ void esp_mpi_enable_hardware_hw_op( void ) while (DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) { } // Note: from enabling RSA clock to here takes about 1.3us + + REG_WRITE(RSA_INTERRUPT_REG, 0); } void esp_mpi_disable_hardware_hw_op( void ) @@ -58,6 +60,15 @@ void esp_mpi_disable_hardware_hw_op( void ) esp_crypto_mpi_lock_release(); } +void esp_mpi_interrupt_enable( bool enable ) +{ + REG_WRITE(RSA_INTERRUPT_REG, enable); +} + +void esp_mpi_interrupt_clear( void ) +{ + REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); +} /* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. diff --git a/components/mbedtls/port/esp32s3/bignum.c b/components/mbedtls/port/esp32s3/bignum.c index 09ec4b7d64..25bf552ac0 100644 --- a/components/mbedtls/port/esp32s3/bignum.c +++ b/components/mbedtls/port/esp32s3/bignum.c @@ -45,6 +45,7 @@ void esp_mpi_enable_hardware_hw_op( void ) } // Note: from enabling RSA clock to here takes about 1.3us + REG_WRITE(RSA_INTERRUPT_REG, 0); } @@ -56,6 +57,15 @@ void esp_mpi_disable_hardware_hw_op( void ) periph_module_disable(PERIPH_RSA_MODULE); } +void esp_mpi_interrupt_enable( bool enable ) +{ + REG_WRITE(RSA_INTERRUPT_REG, enable); +} + +void esp_mpi_interrupt_clear( void ) +{ + REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); +} /* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'. diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index d29967c145..6e03570494 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -27,13 +27,22 @@ #include #include #include -#include "soc/hwcrypto_periph.h" + #include "esp_system.h" #include "esp_log.h" #include "esp_attr.h" -#include "bignum_impl.h" +#include "esp_intr_alloc.h" +#include "esp_pm.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +#include "soc/hwcrypto_periph.h" +#include "soc/periph_defs.h" #include "soc/soc_caps.h" +#include "bignum_impl.h" + #include @@ -56,6 +65,77 @@ static const __attribute__((unused)) char *TAG = "bignum"; #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ +#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT) +static SemaphoreHandle_t op_complete_sem; +#if defined(CONFIG_PM_ENABLE) +static esp_pm_lock_handle_t s_pm_cpu_lock; +static esp_pm_lock_handle_t s_pm_sleep_lock; +#endif + +static IRAM_ATTR void esp_mpi_complete_isr(void *arg) +{ + BaseType_t higher_woken; + esp_mpi_interrupt_clear(); + + xSemaphoreGiveFromISR(op_complete_sem, &higher_woken); + if (higher_woken) { + portYIELD_FROM_ISR(); + } +} + + +static esp_err_t esp_mpi_isr_initialise(void) +{ + esp_mpi_interrupt_clear(); + esp_mpi_interrupt_enable(true); + if (op_complete_sem == NULL) { + op_complete_sem = xSemaphoreCreateBinary(); + + if (op_complete_sem == NULL) { + ESP_LOGE(TAG, "Failed to create intr semaphore"); + return ESP_FAIL; + } + + esp_intr_alloc(ETS_RSA_INTR_SOURCE, 0, esp_mpi_complete_isr, NULL, NULL); + } + + /* MPI is clocked proportionally to CPU clock, take power management lock */ +#ifdef CONFIG_PM_ENABLE + if (s_pm_cpu_lock == NULL) { + if (esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "mpi_sleep", &s_pm_sleep_lock) != ESP_OK) { + ESP_LOGE(TAG, "Failed to create PM sleep lock"); + return ESP_FAIL; + } + if (esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "mpi_cpu", &s_pm_cpu_lock) != ESP_OK) { + ESP_LOGE(TAG, "Failed to create PM CPU lock"); + return ESP_FAIL; + } + } + esp_pm_lock_acquire(s_pm_cpu_lock); + esp_pm_lock_acquire(s_pm_sleep_lock); +#endif + + return ESP_OK; +} + +static int esp_mpi_wait_intr(void) +{ + if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) { + ESP_LOGE("MPI", "Timed out waiting for completion of MPI Interrupt"); + return -1; + } + +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_cpu_lock); + esp_pm_lock_release(s_pm_sleep_lock); +#endif // CONFIG_PM_ENABLE + + esp_mpi_interrupt_enable(false); + + return 0; +} + +#endif // CONFIG_MBEDTLS_MPI_USE_INTERRUPT /* Convert bit count to word count */ @@ -327,12 +407,29 @@ static int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_ #else esp_mpi_enable_hardware_hw_op(); +#if defined (CONFIG_MBEDTLS_MPI_USE_INTERRUPT) + if (esp_mpi_isr_initialise() == ESP_FAIL) { + ret = -1; + esp_mpi_disable_hardware_hw_op(); + goto cleanup; + } +#endif + esp_mpi_exp_mpi_mod_hw_op(X, Y, M, Rinv, Mprime, num_words); ret = mbedtls_mpi_grow(Z, m_words); if (ret != 0) { esp_mpi_disable_hardware_hw_op(); goto cleanup; } + +#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT) + ret = esp_mpi_wait_intr(); + if (ret != 0) { + esp_mpi_disable_hardware_hw_op(); + goto cleanup; + } +#endif //CONFIG_MBEDTLS_MPI_USE_INTERRUPT + esp_mpi_read_result_hw_op(Z, m_words); esp_mpi_disable_hardware_hw_op(); #endif diff --git a/components/mbedtls/port/include/bignum_impl.h b/components/mbedtls/port/include/bignum_impl.h index 838a9d4af4..cb208ecb56 100644 --- a/components/mbedtls/port/include/bignum_impl.h +++ b/components/mbedtls/port/include/bignum_impl.h @@ -80,4 +80,17 @@ void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const #endif //ESP_MPI_USE_MONT_EXP +/** + * @brief Enable/disables MPI operation complete interrupt + * + * @param enable true: enable, false: disable + */ +void esp_mpi_interrupt_enable( bool enable ); + +/** + * @brief Clears the MPI operation complete interrupt status + * + */ +void esp_mpi_interrupt_clear( void ); + #endif diff --git a/tools/unit-test-app/configs/aes_no_hw b/tools/unit-test-app/configs/aes_no_hw index ed9e43572c..e3e81f40f2 100644 --- a/tools/unit-test-app/configs/aes_no_hw +++ b/tools/unit-test-app/configs/aes_no_hw @@ -2,3 +2,4 @@ TEST_EXCLUDE_COMPONENTS=bt app_update test_utils TEST_COMPONENTS=mbedtls CONFIG_MBEDTLS_HARDWARE_AES=n +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y From ba3f12a9fe8fdb048b3eb8ed6d14f7b3c6881a77 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Tue, 4 Jan 2022 16:43:46 +0800 Subject: [PATCH 2/2] rsa: add generate RSA keys test case --- components/mbedtls/Kconfig | 2 +- components/mbedtls/test/test_rsa.c | 41 ++++++++++++++++++++++++++- tools/unit-test-app/configs/aes_no_hw | 2 +- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index ff71da1e57..1b62d5322a 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -285,7 +285,7 @@ menu "mbedTLS" config MBEDTLS_MPI_USE_INTERRUPT bool "Use interrupt for MPI exp-mod operations" depends on !IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_MPI - default n + default y help Use an interrupt to coordinate long MPI operations. diff --git a/components/mbedtls/test/test_rsa.c b/components/mbedtls/test/test_rsa.c index 1f57a37c4d..ef9a1c21ab 100644 --- a/components/mbedtls/test/test_rsa.c +++ b/components/mbedtls/test/test_rsa.c @@ -6,11 +6,14 @@ */ #include #include -#include +#include "esp_system.h" +#include "esp_task_wdt.h" #include "mbedtls/rsa.h" #include "mbedtls/pk.h" #include "mbedtls/x509_crt.h" #include "mbedtls/entropy_poll.h" +#include +#include #include "freertos/FreeRTOS.h" #include "unity.h" #include "test_utils.h" @@ -518,3 +521,39 @@ static void rsa_key_operations(int keysize, bool check_performance, bool use_bli } #endif // CONFIG_MBEDTLS_HARDWARE_MPI + +TEST_CASE("mbedtls RSA Generate Key", "[mbedtls][timeout=60]") +{ + + mbedtls_rsa_context ctx; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + const unsigned int key_size = 3072; + const int exponent = 65537; + +#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT + /* Check that generating keys doesnt starve the watchdog if interrupt-based driver is used */ + const int timeout_s = 1; + esp_task_wdt_init(timeout_s, true); + esp_task_wdt_add(xTaskGetIdleTaskHandleForCPU(0)); +#endif //CONFIG_MBEDTLS_MPI_USE_INTERRUPT + + mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V15, 0); + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_entropy_init(&entropy); + TEST_ASSERT_FALSE( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) ); + + TEST_ASSERT_FALSE( mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, key_size, exponent) ); + + mbedtls_rsa_free(&ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + +#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT + esp_task_wdt_delete(xTaskGetIdleTaskHandleForCPU(0)); + esp_task_wdt_deinit(); +#endif //CONFIG_MBEDTLS_MPI_USE_INTERRUPT + +} diff --git a/tools/unit-test-app/configs/aes_no_hw b/tools/unit-test-app/configs/aes_no_hw index e3e81f40f2..b9c75414e8 100644 --- a/tools/unit-test-app/configs/aes_no_hw +++ b/tools/unit-test-app/configs/aes_no_hw @@ -2,4 +2,4 @@ TEST_EXCLUDE_COMPONENTS=bt app_update test_utils TEST_COMPONENTS=mbedtls CONFIG_MBEDTLS_HARDWARE_AES=n -CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=n