Jelajahi Sumber

Merge branch 'feature/rsa_intr' into 'master'

MPI: add kconfig option for doing intr-based exp-mod operations

Closes IDF-4389

See merge request espressif/esp-idf!16558
Mahavir Jain 4 tahun lalu
induk
melakukan
397639da7d

+ 10 - 0
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 y
+        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

+ 10 - 0
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

+ 11 - 0
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'.
 

+ 11 - 0
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'.
 

+ 11 - 0
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'.
 

+ 10 - 0
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'.
 

+ 99 - 2
components/mbedtls/port/esp_bignum.c

@@ -27,13 +27,22 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <sys/param.h>
-#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 <mbedtls/bignum.h>
 
 
@@ -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

+ 13 - 0
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

+ 40 - 1
components/mbedtls/test/test_rsa.c

@@ -6,11 +6,14 @@
 */
 #include <string.h>
 #include <stdbool.h>
-#include <esp_system.h>
+#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 <mbedtls/entropy.h>
+#include <mbedtls/ctr_drbg.h>
 #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
+
+}

+ 1 - 0
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=n