From 4636443b4936fdf23cd644aebe71a81799a2ca08 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 1 Sep 2023 13:46:22 +0530 Subject: [PATCH] fix(aes): correct the linking of the DMA descriptors For certain data lengths, the last input descriptor was not getting appended correctly and hence the EOF flag in the DMA descriptor link list was set at incorrect location. This was resulting in the peripheral being stalled expecting more data and eventually the code used to timeout waiting for the AES completion interrupt. Required configs for this issue: CONFIG_MBEDTLS_HARDWARE_AES CONFIG_SOC_AES_SUPPORT_DMA This observation is similar to the issue reported in: https://github.com/espressif/esp-idf/issues/10647 To recreate this issue, start the AES-GCM DMA operation with data length 12280 bytes and this should stall the operation forever. In this fix, we are tracing the entire descriptor list and then appending the extra bytes descriptor at correct position (as the last node). --- components/mbedtls/port/aes/dma/esp_aes.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/components/mbedtls/port/aes/dma/esp_aes.c b/components/mbedtls/port/aes/dma/esp_aes.c index 0c465281fd..8d4f071937 100644 --- a/components/mbedtls/port/aes/dma/esp_aes.c +++ b/components/mbedtls/port/aes/dma/esp_aes.c @@ -391,6 +391,10 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, //Limit max inlink descriptor length to be 16 byte aligned, require for EDMA lldesc_setup_link_constrained(block_out_desc, output, block_bytes, LLDESC_MAX_NUM_PER_DESC_16B_ALIGNED, 0); + /* Setup in/out start descriptors */ + lldesc_append(&in_desc_head, block_in_desc); + lldesc_append(&out_desc_head, block_out_desc); + out_desc_tail = &block_out_desc[lldesc_num - 1]; } @@ -408,20 +412,13 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, lldesc_setup_link(&s_stream_in_desc, s_stream_in, AES_BLOCK_BYTES, 0); lldesc_setup_link(&s_stream_out_desc, s_stream_out, AES_BLOCK_BYTES, 0); - if (block_bytes > 0) { - /* Link with block descriptors*/ - block_in_desc[lldesc_num - 1].empty = (uint32_t)&s_stream_in_desc; - block_out_desc[lldesc_num - 1].empty = (uint32_t)&s_stream_out_desc; - } + /* Link with block descriptors */ + lldesc_append(&in_desc_head, &s_stream_in_desc); + lldesc_append(&out_desc_head, &s_stream_out_desc); out_desc_tail = &s_stream_out_desc; } - // block buffers are sent to DMA first, unless there aren't any - in_desc_head = (block_bytes > 0) ? block_in_desc : &s_stream_in_desc; - out_desc_head = (block_bytes > 0) ? block_out_desc : &s_stream_out_desc; - - #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) /* Only use interrupt for long AES operations */ if (len > AES_DMA_INTR_TRIG_LEN) {