From 08287852abf7430b3fe4ca07199ff70ccc3fb15c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 27 Jun 2017 20:28:32 +0800 Subject: [PATCH 01/12] esp32: add protection for DPORT registers of RSA --- components/mbedtls/port/esp_bignum.c | 38 ++++++++++++++------------ components/soc/esp32/include/soc/soc.h | 2 +- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index 2c82a825f..9eb409ba0 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -52,7 +52,7 @@ static SemaphoreHandle_t op_complete_sem; static IRAM_ATTR void rsa_complete_isr(void *arg) { BaseType_t higher_woken; - REG_WRITE(RSA_INTERRUPT_REG, 1); + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); xSemaphoreGiveFromISR(op_complete_sem, &higher_woken); if (higher_woken) { portYIELD_FROM_ISR(); @@ -84,7 +84,7 @@ void esp_mpi_acquire_hardware( void ) DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); - while(REG_READ(RSA_CLEAN_REG) != 1); + while(DPORT_REG_READ(RSA_CLEAN_REG) != 1); // Note: from enabling RSA clock to here takes about 1.3us @@ -167,7 +167,9 @@ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_wo MBEDTLS_MPI_CHK( mbedtls_mpi_grow(x, num_words) ); /* Copy data from memory block registers */ - memcpy(x->p, (uint32_t *)mem_base, num_words * 4); + for (size_t i = 0; i < num_words; ++i) { + x->p[i] = DPORT_REG_READ(mem_base + i * 4); + } /* Zero any remaining limbs in the bignum, if the buffer is bigger than num_words */ @@ -242,17 +244,17 @@ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words static inline void execute_op(uint32_t op_reg) { /* Clear interrupt status */ - REG_WRITE(RSA_INTERRUPT_REG, 1); + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); /* Note: above REG_WRITE includes a memw, so we know any writes to the memory blocks are also complete. */ - REG_WRITE(op_reg, 1); + DPORT_REG_WRITE(op_reg, 1); #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) { ESP_LOGE(TAG, "Timed out waiting for RSA operation (op_reg 0x%x int_reg 0x%x)", - op_reg, REG_READ(RSA_INTERRUPT_REG)); + op_reg, DPORT_REG_READ(RSA_INTERRUPT_REG)); abort(); /* indicates a fundamental problem with driver */ } #else @@ -261,7 +263,7 @@ static inline void execute_op(uint32_t op_reg) #endif /* clear the interrupt */ - REG_WRITE(RSA_INTERRUPT_REG, 1); + DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); } /* Sub-stages of modulo multiplication/exponentiation operations */ @@ -289,10 +291,10 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words); - REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); + DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ - REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); /* Execute first stage montgomery multiplication */ execute_op(RSA_MULT_START_REG); @@ -365,14 +367,14 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi esp_mpi_acquire_hardware(); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ - REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1); + DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1); /* Load M, X, Rinv, M-prime (M-prime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words); mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words); - REG_WRITE(RSA_M_DASH_REG, Mprime); + DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime); execute_op(RSA_START_MODEXP_REG); @@ -502,12 +504,12 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware(). */ - REG_WRITE(RSA_M_DASH_REG, 0); + DPORT_REG_WRITE(RSA_M_DASH_REG, 0); /* "mode" register loaded with number of 512-bit blocks in result, plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8)) */ - REG_WRITE(RSA_MULT_MODE_REG, (words_z / 16) + 7); + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (words_z / 16) + 7); execute_op(RSA_MULT_START_REG); @@ -547,21 +549,21 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, /* M = 2^num_words - 1, so block is entirely FF */ for(int i = 0; i < num_words; i++) { - REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX); + DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX); } /* Mprime = 1 */ - REG_WRITE(RSA_M_DASH_REG, 1); + DPORT_REG_WRITE(RSA_M_DASH_REG, 1); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ - REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); + DPORT_REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); /* Load X */ mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); /* Rinv = 1 */ - REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1); + DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1); for(int i = 1; i < num_words; i++) { - REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0); + DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0); } execute_op(RSA_MULT_START_REG); diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index 3b1e85f2f..b758f559e 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -69,9 +69,9 @@ #define SOC_RTC_DATA_HIGH 0x50002000 #define DR_REG_DPORT_BASE 0x3ff00000 -#define DR_REG_DPORT_END 0x3ff00FFC #define DR_REG_RSA_BASE 0x3ff02000 #define DR_REG_SHA_BASE 0x3ff03000 +#define DR_REG_DPORT_END 0x3ff03FFC #define DR_REG_UART_BASE 0x3ff40000 #define DR_REG_SPI1_BASE 0x3ff42000 #define DR_REG_SPI0_BASE 0x3ff43000 From dc8c33892e0082822c4c69afa201c02d9758a1c0 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Aug 2017 11:23:35 +1000 Subject: [PATCH 02/12] dport access: Fix nested calls to DPORT_STALL_OTHER_CPU_START() --- components/esp32/dport_access.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 49e6032d2..e1923b412 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -79,11 +79,12 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void) #ifdef DPORT_ACCESS_BENCHMARK ccount_start[cpu_id] = XTHAL_GET_CCOUNT(); #endif - BaseType_t intLvl=portENTER_CRITICAL_NESTED(); - oldInterruptLevel[cpu_id]=intLvl; + BaseType_t intLvl = portENTER_CRITICAL_NESTED(); if (dport_access_ref[cpu_id] == 0) { - portENTER_CRITICAL_ISR(&g_dport_mux); + portENTER_CRITICAL_ISR(&g_dport_mux); + + oldInterruptLevel[cpu_id]=intLvl; dport_access_start[cpu_id] = 0; dport_access_end[cpu_id] = 0; @@ -100,6 +101,11 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void) } dport_access_ref[cpu_id]++; + + if (dport_access_ref[cpu_id] > 1) { + /* Interrupts are already disabled by the parent, we're nested here. */ + portEXIT_CRITICAL_NESTED(intLvl); + } #endif /* CONFIG_FREERTOS_UNICORE */ } @@ -124,9 +130,9 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void) dport_access_end[cpu_id] = 1; portEXIT_CRITICAL_ISR(&g_dport_mux); + + portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]); } - - portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]); #ifdef DPORT_ACCESS_BENCHMARK ccount_end[cpu_id] = XTHAL_GET_CCOUNT(); From cb31222e8b83049257d4349b845e443b40b4ba6a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 Aug 2017 14:16:21 +1000 Subject: [PATCH 03/12] dport access: Add _DPORT_REG_SET_BIT & _DPORT_REG_CLR_BIT --- components/esp32/include/esp_dport_access.h | 2 ++ .../soc/esp32/include/soc/dport_access.h | 21 +++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 8b081c5ae..d66b119bc 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #ifndef _ESP_DPORT_ACCESS_H_ #define _ESP_DPORT_ACCESS_H_ diff --git a/components/soc/esp32/include/soc/dport_access.h b/components/soc/esp32/include/soc/dport_access.h index d1d264cbc..817ac98e7 100644 --- a/components/soc/esp32/include/soc/dport_access.h +++ b/components/soc/esp32/include/soc/dport_access.h @@ -25,14 +25,21 @@ extern "C" { //Registers Operation {{ -//Register read macros with an underscore prefix access DPORT memory directly. In IDF apps, use the non-underscore versions to be SMP-safe. +// The _DPORT_xxx register read macros access DPORT memory directly (as opposed to +// DPORT_REG_READ which applies SMP-safe protections). +// +// Use DPORT_REG_READ versions to be SMP-safe in IDF apps. If you want to +// make a sequence of DPORT reads, use DPORT_STALL_OTHER_CPU_START() macro +// explicitly and then use _DPORT_REG_READ macro while other CPU is stalled. +// +// _DPORT_REG_WRITE & DPORT_REG_WRITE are equivalent. #define _DPORT_REG_READ(_r) (*(volatile uint32_t *)(_r)) #define _DPORT_REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) -//write value to register +// Write value to DPORT register (does not require protecting) #define DPORT_REG_WRITE(_r, _v) _DPORT_REG_WRITE((_r), (_v)) -//read value from register +// Read value from register, SMP-safe version. static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) { uint32_t val; @@ -40,7 +47,7 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) DPORT_STALL_OTHER_CPU_START(); val = _DPORT_REG_READ(reg); DPORT_STALL_OTHER_CPU_END(); - + return val; } @@ -81,8 +88,10 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) #define DPORT_FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f)) //Register read macros with an underscore prefix access DPORT memory directly. In IDF apps, use the non-underscore versions to be SMP-safe. -#define _DPORT_READ_PERI_REG(addr) (*((volatile uint32_t *)(addr))) -#define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val) +#define _DPORT_READ_PERI_REG(addr) (*((volatile uint32_t *)(addr))) +#define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val) +#define _DPORT_REG_SET_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r)|(_b))) +#define _DPORT_REG_CLR_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r) & (~(_b)))) //read value from register static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t addr) From 7be002ec0f76f0128058cd7d83fc6a4f5951cad1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Aug 2017 12:09:40 +1000 Subject: [PATCH 04/12] hwcrypto bignum/MPI: Batch safe DPORT reads to improve performance --- components/mbedtls/port/esp_bignum.c | 107 +++++++++++++++++++-------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index 9eb409ba0..a9faa2670 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -76,16 +76,19 @@ void esp_mpi_acquire_hardware( void ) /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&mpi_lock); - DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); - /* also clear reset on digital signature, otherwise RSA is held in reset */ - DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_RSA - | DPORT_PERI_EN_DIGITAL_SIGNATURE); + DPORT_STALL_OTHER_CPU_START(); + { + _DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + /* also clear reset on digital signature, otherwise RSA is held in reset */ + _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_RSA + | DPORT_PERI_EN_DIGITAL_SIGNATURE); - DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + _DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + } + DPORT_STALL_OTHER_CPU_END(); while(DPORT_REG_READ(RSA_CLEAN_REG) != 1); - // Note: from enabling RSA clock to here takes about 1.3us #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT @@ -95,11 +98,15 @@ void esp_mpi_acquire_hardware( void ) void esp_mpi_release_hardware( void ) { - DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + DPORT_STALL_OTHER_CPU_START(); + { + _DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); - /* don't reset digital signature unit, as this resets AES also */ - DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); - DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + /* don't reset digital signature unit, as this resets AES also */ + _DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); + _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + } + DPORT_STALL_OTHER_CPU_END(); _lock_release(&mpi_lock); } @@ -139,6 +146,9 @@ static inline size_t bits_to_hardware_words(size_t num_bits) If num_words is higher than the number of words in the bignum then these additional words will be zeroed in the memory buffer. + + As this function only writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START() + is required. */ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words) { @@ -146,10 +156,14 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s uint32_t copy_words = num_words < mpi->n ? num_words : mpi->n; /* Copy MPI data to memory block registers */ - memcpy(pbase, mpi->p, copy_words * 4); + for (int i = 0; i < copy_words; i++) { + pbase[i] = mpi->p[i]; + } /* Zero any remaining memory block data */ - bzero(pbase + copy_words, (num_words - copy_words) * 4); + for (int i = copy_words; i < num_words; i++) { + pbase[i] = 0; + } /* Note: not executing memw here, can do it before we start a bignum operation */ } @@ -159,6 +173,8 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s Reads num_words words from block. Can return a failure result if fails to grow the MPI result. + + Cannot be called inside DPORT_STALL_OTHER_CPU_START() (as may allocate memory). */ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words) { @@ -167,9 +183,13 @@ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_wo MBEDTLS_MPI_CHK( mbedtls_mpi_grow(x, num_words) ); /* Copy data from memory block registers */ - for (size_t i = 0; i < num_words; ++i) { - x->p[i] = DPORT_REG_READ(mem_base + i * 4); + DPORT_STALL_OTHER_CPU_START(); + { + for (size_t i = 0; i < num_words; ++i) { + x->p[i] = _DPORT_REG_READ(mem_base + i * 4); + } } + DPORT_STALL_OTHER_CPU_END(); /* Zero any remaining limbs in the bignum, if the buffer is bigger than num_words */ @@ -238,10 +258,13 @@ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words } -/* Execute RSA operation. op_reg specifies which 'START' register +/* Begin an RSA operation. op_reg specifies which 'START' register to write to. + + Because the only DPORT operations here are writes, + does not need protecting via DPORT_STALL_OTHER_CPU_START(); */ -static inline void execute_op(uint32_t op_reg) +static inline void start_op(uint32_t op_reg) { /* Clear interrupt status */ DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); @@ -250,7 +273,15 @@ static inline void execute_op(uint32_t op_reg) to the memory blocks are also complete. */ DPORT_REG_WRITE(op_reg, 1); +} +/* Wait for an RSA operation to complete. + + This should NOT be called inside a DPORT_STALL_OTHER_CPU_START(), as it will stall the other CPU for an unacceptably long + period (and - depending on config - may require interrupts enabled). +*/ +static inline void wait_op_complete(uint32_t op_reg) +{ #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) { ESP_LOGE(TAG, "Timed out waiting for RSA operation (op_reg 0x%x int_reg 0x%x)", @@ -258,12 +289,13 @@ static inline void execute_op(uint32_t op_reg) abort(); /* indicates a fundamental problem with driver */ } #else - while(REG_READ(RSA_INTERRUPT_REG) != 1) + while(DPORT_REG_READ(RSA_INTERRUPT_REG) != 1) { } -#endif /* clear the interrupt */ DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1); +#endif + } /* Sub-stages of modulo multiplication/exponentiation operations */ @@ -287,6 +319,8 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi esp_mpi_acquire_hardware(); + /* (As the following are all writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START is required.) */ + /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); @@ -297,10 +331,12 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi DPORT_REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); /* Execute first stage montgomery multiplication */ - execute_op(RSA_MULT_START_REG); + start_op(RSA_MULT_START_REG); + + wait_op_complete(RSA_MULT_START_REG); /* execute second stage */ - MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) ); + ret = modular_multiply_finish(Z, X, Y, num_words); esp_mpi_release_hardware(); @@ -366,6 +402,8 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi esp_mpi_acquire_hardware(); + /* (As the following are all writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START is required.) */ + /* "mode" register loaded with number of 512-bit blocks, minus 1 */ DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1); @@ -376,10 +414,11 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words); DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime); - execute_op(RSA_START_MODEXP_REG); + start_op(RSA_START_MODEXP_REG); + + wait_op_complete(RSA_START_MODEXP_REG); ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words); - esp_mpi_release_hardware(); cleanup: @@ -407,11 +446,14 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi */ static int modular_multiply_finish(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words) { - int ret; + int ret = 0; + /* Load Y to X input memory block, rerun */ mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, num_words); - execute_op(RSA_MULT_START_REG); + start_op(RSA_MULT_START_REG); + + wait_op_complete(RSA_MULT_START_REG); /* Read result into Z */ ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words); @@ -429,7 +471,7 @@ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbe /* Z = X * Y */ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y ) { - int ret; + int ret = 0; size_t bits_x, bits_y, words_x, words_y, words_mult, words_z; /* Count words needed for X & Y in hardware */ @@ -511,7 +553,9 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi */ DPORT_REG_WRITE(RSA_MULT_MODE_REG, (words_z / 16) + 7); - execute_op(RSA_MULT_START_REG); + start_op(RSA_MULT_START_REG); + + wait_op_complete(RSA_MULT_START_REG); /* Read back the result */ ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, words_z); @@ -566,14 +610,15 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0); } - execute_op(RSA_MULT_START_REG); + start_op(RSA_MULT_START_REG); + + wait_op_complete(RSA_MULT_START_REG); /* finish the modular multiplication */ - MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) ); + ret = modular_multiply_finish(Z, X, Y, num_words); esp_mpi_release_hardware(); - cleanup: return ret; } @@ -596,7 +641,7 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, */ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t bits_y, size_t words_result) { - int ret; + int ret = 0; mbedtls_mpi Ztemp; const size_t limbs_y = (bits_y + biL - 1) / biL; /* Rather than slicing in two on bits we slice on limbs (32 bit words) */ From d0c300c52d32bfd970bf5ecc3dc04c3e23b42ad1 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Aug 2017 12:15:37 +1000 Subject: [PATCH 05/12] hwcrypto: SHA acceleration using safe DPORT reads --- components/esp32/hwcrypto/sha.c | 86 +++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c index c9c8d33ee..0c0c8ddb5 100644 --- a/components/esp32/hwcrypto/sha.c +++ b/components/esp32/hwcrypto/sha.c @@ -159,13 +159,17 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine) _lock_acquire(&state_change_lock); if (sha_engines_all_idle()) { - /* Enable SHA hardware */ - DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); - /* also clear reset on secure boot, otherwise SHA is held in reset */ - DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_SHA - | DPORT_PERI_EN_SECUREBOOT); - ets_sha_enable(); + DPORT_STALL_OTHER_CPU_START(); + { + /* Enable SHA hardware */ + _DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + /* also clear reset on secure boot, otherwise SHA is held in reset */ + _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_SHA + | DPORT_PERI_EN_SECUREBOOT); + ets_sha_enable(); + } + DPORT_STALL_OTHER_CPU_END(); } _lock_release(&state_change_lock); @@ -187,8 +191,12 @@ void esp_sha_unlock_engine(esp_sha_type sha_type) if (sha_engines_all_idle()) { /* Disable SHA hardware */ /* Don't assert reset on secure boot, otherwise AES is held in reset */ - DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); - DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + DPORT_STALL_OTHER_CPU_START(); + { + _DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); + _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + } + DPORT_STALL_OTHER_CPU_END(); } _lock_release(&state_change_lock); @@ -198,10 +206,16 @@ void esp_sha_unlock_engine(esp_sha_type sha_type) void esp_sha_wait_idle(void) { - while(REG_READ(SHA_1_BUSY_REG) == 1) {} - while(REG_READ(SHA_256_BUSY_REG) == 1) {} - while(REG_READ(SHA_384_BUSY_REG) == 1) {} - while(REG_READ(SHA_512_BUSY_REG) == 1) {} + DPORT_STALL_OTHER_CPU_START(); + while(1) { + if(_DPORT_REG_READ(SHA_1_BUSY_REG) == 0 + && _DPORT_REG_READ(SHA_256_BUSY_REG) == 0 + && _DPORT_REG_READ(SHA_384_BUSY_REG) == 0 + && _DPORT_REG_READ(SHA_512_BUSY_REG) == 0) { + break; + } + } + DPORT_STALL_OTHER_CPU_END(); } void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) @@ -211,23 +225,26 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) esp_sha_lock_memory_block(); - esp_sha_wait_idle(); + DPORT_STALL_OTHER_CPU_START(); // This block reads from DPORT memory (reg_addr_buf) + { + esp_sha_wait_idle(); - REG_WRITE(SHA_LOAD_REG(sha_type), 1); - while(REG_READ(SHA_BUSY_REG(sha_type)) == 1) { } + _DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1); + while(_DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { } - uint32_t *digest_state_words = (uint32_t *)digest_state; - uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); - if(sha_type == SHA2_384 || sha_type == SHA2_512) { - /* for these ciphers using 64-bit states, swap each pair of words */ - for(int i = 0; i < sha_length(sha_type)/4; i += 2) { - digest_state_words[i+1] = reg_addr_buf[i]; - digest_state_words[i]= reg_addr_buf[i+1]; + uint32_t *digest_state_words = (uint32_t *)digest_state; + uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); + if(sha_type == SHA2_384 || sha_type == SHA2_512) { + /* for these ciphers using 64-bit states, swap each pair of words */ + for(int i = 0; i < sha_length(sha_type)/4; i += 2) { + digest_state_words[i+1] = reg_addr_buf[i]; + digest_state_words[i]= reg_addr_buf[i+1]; + } + } else { + memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type)); } - } else { - memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type)); } - asm volatile ("memw"); + DPORT_STALL_OTHER_CPU_END(); esp_sha_unlock_memory_block(); } @@ -250,9 +267,9 @@ void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_ asm volatile ("memw"); if(is_first_block) { - REG_WRITE(SHA_START_REG(sha_type), 1); + DPORT_REG_WRITE(SHA_START_REG(sha_type), 1); } else { - REG_WRITE(SHA_CONTINUE_REG(sha_type), 1); + DPORT_REG_WRITE(SHA_CONTINUE_REG(sha_type), 1); } esp_sha_unlock_memory_block(); @@ -275,14 +292,23 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns size_t chunk_len = (ilen > block_len) ? block_len : ilen; esp_sha_lock_memory_block(); esp_sha_wait_idle(); - ets_sha_update(&ctx, sha_type, input, chunk_len * 8); + DPORT_STALL_OTHER_CPU_START(); + { + // This SHA ROM function reads DPORT regs + ets_sha_update(&ctx, sha_type, input, chunk_len * 8); + } + DPORT_STALL_OTHER_CPU_END(); esp_sha_unlock_memory_block(); input += chunk_len; ilen -= chunk_len; } esp_sha_lock_memory_block(); esp_sha_wait_idle(); - ets_sha_finish(&ctx, sha_type, output); + DPORT_STALL_OTHER_CPU_START(); + { + ets_sha_finish(&ctx, sha_type, output); + } + DPORT_STALL_OTHER_CPU_END(); esp_sha_unlock_memory_block(); esp_sha_unlock_engine(sha_type); From 99c663a6e9b6195d8fefa611ac81168bcd6b8e82 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Aug 2017 16:45:40 +1000 Subject: [PATCH 06/12] mbedtls tests: utility tests for APB corruption Used when running mbedTLS self-tests to verify DPORT protection is working correctly. --- .../mbedtls/test/test_apb_dport_access.c | 55 +++++++++++++++++++ .../mbedtls/test/test_apb_dport_access.h | 18 ++++++ components/mbedtls/test/test_mbedtls.c | 7 +++ components/mbedtls/test/test_mbedtls_sha.c | 3 + 4 files changed, 83 insertions(+) create mode 100644 components/mbedtls/test/test_apb_dport_access.c create mode 100644 components/mbedtls/test/test_apb_dport_access.h diff --git a/components/mbedtls/test/test_apb_dport_access.c b/components/mbedtls/test/test_apb_dport_access.c new file mode 100644 index 000000000..54e518bc1 --- /dev/null +++ b/components/mbedtls/test/test_apb_dport_access.c @@ -0,0 +1,55 @@ +/* Implementation of utility functions to verify + unit tests aren't performing SMP-unsafe DPORT reads. +*/ + +#include "unity.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/uart_reg.h" +#include "test_apb_dport_access.h" + +#ifndef CONFIG_FREERTOS_UNICORE + +static void apb_access_loop_task(void *ignore); + +static volatile bool apb_access_corrupt; +static TaskHandle_t apb_task_handle; + +void start_apb_access_loop() +{ + apb_access_corrupt = false; + xTaskCreatePinnedToCore(apb_access_loop_task, "accessAPB", 2048, NULL, + UNITY_FREERTOS_PRIORITY - 1, + &apb_task_handle, !UNITY_FREERTOS_CPU); +} + +void verify_apb_access_loop() +{ + vTaskDelete(apb_task_handle); + apb_task_handle = NULL; + TEST_ASSERT_FALSE(apb_access_corrupt); + printf("Verified no APB corruption from operations\n"); +} + +static void apb_access_loop_task(void *ignore) +{ + uint32_t initial = REG_READ(UART_DATE_REG(0)); + while(1) { + if (REG_READ(UART_DATE_REG(0)) != initial) { + apb_access_corrupt = true; + } + } +} + +#else /*CONFIG_FREERTOS_UNICORE */ + +void start_apb_access_loop() +{ +} + +void verify_apb_access_loop() +{ +} + +#endif diff --git a/components/mbedtls/test/test_apb_dport_access.h b/components/mbedtls/test/test_apb_dport_access.h new file mode 100644 index 000000000..a974c2d42 --- /dev/null +++ b/components/mbedtls/test/test_apb_dport_access.h @@ -0,0 +1,18 @@ +/* Utility functions to test that APB access is still safe + while the other CPU performs some set of DPORT accesses + + (see ECO 3.10 and the standalone esp32 test_dport.c for more). +*/ + +/* start_apb_access_loop() starts a task reading from APB in a loop on the non-Unity-test CPU. + + Call this before doing something which involes DPORT reads. + + Does nothing in unicore mode. +*/ +void start_apb_access_loop(); + +/* verify_apb_access_loop() kills the task started by start_apb_access_loop() + and verifies that none of the APB reads were corrupted by unsafe DPORT reads. +*/ +void verify_apb_access_loop(); diff --git a/components/mbedtls/test/test_mbedtls.c b/components/mbedtls/test/test_mbedtls.c index acde6e9dd..9dc1b6649 100644 --- a/components/mbedtls/test/test_mbedtls.c +++ b/components/mbedtls/test/test_mbedtls.c @@ -20,19 +20,26 @@ #include "freertos/semphr.h" #include "unity.h" #include "sdkconfig.h" +#include "test_apb_dport_access.h" TEST_CASE("mbedtls AES self-tests", "[aes]") { + start_apb_access_loop(); TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass."); + verify_apb_access_loop(); } TEST_CASE("mbedtls MPI self-tests", "[bignum]") { + start_apb_access_loop(); TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass."); + verify_apb_access_loop(); } TEST_CASE("mbedtls RSA self-tests", "[bignum]") { + start_apb_access_loop(); TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass."); + verify_apb_access_loop(); } diff --git a/components/mbedtls/test/test_mbedtls_sha.c b/components/mbedtls/test/test_mbedtls_sha.c index e62769a60..e31eec9bb 100644 --- a/components/mbedtls/test/test_mbedtls_sha.c +++ b/components/mbedtls/test/test_mbedtls_sha.c @@ -13,13 +13,16 @@ #include "freertos/semphr.h" #include "unity.h" #include "sdkconfig.h" +#include "test_apb_dport_access.h" TEST_CASE("mbedtls SHA self-tests", "[mbedtls]") { + start_apb_access_loop(); TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass."); TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha256_self_test(1), "SHA256 self-tests should pass."); TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass."); TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass."); + verify_apb_access_loop(); } static const unsigned char *one_hundred_as = (unsigned char *) From e256fb6d9606b1914b24503aa19b847e1006bcf7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 Aug 2017 16:45:55 +1000 Subject: [PATCH 07/12] hwcrypto: Use DPORT-safe accesses with AES --- components/esp32/hwcrypto/aes.c | 75 +++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 4b6b220cf..e1acf536f 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -37,23 +37,33 @@ void esp_aes_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&aes_lock); - /* Enable AES hardware */ - DPORT_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. */ - DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_AES - | DPORT_PERI_EN_DIGITAL_SIGNATURE - | DPORT_PERI_EN_SECUREBOOT); + + DPORT_STALL_OTHER_CPU_START(); + { + /* Enable AES hardware */ + _DPORT_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. */ + _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_AES + | DPORT_PERI_EN_DIGITAL_SIGNATURE + | DPORT_PERI_EN_SECUREBOOT); + } + DPORT_STALL_OTHER_CPU_END(); } void esp_aes_release_hardware( void ) { - /* Disable AES hardware */ - DPORT_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. */ - DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); + DPORT_STALL_OTHER_CPU_START(); + { + /* Disable AES hardware */ + _DPORT_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. */ + _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); + } + DPORT_STALL_OTHER_CPU_END(); + _lock_release(&aes_lock); } @@ -131,14 +141,25 @@ int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, */ static inline int esp_aes_setkey_hardware( esp_aes_context *ctx, int mode) { - if ( mode == ESP_AES_ENCRYPT ) { - ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits); - } else { - ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits); + DPORT_ACCESS_BLOCK() { + // ROM AES functions access DPORT, so need to be protected as such + if ( mode == ESP_AES_ENCRYPT ) { + ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits); + } else { + ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits); + } } return 0; } +static inline void esp_aes_block(const uint8_t input[16], uint8_t output[16]) +{ + DPORT_ACCESS_BLOCK() { + // ROM AES functions access DPORT, so need to be protected as such + ets_aes_crypt(input, output); + } +} + /* * AES-ECB block encryption */ @@ -148,7 +169,7 @@ void esp_aes_encrypt( esp_aes_context *ctx, { esp_aes_acquire_hardware(); esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); - ets_aes_crypt(input, output); + esp_aes_block(input, output); esp_aes_release_hardware(); } @@ -162,7 +183,7 @@ void esp_aes_decrypt( esp_aes_context *ctx, { esp_aes_acquire_hardware(); esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); - ets_aes_crypt(input, output); + esp_aes_block(input, output); esp_aes_release_hardware(); } @@ -177,7 +198,7 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx, { esp_aes_acquire_hardware(); esp_aes_setkey_hardware(ctx, mode); - ets_aes_crypt(input, output); + esp_aes_block(input, output); esp_aes_release_hardware(); return 0; } @@ -206,7 +227,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, if ( mode == ESP_AES_DECRYPT ) { while ( length > 0 ) { memcpy( temp, input, 16 ); - ets_aes_crypt(input, output); + esp_aes_block(input, output); for ( i = 0; i < 16; i++ ) { output[i] = (unsigned char)( output[i] ^ iv[i] ); @@ -218,13 +239,13 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, output += 16; length -= 16; } - } else { + } else { // ESP_AES_ENCRYPT while ( length > 0 ) { for ( i = 0; i < 16; i++ ) { output[i] = (unsigned char)( input[i] ^ iv[i] ); } - ets_aes_crypt(output, output); + esp_aes_block(output, output); memcpy( iv, output, 16 ); input += 16; @@ -258,7 +279,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx, if ( mode == ESP_AES_DECRYPT ) { while ( length-- ) { if ( n == 0 ) { - ets_aes_crypt(iv, iv ); + esp_aes_block(iv, iv ); } c = *input++; @@ -270,7 +291,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx, } else { while ( length-- ) { if ( n == 0 ) { - ets_aes_crypt(iv, iv ); + esp_aes_block(iv, iv ); } iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); @@ -304,7 +325,7 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx, while ( length-- ) { memcpy( ov, iv, 16 ); - ets_aes_crypt(iv, iv); + esp_aes_block(iv, iv); if ( mode == ESP_AES_DECRYPT ) { ov[16] = *input; @@ -343,7 +364,7 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, while ( length-- ) { if ( n == 0 ) { - ets_aes_crypt(nonce_counter, stream_block); + esp_aes_block(nonce_counter, stream_block); for ( i = 16; i > 0; i-- ) if ( ++nonce_counter[i - 1] != 0 ) { From 2624e100553d66435bef4fbad99e18e22b17dfd7 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Aug 2017 08:58:33 +1000 Subject: [PATCH 08/12] esp32 hwcrypto: Use AES registers directly --- components/esp32/hwcrypto/aes.c | 134 ++++++++---------- components/esp32/include/hwcrypto/aes.h | 26 +--- components/mbedtls/port/include/aes_alt.h | 4 +- .../soc/esp32/include/soc/hwcrypto_reg.h | 8 ++ components/soc/esp32/include/soc/soc.h | 1 + 5 files changed, 75 insertions(+), 98 deletions(-) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index e1acf536f..7a9c93f32 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -3,7 +3,7 @@ * Based on mbedTLS FIPS-197 compliant version. * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd + * Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -26,9 +26,10 @@ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf */ #include +#include "mbedtls/aes.h" #include "hwcrypto/aes.h" -#include "rom/aes.h" #include "soc/dport_reg.h" +#include "soc/hwcrypto_reg.h" #include static _lock_t aes_lock; @@ -81,55 +82,18 @@ void esp_aes_free( esp_aes_context *ctx ) bzero( ctx, sizeof( esp_aes_context ) ); } -/* Translate number of bits to an AES_BITS enum */ -static int keybits_to_aesbits(unsigned int keybits) -{ - switch (keybits) { - case 128: - return AES128; - case 192: - return AES192; - break; - case 256: - return AES256; - default: - return ( ERR_ESP_AES_INVALID_KEY_LENGTH ); - } -} - /* - * AES key schedule (encryption) + * AES key schedule (same for encryption or decryption, as hardware handles schedule) * */ -int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) +int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) { - uint16_t keybytes = keybits / 8; - int aesbits = keybits_to_aesbits(keybits); - if (aesbits < 0) { - return aesbits; + if (keybits != 128 && keybits != 192 && keybits != 256) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } - ctx->enc.aesbits = aesbits; - bzero(ctx->enc.key, sizeof(ctx->enc.key)); - memcpy(ctx->enc.key, key, keybytes); - return 0; -} - -/* - * AES key schedule (decryption) - * - */ -int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - uint16_t keybytes = keybits / 8; - int aesbits = keybits_to_aesbits(keybits); - if (aesbits < 0) { - return aesbits; - } - ctx->dec.aesbits = aesbits; - bzero(ctx->dec.key, sizeof(ctx->dec.key)); - memcpy(ctx->dec.key, key, keybytes); + ctx->key_bytes = keybits / 8; + memcpy(ctx->key, key, ctx->key_bytes); return 0; } @@ -137,27 +101,41 @@ int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, * Helper function to copy key from esp_aes_context buffer * to hardware key registers. * - * Only call when protected by esp_aes_acquire_hardware(). + * Call only while holding esp_aes_acquire_hardware(). */ -static inline int esp_aes_setkey_hardware( esp_aes_context *ctx, int mode) +static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode) { - DPORT_ACCESS_BLOCK() { - // ROM AES functions access DPORT, so need to be protected as such - if ( mode == ESP_AES_ENCRYPT ) { - ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits); - } else { - ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits); - } - } - return 0; + const uint32_t MODE_DECRYPT_BIT = 4; + unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT; + + memcpy((uint32_t *)AES_KEY_BASE, ctx->key, ctx->key_bytes); + DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2)); } -static inline void esp_aes_block(const uint8_t input[16], uint8_t output[16]) +/* Run a single 16 byte block of AES, using the hardware engine. + * + * Call only while holding esp_aes_acquire_hardware(). + */ +static inline void esp_aes_block(const void *input, void *output) { - DPORT_ACCESS_BLOCK() { - // ROM AES functions access DPORT, so need to be protected as such - ets_aes_crypt(input, output); + const uint32_t *input_words = (const uint32_t *)input; + uint32_t *output_words = (uint32_t *)output; + uint32_t *mem_block = (uint32_t *)AES_TEXT_BASE; + + for(int i = 0; i < 4; i++) { + mem_block[i] = input_words[i]; } + + DPORT_REG_WRITE(AES_START_REG, 1); + + DPORT_STALL_OTHER_CPU_START(); + { + while (_DPORT_REG_READ(AES_IDLE_REG) != 1) { } + for (int i = 0; i < 4; i++) { + output_words[i] = mem_block[i]; + } + } + DPORT_STALL_OTHER_CPU_END(); } /* @@ -215,6 +193,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, unsigned char *output ) { int i; + uint32_t *output_words = (uint32_t *)output; + const uint32_t *input_words = (const uint32_t *)input; + uint32_t *iv_words = (uint32_t *)iv; unsigned char temp[16]; if ( length % 16 ) { @@ -222,34 +203,36 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, } esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, mode); if ( mode == ESP_AES_DECRYPT ) { while ( length > 0 ) { - memcpy( temp, input, 16 ); - esp_aes_block(input, output); + memcpy(temp, input_words, 16); + esp_aes_block(input_words, output_words); - for ( i = 0; i < 16; i++ ) { - output[i] = (unsigned char)( output[i] ^ iv[i] ); + for ( i = 0; i < 4; i++ ) { + output_words[i] = output_words[i] ^ iv_words[i]; } - memcpy( iv, temp, 16 ); + memcpy( iv_words, temp, 16 ); - input += 16; - output += 16; + input_words += 4; + output_words += 4; length -= 16; } } else { // ESP_AES_ENCRYPT while ( length > 0 ) { - for ( i = 0; i < 16; i++ ) { - output[i] = (unsigned char)( input[i] ^ iv[i] ); + + for ( i = 0; i < 4; i++ ) { + output_words[i] = input_words[i] ^ iv_words[i]; } - esp_aes_block(output, output); - memcpy( iv, output, 16 ); + esp_aes_block(output_words, output_words); + memcpy( iv_words, output_words, 16 ); - input += 16; - output += 16; + input_words += 4; + output_words += 4; length -= 16; } } @@ -274,6 +257,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx, size_t n = *iv_off; esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); if ( mode == ESP_AES_DECRYPT ) { @@ -321,6 +305,7 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx, unsigned char ov[17]; esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); while ( length-- ) { @@ -360,6 +345,7 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, size_t n = *nc_off; esp_aes_acquire_hardware(); + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); while ( length-- ) { diff --git a/components/esp32/include/hwcrypto/aes.h b/components/esp32/include/hwcrypto/aes.h index b6a632aff..0bcd1f490 100644 --- a/components/esp32/include/hwcrypto/aes.h +++ b/components/esp32/include/hwcrypto/aes.h @@ -38,11 +38,6 @@ extern "C" { #define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ -typedef struct { - enum AES_BITS aesbits; - uint8_t key[32]; -} key_context, KEY_CTX; - /** * \brief AES context structure * @@ -52,10 +47,8 @@ typedef struct { * generating an extra round key */ typedef struct { - int nr; /*!< number of rounds */ - uint32_t *rk; /*!< AES round keys */ - KEY_CTX enc; - KEY_CTX dec; + uint8_t key_bytes; + uint8_t key[32]; } esp_aes_context; /** @@ -94,7 +87,7 @@ void esp_aes_init( esp_aes_context *ctx ); void esp_aes_free( esp_aes_context *ctx ); /** - * \brief AES key schedule (encryption) + * \brief AES set key schedule (encryption or decryption) * * \param ctx AES context to be initialized * \param key encryption key @@ -102,18 +95,7 @@ void esp_aes_free( esp_aes_context *ctx ); * * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH */ -int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH - */ -int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits ); +int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits ); /** * \brief AES-ECB block encryption/decryption diff --git a/components/mbedtls/port/include/aes_alt.h b/components/mbedtls/port/include/aes_alt.h index d4da6ca87..a4d0b70c3 100644 --- a/components/mbedtls/port/include/aes_alt.h +++ b/components/mbedtls/port/include/aes_alt.h @@ -34,8 +34,8 @@ typedef esp_aes_context mbedtls_aes_context; #define mbedtls_aes_init esp_aes_init #define mbedtls_aes_free esp_aes_free -#define mbedtls_aes_setkey_enc esp_aes_setkey_enc -#define mbedtls_aes_setkey_dec esp_aes_setkey_dec +#define mbedtls_aes_setkey_enc esp_aes_setkey +#define mbedtls_aes_setkey_dec esp_aes_setkey #define mbedtls_aes_crypt_ecb esp_aes_crypt_ecb #if defined(MBEDTLS_CIPHER_MODE_CBC) #define mbedtls_aes_crypt_cbc esp_aes_crypt_cbc diff --git a/components/soc/esp32/include/soc/hwcrypto_reg.h b/components/soc/esp32/include/soc/hwcrypto_reg.h index 10e80d935..d0dfa7485 100644 --- a/components/soc/esp32/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32/include/soc/hwcrypto_reg.h @@ -57,4 +57,12 @@ #define SHA_512_LOAD_REG ((DR_REG_SHA_BASE) + 0xb8) #define SHA_512_BUSY_REG ((DR_REG_SHA_BASE) + 0xbc) +/* AES acceleration registers */ +#define AES_START_REG ((DR_REG_AES_BASE) + 0x00) +#define AES_IDLE_REG ((DR_REG_AES_BASE) + 0x04) +#define AES_MODE_REG ((DR_REG_AES_BASE) + 0x08) +#define AES_KEY_BASE ((DR_REG_AES_BASE) + 0x10) +#define AES_TEXT_BASE ((DR_REG_AES_BASE) + 0x30) +#define AES_ENDIAN ((DR_REG_AES_BASE) + 0x40) + #endif diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index b758f559e..f3448a190 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -69,6 +69,7 @@ #define SOC_RTC_DATA_HIGH 0x50002000 #define DR_REG_DPORT_BASE 0x3ff00000 +#define DR_REG_AES_BASE 0x3ff01000 #define DR_REG_RSA_BASE 0x3ff02000 #define DR_REG_SHA_BASE 0x3ff03000 #define DR_REG_DPORT_END 0x3ff03FFC From 50e0a54630747f76c0d94455bf1a0d7a4908856a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Aug 2017 09:06:52 +1000 Subject: [PATCH 09/12] esp32 hwcrypto: Use spinlock instead of lock to protect AES More than doubles performance of mbedTLS AES self-tests. --- components/esp32/hwcrypto/aes.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 7a9c93f32..716bc636f 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -32,12 +32,26 @@ #include "soc/hwcrypto_reg.h" #include -static _lock_t aes_lock; +#include + +#include "soc/cpu.h" +#include + + +/* AES uses a spinlock mux not a lock as the underlying block operation + only takes 208 cycles (to write key & compute block), +600 cycles + for DPORT protection but +3400 cycles again if you use a full sized lock. + + For CBC, CFB, etc. this may mean that interrupts are disabled for a longer + period of time for bigger lengths. However at the moment this has to happen + anyway due to DPORT protection... +*/ +static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED; void esp_aes_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ - _lock_acquire(&aes_lock); + portENTER_CRITICAL(&aes_spinlock); DPORT_STALL_OTHER_CPU_START(); { @@ -65,7 +79,7 @@ void esp_aes_release_hardware( void ) } DPORT_STALL_OTHER_CPU_END(); - _lock_release(&aes_lock); + portEXIT_CRITICAL(&aes_spinlock); } void esp_aes_init( esp_aes_context *ctx ) @@ -178,6 +192,7 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx, esp_aes_setkey_hardware(ctx, mode); esp_aes_block(input, output); esp_aes_release_hardware(); + return 0; } From afb61195047d7eff2d54ebbb0a42e0becbbc04c4 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 16 Aug 2017 16:02:46 +1000 Subject: [PATCH 10/12] dport access: Fix WDT bug (permanent locking) in non-pinned tasks If scheduler switches cores in narrow window during esp_dport_access_stall_other_cpu_start(), could cause the stall interrupt to occur on the running CPU - halting the CPU until WDT cleans up. Related to https://github.com/espressif/esp-idf/issues/630 --- components/esp32/dport_access.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index e1923b412..29ddad8b5 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -69,17 +69,18 @@ static BaseType_t oldInterruptLevel[2]; void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void) { #ifndef CONFIG_FREERTOS_UNICORE - int cpu_id = xPortGetCoreID(); - if (dport_core_state[0] == DPORT_CORE_STATE_IDLE - || dport_core_state[1] == DPORT_CORE_STATE_IDLE) { + || dport_core_state[1] == DPORT_CORE_STATE_IDLE) { return; } + BaseType_t intLvl = portENTER_CRITICAL_NESTED(); + + int cpu_id = xPortGetCoreID(); + #ifdef DPORT_ACCESS_BENCHMARK ccount_start[cpu_id] = XTHAL_GET_CCOUNT(); #endif - BaseType_t intLvl = portENTER_CRITICAL_NESTED(); if (dport_access_ref[cpu_id] == 0) { portENTER_CRITICAL_ISR(&g_dport_mux); From 0ea4cd67ddc0fd7edc3b68538bdc0717483e834b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 Aug 2017 14:19:03 +1000 Subject: [PATCH 11/12] mbedtls: Remove "unsafe" warning, enable AES by default & make SHA/MPI optional --- components/mbedtls/Kconfig | 28 +++++++++------------- components/mbedtls/test/test_mbedtls_sha.c | 22 ++++++++--------- tools/unit-test-app/sdkconfig | 27 ++++++++++++++++++--- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 8d9d70820..f1016f5c2 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -31,26 +31,18 @@ config MBEDTLS_DEBUG at runtime in order to enable mbedTLS debug output via the ESP log mechanism. -config MBEDTLS_UNSAFE_ACCELERATION - bool "Allow buggy hardware acceleration features" - depends on !FREERTOS_UNICORE - default n - help - A bug currently prevents dual cores & crypto hardware acceleration from being used together. - - Enable this option to allow hardware acceleration anyhow (note that invalid results or crashes may occur.) - config MBEDTLS_HARDWARE_AES bool "Enable hardware AES acceleration" - depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE default y help Enable hardware accelerated AES encryption & decryption. + Note that if the ESP32 CPU is running at 240MHz, hardware AES does not + offer any speed boost over software AES. + config MBEDTLS_HARDWARE_MPI bool "Enable hardware MPI (bignum) acceleration" - depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE - default y + default n help Enable hardware accelerated multiple precision integer operations. @@ -62,7 +54,7 @@ config MBEDTLS_HARDWARE_MPI config MBEDTLS_MPI_USE_INTERRUPT bool "Use interrupt for MPI operations" depends on MBEDTLS_HARDWARE_MPI - default y + default n help Use an interrupt to coordinate MPI operations. @@ -71,16 +63,18 @@ config MBEDTLS_MPI_USE_INTERRUPT config MBEDTLS_HARDWARE_SHA bool "Enable hardware SHA acceleration" - depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE - default y + default n help Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS. Due to a hardware limitation, hardware acceleration is only guaranteed if SHA digests are calculated one at a time. If more - than one SHA digest is calculated at the same time, only will + than one SHA digest is calculated at the same time, one will be calculated fully in hardware and the rest will be calculated - (at least partially calculated) in software. + (at least partially calculated) in software. This happens automatically. + + SHA hardware acceleration is faster than software in some situations but + slower in others. You should benchmark to find the best setting for you. config MBEDTLS_HAVE_TIME bool "Enable mbedtls time" diff --git a/components/mbedtls/test/test_mbedtls_sha.c b/components/mbedtls/test/test_mbedtls_sha.c index e31eec9bb..fba16ef0b 100644 --- a/components/mbedtls/test/test_mbedtls_sha.c +++ b/components/mbedtls/test/test_mbedtls_sha.c @@ -119,13 +119,15 @@ static void tskRunSHA256Test(void *pvParameters) vTaskDelete(NULL); } -TEST_CASE("mbedtls SHA multithreading", "[mbedtls][ignore]") +#define SHA_TASK_STACK_SIZE (10*1024) + +TEST_CASE("mbedtls SHA multithreading", "[mbedtls]") { done_sem = xSemaphoreCreateCounting(4, 0); - xTaskCreate(tskRunSHA1Test, "SHA1Task1", 8192, NULL, 3, NULL); - xTaskCreate(tskRunSHA1Test, "SHA1Task2", 8192, NULL, 3, NULL); - xTaskCreate(tskRunSHA256Test, "SHA256Task1", 8192, NULL, 3, NULL); - xTaskCreate(tskRunSHA256Test, "SHA256Task2", 8192, NULL, 3, NULL); + xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA1Test, "SHA1Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA256Test, "SHA256Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHA256Test, "SHA256Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); for(int i = 0; i < 4; i++) { if(!xSemaphoreTake(done_sem, 10000/portTICK_PERIOD_MS)) { @@ -165,14 +167,10 @@ void tskRunSHASelftests(void *param) TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]") { done_sem = xSemaphoreCreateCounting(2, 0); - xTaskCreate(tskRunSHASelftests, "SHASelftests1", 8192, NULL, 3, NULL); - xTaskCreate(tskRunSHASelftests, "SHASelftests2", 8192, NULL, 3, NULL); + xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); + xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); -#ifdef CONFIG_MBEDTLS_HARDWARE_SHA - const int TIMEOUT_MS = 12000; -#else - const int TIMEOUT_MS = 20000; // Soft-only SHA may need a little longer -#endif + const int TIMEOUT_MS = 20000; for(int i = 0; i < 2; i++) { if(!xSemaphoreTake(done_sem, TIMEOUT_MS/portTICK_PERIOD_MS)) { diff --git a/tools/unit-test-app/sdkconfig b/tools/unit-test-app/sdkconfig index 55a5121e2..e97cb3c45 100644 --- a/tools/unit-test-app/sdkconfig +++ b/tools/unit-test-app/sdkconfig @@ -19,7 +19,6 @@ CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y # CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set # CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set CONFIG_LOG_BOOTLOADER_LEVEL=2 -# CONFIG_BOOTLOADER_LTO is not set # # Security features @@ -174,6 +173,11 @@ CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=0 # CONFIG_ESP32_XTAL_FREQ_26 is not set CONFIG_ESP32_XTAL_FREQ_AUTO=y CONFIG_ESP32_XTAL_FREQ=0 +# CONFIG_NO_BLOBS is not set + +# +# Wi-Fi +# CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=0 # CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set @@ -181,8 +185,9 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP32_WIFI_AMPDU_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y -CONFIG_PHY_ENABLED=y # # PHY @@ -280,10 +285,16 @@ CONFIG_TCP_SYNMAXRTX=6 CONFIG_TCP_MSS=1436 CONFIG_TCP_SND_BUF_DEFAULT=5744 CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 CONFIG_TCP_QUEUE_OOSEQ=y CONFIG_TCP_OVERSIZE_MSS=y # CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set # CONFIG_TCP_OVERSIZE_DISABLE is not set + +# +# UDP +# +CONFIG_UDP_RECVMBOX_SIZE=6 # CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set CONFIG_TCPIP_TASK_STACK_SIZE=2048 # CONFIG_PPP_SUPPORT is not set @@ -299,7 +310,10 @@ CONFIG_TCPIP_TASK_STACK_SIZE=2048 # CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 # CONFIG_MBEDTLS_DEBUG is not set -# CONFIG_MBEDTLS_UNSAFE_ACCELERATION is not set +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA=y CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set @@ -315,3 +329,10 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y # # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 From 703d143619dcb740b5da71953e57d2ec5bf535ca Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 Aug 2017 15:48:43 +1000 Subject: [PATCH 12/12] hwcrypto: Fix bug with concurrent SHA access If two different types of SHA hashes were active in the hardware concurrently, a race condition meant the SHA unit could be incorrectly reset leading to all-zero results. --- components/esp32/hwcrypto/sha.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c index 0c0c8ddb5..305b476a8 100644 --- a/components/esp32/hwcrypto/sha.c +++ b/components/esp32/hwcrypto/sha.c @@ -172,10 +172,10 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine) DPORT_STALL_OTHER_CPU_END(); } - _lock_release(&state_change_lock); - assert( !engine->in_use && "in_use flag should be cleared" ); engine->in_use = true; + + _lock_release(&state_change_lock); }