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 "hwcrypto/aes.h"
#include "rom/aes.h"
#include "soc/dport_reg.h"
#include <sys/lock.h>
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);
}

View file

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

View file

@ -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: */

View file

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

View file

@ -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);
}