fix(mbedtls/aes): fix ESP32-S2 Crypto DMA stall on PSRAM output with partial blocks

The ESP32-S2 Crypto DMA in-channel stalls silently when a receive
descriptor list transitions from external to internal RAM. The AES
driver hits this when a PSRAM-output operation has a trailing partial
block, as the internal stream descriptor is linked after the external
RAM data descriptors.

- esp_aes_process_dma(): process the block-aligned part and the partial
  block as two separate DMA operations, keeping each descriptor list
  uniform
- crypto_dma_ll_reset(): also reset the in-channel (per the TRM receive
  reset sequence), otherwise stale state from a preceding external-RAM
  operation corrupts the next operation's output

The GCM DMA path is unaffected; it never operates on PSRAM buffers.
This commit is contained in:
harshal.patil
2026-08-19 11:27:42 +05:30
parent 4f7226bb6e
commit d88cb2c719
2 changed files with 22 additions and 2 deletions

View File

@@ -31,8 +31,8 @@ typedef enum {
*/ */
static inline void crypto_dma_ll_reset(void) static inline void crypto_dma_ll_reset(void)
{ {
SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_IN_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_IN_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
} }
/** /**

View File

@@ -360,6 +360,26 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
} }
#if SOC_AES_CRYPTO_DMA && CONFIG_SPIRAM
/* The Crypto DMA in-channel stalls indefinitely (no descriptor error is raised) when a
receive descriptor list transitions from a buffer in external RAM to one in internal
RAM. Avoid linking the internal stream buffer descriptor after external-RAM data
descriptors by processing the block-aligned part and the trailing partial block as
two separate DMA operations. */
if (block_bytes > 0 && stream_bytes > 0 && esp_ptr_external_ram(output)) {
ret = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
if (ret != 0) {
mbedtls_platform_zeroize(output, len);
return ret;
}
ret = esp_aes_process_dma(ctx, input + block_bytes, output + block_bytes, stream_bytes, stream_out);
if (ret != 0) {
mbedtls_platform_zeroize(output, len);
}
return ret;
}
#endif /* SOC_AES_CRYPTO_DMA && CONFIG_SPIRAM */
if (block_bytes > 0) { if (block_bytes > 0) {
/* Flush cache if input in external ram */ /* Flush cache if input in external ram */
#if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE) #if (CONFIG_SPIRAM && SOC_PSRAM_DMA_CAPABLE)