forked from espressif/esp-idf
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
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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'.
|
||||
|
||||
|
@@ -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'.
|
||||
|
||||
|
@@ -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'.
|
||||
|
||||
|
@@ -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'.
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user