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.
This commit is contained in:
Angus Gratton 2016-11-22 18:09:32 +11:00
parent c48612e516
commit 2561b68af8
5 changed files with 55 additions and 10 deletions

View file

@ -28,6 +28,7 @@
#include <string.h> #include <string.h>
#include "hwcrypto/aes.h" #include "hwcrypto/aes.h"
#include "rom/aes.h" #include "rom/aes.h"
#include "soc/dport_reg.h"
#include <sys/lock.h> #include <sys/lock.h>
static _lock_t aes_lock; static _lock_t aes_lock;
@ -36,14 +37,23 @@ void esp_aes_acquire_hardware( void )
{ {
/* newlib locks lazy initialize on ESP-IDF */ /* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&aes_lock); _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 ) void esp_aes_release_hardware( void )
{ {
uint8_t zero[256/8] = { 0 }; /* Disable AES hardware */
ets_aes_setkey_enc(zero, AES256); REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES);
ets_aes_disable(); /* 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); _lock_release(&aes_lock);
} }

View file

@ -143,15 +143,21 @@ bool esp_sha_try_lock_engine(esp_sha_type sha_type)
_lock_acquire(&state_change_lock); _lock_acquire(&state_change_lock);
assert( !engine->in_use && "in_use flag should be cleared" );
if (sha_engines_all_idle()) { 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(); ets_sha_enable();
} }
_lock_release(&state_change_lock); _lock_release(&state_change_lock);
assert( !engine->in_use && "in_use flag should be cleared" );
engine->in_use = true; engine->in_use = true;
return true; return true;
} }
@ -165,7 +171,10 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
engine->in_use = false; engine->in_use = false;
if (sha_engines_all_idle()) { 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); _lock_release(&state_change_lock);

View file

@ -94,6 +94,16 @@
#define DPORT_PERI_RST_EN_V 0xFFFFFFFF #define DPORT_PERI_RST_EN_V 0xFFFFFFFF
#define DPORT_PERI_RST_EN_S 0 #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) #define DPORT_WIFI_BB_CFG_REG (DR_REG_DPORT_BASE + 0x024)
/* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ /* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
/*description: */ /*description: */

View file

@ -30,7 +30,7 @@
#define RSA_MULT_MODE_REG (DR_REG_RSA_BASE + 0x80c) #define RSA_MULT_MODE_REG (DR_REG_RSA_BASE + 0x80c)
#define RSA_MULT_START_REG (DR_REG_RSA_BASE + 0x810) #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) #define RSA_CLEAN_REG (DR_REG_RSA_BASE + 0x818)

View file

@ -33,6 +33,8 @@
#include "esp_intr.h" #include "esp_intr.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "soc/dport_reg.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
@ -71,7 +73,16 @@ void esp_mpi_acquire_hardware( void )
{ {
/* newlib locks lazy initialize on ESP-IDF */ /* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&mpi_lock); _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 #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
rsa_isr_initialise(); rsa_isr_initialise();
#endif #endif
@ -79,7 +90,12 @@ void esp_mpi_acquire_hardware( void )
void esp_mpi_release_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); _lock_release(&mpi_lock);
} }