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

This commit is contained in:
Marius Vikhammer 2021-12-28 12:04:05 +08:00
parent e8cfba0745
commit a9a7160cb6
9 changed files with 176 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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'.

View File

@ -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'.

View File

@ -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'.

View File

@ -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'.

View File

@ -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

View File

@ -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

View File

@ -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