Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esp32: Fix memory leaks and thread safety issues #8471

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 47 additions & 10 deletions wolfcrypt/src/port/Espressif/esp32_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,16 +474,26 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
int ret;

ESP_LOGV(TAG, "enter wc_esp32AesDecrypt");
/* lock the hw engine */
esp_aes_hw_InUse();
/* load the key into the register */

/* Validate parameters */
if (aes == NULL || in == NULL || out == NULL) {
ESP_LOGE(TAG, "Invalid parameters");
return BAD_FUNC_ARG;
}

/* Lock the hw engine */
ret = esp_aes_hw_InUse();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to acquire HW lock");
return ret;
}

/* Load the key into the register */
ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "wc_esp32AesDecrypt failed "
"during esp_aes_hw_Set_KeyMode");
/* release hw */
ESP_LOGE(TAG, "Failed during esp_aes_hw_Set_KeyMode");
esp_aes_hw_Leave();
ret = BAD_FUNC_ARG;
return BAD_FUNC_ARG;
}

if (ret == ESP_OK) {
Expand Down Expand Up @@ -514,13 +524,27 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
int ret;
int i;
int offset = 0;
word32 blocks = (sz / WC_AES_BLOCK_SIZE);
word32 blocks;
byte *iv;
byte temp_block[WC_AES_BLOCK_SIZE];

ESP_LOGV(TAG, "enter wc_esp32AesCbcEncrypt");

/* Validate parameters */
if (aes == NULL || out == NULL || in == NULL) {
ESP_LOGE(TAG, "Invalid parameters");
return BAD_FUNC_ARG;
}

/* Validate size */
if (sz == 0 || (sz % WC_AES_BLOCK_SIZE) != 0) {
ESP_LOGE(TAG, "Invalid size: must be multiple of block size");
return BAD_FUNC_ARG;
}

blocks = sz / WC_AES_BLOCK_SIZE;
iv = (byte*)aes->reg;
XMEMSET(temp_block, 0, WC_AES_BLOCK_SIZE);

ret = esp_aes_hw_InUse();

Expand Down Expand Up @@ -570,16 +594,29 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
{
int ret;

int i;
int offset = 0;
word32 blocks = (sz / WC_AES_BLOCK_SIZE);
word32 blocks;
byte* iv;
byte temp_block[WC_AES_BLOCK_SIZE];

ESP_LOGV(TAG, "enter wc_esp32AesCbcDecrypt");

/* Validate parameters */
if (aes == NULL || out == NULL || in == NULL) {
ESP_LOGE(TAG, "Invalid parameters");
return BAD_FUNC_ARG;
}

/* Validate size */
if (sz == 0 || (sz % WC_AES_BLOCK_SIZE) != 0) {
ESP_LOGE(TAG, "Invalid size: must be multiple of block size");
return BAD_FUNC_ARG;
}

blocks = sz / WC_AES_BLOCK_SIZE;
iv = (byte*)aes->reg;
XMEMSET(temp_block, 0, WC_AES_BLOCK_SIZE);

ret = esp_aes_hw_InUse();

Expand Down
78 changes: 52 additions & 26 deletions wolfcrypt/src/port/Espressif/esp32_mp.c
Original file line number Diff line number Diff line change
Expand Up @@ -788,13 +788,18 @@ static int esp_clean_result(MATH_INT_T* Z, int used_padding)
/* Start HW process. Reg is SoC-specific register. */
static int process_start(u_int32_t reg)
{
int ret = MP_OKAY;
/* see 3.16 "software needs to always use the "volatile"
** attribute when accessing registers in these two address spaces. */
if (reg == 0) {
ESP_LOGE(TAG, "Invalid register in process_start");
return MP_VAL;
}

/* See 3.16: "software needs to always use the 'volatile'
* attribute when accessing registers in these address spaces" */
portENTER_CRITICAL(&wc_rsa_reg_lock);
DPORT_REG_WRITE((volatile word32*)reg, 1);
ESP_EM__POST_PROCESS_START;
portEXIT_CRITICAL(&wc_rsa_reg_lock);

return ret;
return MP_OKAY;
}

/* wait until RSA math register indicates operation completed */
Expand All @@ -803,27 +808,31 @@ static int wait_until_done(word32 reg)
int ret = MP_OKAY;
word32 timeout = 0;

/* wait until done && not timeout */
ESP_EM__MP_HW_WAIT_DONE;
while (!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(reg) != 1) {
asm volatile("nop"); /* wait */
if (reg == 0) {
ESP_LOGE(TAG, "Invalid register in wait_until_done");
return MP_VAL;
}
ESP_EM__DPORT_FIFO_READ;

#if defined(CONFIG_IDF_TARGET_ESP32C6)
/* Write 1 or 0 to the RSA_INT_ENA_REG register to
* enable or disable the interrupt function. */
DPORT_REG_WRITE(RSA_INT_CLR_REG, 1); /* write 1 to clear */
DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); /* disable */
/* Wait until done && not timeout */
while (!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(reg) != 1) {
/* Expected delay 1-2 µs */
}

#elif defined(CONFIG_IDF_TARGET_ESP32C3)
/* not currently clearing / disable on C3 */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
/* Handle timeouts and cleanup */
if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "Hardware operation timeout in wait_until_done");
ret = WC_HW_E;
goto cleanup;
}

/* Clear interrupts based on target */
#if defined(CONFIG_IDF_TARGET_ESP32C6)
/* Write 1 to clear, 0 to disable interrupt function */
DPORT_REG_WRITE(RSA_INT_CLR_REG, 1);
DPORT_REG_WRITE(RSA_INT_ENA_REG, 0);
#else
/* clear interrupt */
/* Clear interrupt for other targets */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);

#endif

#if defined(WOLFSSL_HW_METRICS)
Expand All @@ -832,9 +841,11 @@ static int wait_until_done(word32 reg)
}
#endif

if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "rsa operation timed out.");
ret = WC_HW_E; /* MP_HW_ERROR; */
cleanup:
if (ret != MP_OKAY) {
/* Force hardware reset on error */
periph_module_disable(PERIPH_RSA_MODULE);
periph_module_enable(PERIPH_RSA_MODULE);
}

return ret;
Expand All @@ -846,12 +857,27 @@ static int esp_memblock_to_mpint(const word32 mem_address,
word32 numwords)
{
int ret = MP_OKAY;

if (mp == NULL || numwords == 0 || mem_address == 0 ||
numwords > (ESP_HW_MOD_RSAMAX_BITS / 32)) {
ESP_LOGE(TAG, "Invalid parameters in esp_memblock_to_mpint");
return MP_VAL;
}

/* Initialize mp->used to prevent buffer overflow */
mp->used = numwords;
if (mp->used > MP_SIZE) {
ESP_LOGE(TAG, "Buffer overflow prevented in esp_memblock_to_mpint");
return MP_VAL;
}

/* Clear destination buffer before copying */
XMEMSET(mp->dp, 0, numwords * sizeof(word32));

#ifdef USE_ESP_DPORT_ACCESS_READ_BUFFER
esp_dport_access_read_buffer((word32*)mp->dp, mem_address, numwords);
#else
ESP_EM__PRE_DPORT_READ;
DPORT_INTERRUPT_DISABLE();
ESP_EM__READ_NON_FIFO_REG;
portENTER_CRITICAL(&wc_rsa_reg_lock);
for (volatile word32 i = 0; i < numwords; ++i) {
ESP_EM__3_16;
mp->dp[i] = DPORT_SEQUENCE_REG_READ(
Expand Down
Loading
Loading