From 2561b68af8ebc9949ad35887e9d1f0f5419022aa Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 22 Nov 2016 18:09:32 +1100 Subject: [PATCH] hwcrypto: Fixes for disabling one hardware unit causing reset of a different unit ROM functions reset related units, but this can have problems in a multithreaded environment. --- components/esp32/hwcrypto/aes.c | 18 ++++++++++++++---- components/esp32/hwcrypto/sha.c | 15 ++++++++++++--- components/esp32/include/soc/dport_reg.h | 10 ++++++++++ components/esp32/include/soc/hwcrypto_reg.h | 2 +- components/mbedtls/port/esp_bignum.c | 20 ++++++++++++++++++-- 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 169465822..8f27cd17c 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -28,6 +28,7 @@ #include #include "hwcrypto/aes.h" #include "rom/aes.h" +#include "soc/dport_reg.h" #include static _lock_t aes_lock; @@ -36,14 +37,23 @@ void esp_aes_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&aes_lock); - ets_aes_enable(); + /* Enable AES hardware */ + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); + /* Clear reset on digital signature & secure boot units, + otherwise AES unit is held in reset also. */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_AES + | DPORT_PERI_EN_DIGITAL_SIGNATURE + | DPORT_PERI_EN_SECUREBOOT); } void esp_aes_release_hardware( void ) { - uint8_t zero[256/8] = { 0 }; - ets_aes_setkey_enc(zero, AES256); - ets_aes_disable(); + /* Disable AES hardware */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES); + /* Don't return other units to reset, as this pulls + reset on RSA & SHA units, respectively. */ + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); _lock_release(&aes_lock); } diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c index d58bda7f2..fd8075fc7 100644 --- a/components/esp32/hwcrypto/sha.c +++ b/components/esp32/hwcrypto/sha.c @@ -143,15 +143,21 @@ bool esp_sha_try_lock_engine(esp_sha_type sha_type) _lock_acquire(&state_change_lock); - assert( !engine->in_use && "in_use flag should be cleared" ); - if (sha_engines_all_idle()) { + /* Enable SHA hardware */ + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + /* also clear reset on secure boot, otherwise SHA is held in reset */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_SHA + | DPORT_PERI_EN_SECUREBOOT); ets_sha_enable(); } _lock_release(&state_change_lock); + assert( !engine->in_use && "in_use flag should be cleared" ); engine->in_use = true; + return true; } @@ -165,7 +171,10 @@ void esp_sha_unlock_engine(esp_sha_type sha_type) engine->in_use = false; if (sha_engines_all_idle()) { - ets_sha_disable(); + /* Disable SHA hardware */ + /* Don't assert reset on secure boot, otherwise AES is held in reset */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); } _lock_release(&state_change_lock); diff --git a/components/esp32/include/soc/dport_reg.h b/components/esp32/include/soc/dport_reg.h index 1be0fdee1..f84346717 100644 --- a/components/esp32/include/soc/dport_reg.h +++ b/components/esp32/include/soc/dport_reg.h @@ -94,6 +94,16 @@ #define DPORT_PERI_RST_EN_V 0xFFFFFFFF #define DPORT_PERI_RST_EN_S 0 +/* The following bits apply to DPORT_PERI_CLK_EN_REG, DPORT_PERI_RST_EN_REG + */ +#define DPORT_PERI_EN_AES (1<<0) +#define DPORT_PERI_EN_SHA (1<<1) +#define DPORT_PERI_EN_RSA (1<<2) +/* NB: Secure boot reset will hold SHA & AES in reset */ +#define DPORT_PERI_EN_SECUREBOOT (1<<3) +/* NB: Digital signature reset will hold AES & RSA in reset */ +#define DPORT_PERI_EN_DIGITAL_SIGNATURE (1<<4) + #define DPORT_WIFI_BB_CFG_REG (DR_REG_DPORT_BASE + 0x024) /* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ /*description: */ diff --git a/components/esp32/include/soc/hwcrypto_reg.h b/components/esp32/include/soc/hwcrypto_reg.h index c187117af..10e80d935 100644 --- a/components/esp32/include/soc/hwcrypto_reg.h +++ b/components/esp32/include/soc/hwcrypto_reg.h @@ -30,7 +30,7 @@ #define RSA_MULT_MODE_REG (DR_REG_RSA_BASE + 0x80c) #define RSA_MULT_START_REG (DR_REG_RSA_BASE + 0x810) -#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0X814) +#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0x814) #define RSA_CLEAN_REG (DR_REG_RSA_BASE + 0x818) diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index 7570820e3..6c214b741 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -33,6 +33,8 @@ #include "esp_intr.h" #include "esp_attr.h" +#include "soc/dport_reg.h" + #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" @@ -71,7 +73,16 @@ void esp_mpi_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&mpi_lock); - ets_bigint_enable(); + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + /* also clear reset on digital signature, otherwise RSA is held in reset */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_RSA + | DPORT_PERI_EN_DIGITAL_SIGNATURE); + + REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + while(REG_READ(RSA_CLEAN_REG) != 1); + #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT rsa_isr_initialise(); #endif @@ -79,7 +90,12 @@ void esp_mpi_acquire_hardware( void ) void esp_mpi_release_hardware( void ) { - ets_bigint_disable(); + REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + /* don't reset digital signature unit, as this resets AES also */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + _lock_release(&mpi_lock); }