Browse Source

AES: refactor and add HAL layer

Refactor the AES driver and add HAL, LL and caps.

Add better support for running AES-GCM fully in hardware.
Marius Vikhammer 5 years ago
parent
commit
457ce080ae
42 changed files with 3201 additions and 3296 deletions
  1. 1 1
      components/esp32/test/test_aes_sha_rsa.c
  2. 1 1
      components/esp_rom/include/esp32/rom/aes.h
  3. 1 0
      components/hal/CMakeLists.txt
  4. 227 0
      components/hal/aes_hal.c
  5. 137 0
      components/hal/esp32/include/hal/aes_ll.h
  6. 235 0
      components/hal/esp32c3/include/hal/aes_ll.h
  7. 317 0
      components/hal/esp32s2/include/hal/aes_ll.h
  8. 31 7
      components/hal/esp32s2/include/hal/crypto_dma_ll.h
  9. 235 0
      components/hal/esp32s3/include/hal/aes_ll.h
  10. 15 2
      components/hal/esp32s3/include/hal/gdma_ll.h
  11. 162 0
      components/hal/include/hal/aes_hal.h
  12. 48 0
      components/hal/include/hal/aes_types.h
  13. 2 3
      components/hal/sha_hal.c
  14. 0 1
      components/idf_test/include/esp32/idf_performance_target.h
  15. 2 1
      components/idf_test/include/esp32s2/idf_performance_target.h
  16. 8 2
      components/mbedtls/CMakeLists.txt
  17. 1 1
      components/mbedtls/component.mk
  18. 90 147
      components/mbedtls/port/aes/block/esp_aes.c
  19. 249 322
      components/mbedtls/port/aes/dma/esp_aes.c
  20. 83 0
      components/mbedtls/port/aes/esp_aes_common.c
  21. 695 0
      components/mbedtls/port/aes/esp_aes_gcm.c
  22. 1 13
      components/mbedtls/port/aes/esp_aes_xts.c
  23. 0 1524
      components/mbedtls/port/esp32s2/aes.c
  24. 31 44
      components/mbedtls/port/include/aes/esp_aes.h
  25. 13 12
      components/mbedtls/port/include/aes/esp_aes_gcm.h
  26. 23 9
      components/mbedtls/port/include/aes/esp_aes_internal.h
  27. 1 9
      components/mbedtls/port/include/aes_alt.h
  28. 2 324
      components/mbedtls/port/include/esp32/aes.h
  29. 2 338
      components/mbedtls/port/include/esp32s2/aes.h
  30. 3 215
      components/mbedtls/port/include/esp32s2/gcm.h
  31. 5 24
      components/mbedtls/port/include/gcm_alt.h
  32. 23 202
      components/mbedtls/test/test_aes.c
  33. 494 0
      components/mbedtls/test/test_aes_gcm.c
  34. 1 73
      components/mbedtls/test/test_aes_perf.c
  35. 19 18
      components/mbedtls/test/test_esp_crt_bundle.c
  36. 1 1
      components/mbedtls/test/test_sha_perf.c
  37. 5 0
      components/soc/esp32/include/soc/soc_caps.h
  38. 9 0
      components/soc/esp32c3/include/soc/soc_caps.h
  39. 12 0
      components/soc/esp32s2/include/soc/soc_caps.h
  40. 5 1
      components/soc/esp32s3/include/soc/soc.h
  41. 10 0
      components/soc/esp32s3/include/soc/soc_caps.h
  42. 1 1
      components/soc/include/soc/soc_memory_layout.h

+ 1 - 1
components/esp32/test/test_aes_sha_rsa.c

@@ -17,7 +17,7 @@
 #include "esp_log.h"
 #include "mbedtls/sha256.h"
 #include "sha/sha_parallel_engine.h"
-#include "esp32/aes.h"
+#include "aes/esp_aes.h"
 #include "mbedtls/rsa.h"
 
 static const char *TAG = "test";

+ 1 - 1
components/esp_rom/include/esp32/rom/aes.h

@@ -2,7 +2,7 @@
   ROM functions for hardware AES support.
 
   It is not recommended to use these functions directly,
-  use the wrapper functions in esp32/aes.h instead.
+  use the wrapper functions in aes/esp_aes.h instead.
 
  */
 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD

+ 1 - 0
components/hal/CMakeLists.txt

@@ -28,6 +28,7 @@ if(NOT BOOTLOADER_BUILD)
                 "soc_hal.c"
                 "interrupt_controller_hal.c"
                 "sha_hal.c"
+                "aes_hal.c"
                 "twai_hal.c"
                 "twai_hal_iram.c"
                 "${target}/interrupt_descriptor_table.c")

+ 227 - 0
components/hal/aes_hal.c

@@ -0,0 +1,227 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// The HAL layer for AES
+
+#include "hal/aes_hal.h"
+#include "hal/aes_ll.h"
+#include <stdlib.h>
+#include <string.h>
+#include "soc/soc_caps.h"
+
+#if SOC_AES_CRYPTO_DMA
+#include "soc/crypto_dma_reg.h"
+#include "hal/crypto_dma_ll.h"
+#elif SOC_AES_GENERAL_DMA
+#include "hal/gdma_ll.h"
+#endif
+
+uint8_t aes_hal_setkey(const uint8_t *key, size_t key_bytes, int mode)
+{
+    aes_ll_set_mode(mode, key_bytes);
+
+    uint8_t key_bytes_in_hardware = aes_ll_write_key(key, key_bytes / 4);
+    /* Used for fault injection check: all words of key data should have been written to hardware */
+    return key_bytes_in_hardware;
+}
+
+/**
+ * @brief Busy wait until the AES accelerator is idle
+ *
+ */
+static inline void aes_hal_wait_idle(void)
+{
+    while (aes_ll_get_state() != ESP_AES_STATE_IDLE) {
+    }
+}
+
+void aes_hal_transform_block(const void *input_block, void *output_block)
+{
+    aes_ll_write_block(input_block);
+    aes_ll_start_transform();
+    aes_hal_wait_idle();
+    aes_ll_read_block(output_block);
+}
+
+#if SOC_AES_SUPPORT_DMA
+
+#if SOC_AES_GENERAL_DMA
+/**
+ * @brief Initialize the DMA
+ *
+ * @param input AES input descriptor (outlink)
+ * @param output AES output descriptor (inlink)
+ */
+static inline void aes_hal_dma_init(const lldesc_t *input, const lldesc_t *output)
+{
+    /* Update driver when centralized DMA interface implemented, IDF-2192 */
+    gdma_ll_tx_enable_descriptor_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
+    gdma_ll_tx_enable_data_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
+    gdma_ll_rx_enable_descriptor_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
+    gdma_ll_rx_enable_data_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
+
+    gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_LL_PERIPH_ID_AES);
+    gdma_ll_rx_connect_to_periph(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_LL_PERIPH_ID_AES);
+
+    /* An L2 FIFO bigger than 40 bytes is need when accessing external ram */
+    gdma_ll_tx_extend_fifo_size_to(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, 40);
+    gdma_ll_rx_extend_l2_fifo_size_to(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, 40);
+    gdma_ll_tx_set_block_size_psram(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_OUT_EXT_MEM_BK_SIZE_16B);
+    gdma_ll_rx_set_block_size_psram(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_OUT_EXT_MEM_BK_SIZE_16B);
+
+    /* Set descriptors */
+    gdma_ll_tx_set_desc_addr(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, (uint32_t)input);
+    gdma_ll_rx_set_desc_addr(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, (uint32_t)output);
+
+    gdma_ll_rx_reset_channel(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
+    gdma_ll_tx_reset_channel(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
+
+    /* Start transfer */
+    gdma_ll_tx_start(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
+    gdma_ll_rx_start(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
+}
+
+static inline bool aes_hal_dma_done(const lldesc_t *output)
+{
+    return (gdma_ll_rx_is_fsm_idle(&GDMA, SOC_GDMA_AES_DMA_CHANNEL) && (output->owner == 0));
+}
+#endif //SOC_AES_GENERAL_DMA
+
+
+
+#if SOC_AES_CRYPTO_DMA
+/**
+ * @brief Initialize the DMA
+ *
+ * @param input AES input descriptor (outlink)
+ * @param output AES output descriptor (inlink)
+ */
+static inline void aes_hal_dma_init(const lldesc_t *input, const lldesc_t *output)
+{
+    crypto_dma_ll_reset();
+    crypto_dma_ll_set_mode(CRYPTO_DMA_AES);
+
+    /* Set descriptors, input to AES comes from outlink DMA and viceversa */
+    crypto_dma_ll_outlink_set((uint32_t)input);
+    crypto_dma_ll_inlink_set((uint32_t)output);
+
+    /* Start transfer */
+    crypto_dma_ll_outlink_start();
+    crypto_dma_ll_inlink_start();
+}
+
+static inline bool aes_hal_dma_done(lldesc_t *output)
+{
+    return (crypto_dma_ll_inlink_is_eof() && (output->owner == 0));
+}
+#endif //SOC_AES_CRYPTO_DMA
+
+void aes_hal_transform_dma_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks)
+{
+    aes_ll_dma_enable(true);
+    aes_hal_dma_init(input, output);
+
+    /* Write the number of blocks */
+    aes_ll_set_num_blocks(num_blocks);
+
+    /* Start encrypting/decrypting */
+    aes_ll_start_transform();
+}
+
+void aes_hal_transform_dma_finish(void)
+{
+    aes_ll_dma_exit();
+    aes_ll_dma_enable(false);
+}
+
+void aes_hal_mode_init(esp_aes_mode_t mode)
+{
+    /* Set the algorith mode CBC, CFB ... */
+    aes_ll_set_block_mode(mode);
+    /* Presently hard-coding the INC function to 32 bit */
+    if (mode == ESP_AES_BLOCK_MODE_CTR) {
+        aes_ll_set_inc();
+    }
+}
+
+void aes_hal_set_iv(const uint8_t *iv)
+{
+    aes_ll_set_iv(iv);
+}
+
+void aes_hal_read_iv(uint8_t *iv)
+{
+    aes_ll_read_iv(iv);
+}
+
+static inline void aes_hal_wait_done(void)
+{
+    while (aes_ll_get_state() != ESP_AES_STATE_DONE) {}
+}
+
+void aes_hal_wait_dma_done(lldesc_t *output)
+{
+    /* Checking this if interrupt is used also, to avoid
+       issues with AES fault injection
+    */
+    aes_hal_wait_done();
+
+    /* Wait for DMA write operation to complete */
+    while (1) {
+        if ( aes_hal_dma_done(output) ) {
+            break;
+        }
+    }
+}
+
+#endif //SOC_AES_SUPPORT_DMA
+
+#if SOC_AES_SUPPORT_GCM
+
+void aes_hal_gcm_calc_hash(uint8_t *gcm_hash)
+{
+    aes_ll_dma_enable(true);
+    aes_ll_start_transform();
+
+    aes_hal_wait_idle();
+
+    aes_ll_gcm_read_hash(gcm_hash);
+}
+
+void aes_hal_transform_dma_gcm_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks)
+{
+    aes_hal_dma_init(input, output);
+
+    /* Write the number of blocks */
+    aes_ll_set_num_blocks(num_blocks);
+
+    /* Start encrypting/decrypting */
+    aes_ll_cont_transform();
+}
+
+void aes_hal_gcm_init(size_t aad_num_blocks, size_t num_valid_bit)
+{
+    aes_ll_gcm_set_aad_num_blocks(aad_num_blocks);
+    aes_ll_gcm_set_num_valid_bit(num_valid_bit);
+}
+
+void aes_hal_gcm_read_tag(uint8_t *tag, size_t tag_len)
+{
+    uint8_t tag_res[TAG_BYTES];
+    aes_ll_gcm_read_tag(tag_res);
+    memcpy(tag, tag_res, tag_len);
+}
+
+
+#endif //SOC_AES_SUPPORT_GCM

+ 137 - 0
components/hal/esp32/include/hal/aes_ll.h

@@ -0,0 +1,137 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "soc/hwcrypto_reg.h"
+#include "soc/dport_access.h"
+#include "hal/aes_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief State of AES accelerator, busy or idle
+ *
+ */
+typedef enum {
+    ESP_AES_STATE_BUSY = 0, /* Transform in progress */
+    ESP_AES_STATE_IDLE,     /* AES accelerator is idle */
+} esp_aes_state_t;
+
+
+/**
+ * @brief Write the encryption/decryption key to hardware
+ *
+ * @param key Key to be written to the AES hardware
+ * @param key_word_len Number of words in the key
+ *
+ * @return Number of bytes written to hardware, used for fault injection check,
+ *         if a write was skipped then this sum is likely to be wrong
+ */
+static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
+{
+    /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
+    volatile uint8_t key_bytes_in_hardware = 0;
+    uint32_t *key_words = (uint32_t *)key;
+
+    for (int i = 0; i < key_word_len; i++) {
+        DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
+        key_bytes_in_hardware += 4;
+    }
+    return key_bytes_in_hardware;
+}
+
+/**
+ * @brief Sets the mode
+ *
+ * @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
+ * @param key_bytes Number of bytes in the key
+ */
+static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
+{
+    const uint32_t MODE_DECRYPT_BIT = 4;
+    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
+
+    /* See TRM for the mapping between keylength and mode bit */
+    DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
+}
+
+/**
+ * @brief Writes message block to AES hardware
+ *
+ * @param input Block to be written
+ */
+static inline void aes_ll_write_block(const uint8_t *input)
+{
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t i0;
+    uint32_t i1;
+    uint32_t i2;
+    uint32_t i3;
+
+    /* Storing i0,i1,i2,i3 in registers not an array
+    helps a lot with optimisations at -Os level */
+    i0 = input_words[0];
+    DPORT_REG_WRITE(AES_TEXT_BASE, i0);
+
+    i1 = input_words[1];
+    DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
+
+    i2 = input_words[2];
+    DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
+
+    i3 = input_words[3];
+    DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
+}
+
+/**
+ * @brief Read the AES block
+ *
+ * @note If a transform was ran then this is the output
+ *
+ * @param output the output of the transform, length = AES_BLOCK_BYTES
+ */
+static inline void aes_ll_read_block(void *output)
+{
+    uint32_t *output_words = (uint32_t *)output;
+    esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, AES_BLOCK_WORDS);
+}
+
+
+/**
+ * @brief Starts block transform
+ *
+ */
+static inline void aes_ll_start_transform(void)
+{
+    DPORT_REG_WRITE(AES_START_REG, 1);
+}
+
+
+/**
+ * @brief Read state of AES accelerator
+ *
+ * @return esp_aes_state_t
+ */
+static inline esp_aes_state_t aes_ll_get_state(void)
+{
+    return DPORT_REG_READ(AES_IDLE_REG);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 235 - 0
components/hal/esp32c3/include/hal/aes_ll.h

@@ -0,0 +1,235 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdbool.h>
+#include "soc/hwcrypto_reg.h"
+#include "hal/aes_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief State of AES accelerator, busy, idle or done
+ *
+ */
+typedef enum {
+    ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
+    ESP_AES_STATE_BUSY,     /* Transform in progress */
+    ESP_AES_STATE_DONE,     /* Transform completed */
+} esp_aes_state_t;
+
+
+/**
+ * @brief Write the encryption/decryption key to hardware
+ *
+ * @param key Key to be written to the AES hardware
+ * @param key_word_len Number of words in the key
+ *
+ * @return volatile number of bytes written to hardware, used for fault injection check
+ */
+static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
+{
+    /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
+    volatile uint8_t key_in_hardware = 0;
+    uint32_t *key_words = (uint32_t *)key;
+
+    for (int i = 0; i < key_word_len; i++) {
+        REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
+        key_in_hardware += 4;
+    }
+    return key_in_hardware;
+}
+
+/**
+ * @brief Sets the mode
+ *
+ * @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
+ * @param key_bytes Number of bytes in the key
+ */
+static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
+{
+    const uint32_t MODE_DECRYPT_BIT = 4;
+    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
+
+    /* See TRM for the mapping between keylength and mode bit */
+    REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
+}
+
+/**
+ * @brief Writes message block to AES hardware
+ *
+ * @param input Block to be written
+ */
+static inline void aes_ll_write_block(const void *input)
+{
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t i0, i1, i2, i3;
+
+    /* Storing i0,i1,i2,i3 in registers, not in an array
+    helps a lot with optimisations at -Os level */
+    i0 = input_words[0];
+    REG_WRITE(AES_TEXT_IN_BASE, i0);
+
+    i1 = input_words[1];
+    REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
+
+    i2 = input_words[2];
+    REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
+
+    i3 = input_words[3];
+    REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
+}
+
+/**
+ * @brief Read the AES block
+ *
+ * @param output the output of the transform, length = AES_BLOCK_BYTES
+ */
+static inline void aes_ll_read_block(void *output)
+{
+    uint32_t *output_words = (uint32_t *)output;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
+        output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
+    }
+}
+
+/**
+ * @brief Starts block transform
+ *
+ */
+static inline void aes_ll_start_transform(void)
+{
+    REG_WRITE(AES_TRIGGER_REG, 1);
+}
+
+
+/**
+ * @brief Read state of AES accelerator
+ *
+ * @return esp_aes_state_t
+ */
+static inline esp_aes_state_t aes_ll_get_state(void)
+{
+    return REG_READ(AES_STATE_REG);
+}
+
+
+/**
+ * @brief Set mode of operation
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param mode
+ */
+static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
+{
+    REG_WRITE(AES_BLOCK_MODE_REG, mode);
+}
+
+/**
+ * @brief Set AES-CTR counter to INC32
+ *
+ * @note Only affects AES-CTR mode
+ *
+ */
+static inline void aes_ll_set_inc(void)
+{
+    REG_WRITE(AES_INC_SEL_REG, 0);
+}
+
+/**
+ * @brief Release the DMA
+ *
+ */
+static inline void aes_ll_dma_exit(void)
+{
+    REG_WRITE(AES_DMA_EXIT_REG, 0);
+}
+
+/**
+ * @brief Sets the number of blocks to be transformed
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param num_blocks Number of blocks to transform
+ */
+static inline void aes_ll_set_num_blocks(size_t num_blocks)
+{
+    REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
+}
+
+/*
+ * Write IV to hardware iv registers
+ */
+static inline void aes_ll_set_iv(const uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
+
+    for (int i = 0; i < IV_WORDS; i++ ) {
+        REG_WRITE(&reg_addr_buf[i], iv_words[i]);
+    }
+}
+
+/*
+ * Read IV from hardware iv registers
+ */
+static inline void aes_ll_read_iv(uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < IV_WORDS; i++) {
+        iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
+    }
+}
+
+/**
+ * @brief Enable or disable DMA mode
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_dma_enable(bool enable)
+{
+    REG_WRITE(AES_DMA_ENABLE_REG, enable);
+}
+
+/**
+ * @brief Enable or disable transform completed interrupt
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_interrupt_enable(bool enable)
+{
+    REG_WRITE(AES_INT_ENA_REG, enable);
+}
+
+/**
+ * @brief Clears the interrupt
+ *
+ */
+static inline void aes_ll_interrupt_clear(void)
+{
+    REG_WRITE(AES_INT_CLR_REG, 1);
+}
+
+
+#ifdef __cplusplus
+}
+#endif

+ 317 - 0
components/hal/esp32s2/include/hal/aes_ll.h

@@ -0,0 +1,317 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdbool.h>
+#include "soc/hwcrypto_reg.h"
+#include "hal/aes_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief State of AES accelerator, busy, idle or done
+ *
+ */
+typedef enum {
+    ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
+    ESP_AES_STATE_BUSY,     /* Transform in progress */
+    ESP_AES_STATE_DONE,     /* Transform completed */
+} esp_aes_state_t;
+
+
+/**
+ * @brief Write the encryption/decryption key to hardware
+ *
+ * @param key Key to be written to the AES hardware
+ * @param key_word_len Number of words in the key
+ *
+ * @return Number of bytes written to hardware, used for fault injection check
+ */
+static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
+{
+    /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
+    volatile uint8_t key_in_hardware = 0;
+    uint32_t *key_words = (uint32_t *)key;
+
+    for (int i = 0; i < key_word_len; i++) {
+        REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
+        key_in_hardware += 4;
+    }
+    return key_in_hardware;
+}
+
+/**
+ * @brief Sets the mode
+ *
+ * @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
+ * @param key_bytes Number of bytes in the key
+ */
+static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
+{
+    const uint32_t MODE_DECRYPT_BIT = 4;
+    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
+
+    /* See TRM for the mapping between keylength and mode bit */
+    REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
+}
+
+/**
+ * @brief Writes message block to AES hardware
+ *
+ * @param input Block to be written
+ */
+static inline void aes_ll_write_block(const void *input)
+{
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t i0, i1, i2, i3;
+
+    /* Storing i0,i1,i2,i3 in registers not an array
+    helps a lot with optimisations at -Os level */
+    i0 = input_words[0];
+    REG_WRITE(AES_TEXT_IN_BASE, i0);
+
+    i1 = input_words[1];
+    REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
+
+    i2 = input_words[2];
+    REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
+
+    i3 = input_words[3];
+    REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
+}
+
+/**
+ * @brief Read the AES block
+ *
+ * @param output the output of the transform, length = AES_BLOCK_BYTES
+ */
+static inline void aes_ll_read_block(void *output)
+{
+    uint32_t *output_words = (uint32_t *)output;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
+        output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
+    }
+}
+
+
+/**
+ * @brief Starts block transform
+ *
+ */
+static inline void aes_ll_start_transform(void)
+{
+    REG_WRITE(AES_TRIGGER_REG, 1);
+}
+
+/**
+ * @brief Continue a previous started transform
+ *
+ * @note Only used when doing GCM
+ */
+static inline void aes_ll_cont_transform(void)
+{
+    REG_WRITE(AES_CONTINUE_REG, 1);
+}
+
+/**
+ * @brief Read state of AES accelerator
+ *
+ * @return esp_aes_state_t
+ */
+static inline esp_aes_state_t aes_ll_get_state(void)
+{
+    return REG_READ(AES_STATE_REG);
+}
+
+
+/**
+ * @brief Set mode of operation
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param mode
+ */
+static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
+{
+    REG_WRITE(AES_BLOCK_MODE_REG, mode);
+}
+
+/**
+ * @brief Set AES-CTR counter to INC32
+ *
+ * @note Only affects AES-CTR mode
+ *
+ */
+static inline void aes_ll_set_inc(void)
+{
+    REG_WRITE(AES_INC_SEL_REG, 0);
+}
+
+/**
+ * @brief Release the DMA
+ *
+ */
+static inline void aes_ll_dma_exit(void)
+{
+    REG_WRITE(AES_DMA_EXIT_REG, 0);
+}
+
+/**
+ * @brief Sets the number of blocks to be transformed
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param num_blocks Number of blocks to transform
+ */
+static inline void aes_ll_set_num_blocks(size_t num_blocks)
+{
+    REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
+}
+
+/*
+ * Write IV to hardware iv registers
+ */
+static inline void aes_ll_set_iv(const uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
+
+    for (int i = 0; i < IV_WORDS; i++ ) {
+        REG_WRITE(&reg_addr_buf[i], iv_words[i]);
+    }
+}
+
+/*
+ * Read IV from hardware iv registers
+ */
+static inline void aes_ll_read_iv(uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < IV_WORDS; i++) {
+        iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
+    }
+}
+
+/**
+ * @brief Enable or disable DMA mode
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_dma_enable(bool enable)
+{
+    REG_WRITE(AES_DMA_ENABLE_REG, enable);
+}
+
+/**
+ * @brief Enable or disable transform completed interrupt
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_interrupt_enable(bool enable)
+{
+    REG_WRITE(AES_INT_ENA_REG, enable);
+}
+
+/**
+ * @brief Clears the interrupt
+ *
+ */
+static inline void aes_ll_interrupt_clear(void)
+{
+    REG_WRITE(AES_INT_CLR_REG, 1);
+}
+
+/**
+ * @brief Reads the AES-GCM hash sub-key H
+ *
+ * @param gcm_hash hash value
+ */
+static inline void aes_ll_gcm_read_hash(uint8_t *gcm_hash)
+{
+    uint32_t *hash_words = (uint32_t *)gcm_hash;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
+        hash_words[i] = REG_READ(AES_H_BASE + (i * REG_WIDTH));
+    }
+
+}
+
+/**
+ * @brief Sets the number of Additional Authenticated Data (AAD) blocks
+ *
+ * @note Only affects AES-GCM
+ *
+ * @param aad_num_blocks the number of Additional Authenticated Data (AAD) blocks
+ */
+static inline void aes_ll_gcm_set_aad_num_blocks(size_t aad_num_blocks)
+{
+    REG_WRITE(AES_AAD_BLOCK_NUM_REG, aad_num_blocks);
+}
+
+/**
+ * @brief Sets the J0 value, for more information see the GCM subchapter in the TRM
+ *
+ * @note Only affects AES-GCM
+ *
+ * @param j0 J0 value
+ */
+static inline void aes_ll_gcm_set_j0(const uint8_t *j0)
+{
+    uint32_t *j0_words = (uint32_t *)j0;
+    uint32_t *reg_addr_buf = (uint32_t *)(AES_J_BASE);
+
+    for (int i = 0; i < AES_BLOCK_WORDS; i++ ) {
+        REG_WRITE(&reg_addr_buf[i], j0_words[i]);
+    }
+}
+
+/**
+ * @brief Sets the number of effective bits of incomplete blocks in plaintext/cipertext.
+ *
+ * @note Only affects AES-GCM
+ *
+ * @param num_valid_bits the number of effective bits of incomplete blocks in plaintext/cipertext.
+ */
+static inline void aes_ll_gcm_set_num_valid_bit(size_t num_valid_bits)
+{
+    REG_WRITE(AES_BIT_VALID_NUM_REG, num_valid_bits);
+}
+
+/**
+ * @brief Read the tag after a AES-GCM transform
+ *
+ * @param tag Pointer to where to store the result with length TAG_WORDS
+ */
+static inline void aes_ll_gcm_read_tag(uint8_t *tag)
+{
+    uint32_t *tag_words = (uint32_t *)tag;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < TAG_WORDS; i++) {
+        tag_words[i] = REG_READ(AES_T_BASE + (i * REG_WIDTH));
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 31 - 7
components/hal/esp32s2/include/hal/crypto_dma_ll.h

@@ -19,29 +19,28 @@
  ******************************************************************************/
 #pragma once
 
-#include "soc/hwcrypto_reg.h"
-#include "soc/dport_reg.h"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#include "soc/hwcrypto_reg.h"
+#include "soc/dport_reg.h"
+
 typedef enum {
-    CRYPTO_DMA_AES = 0,
+    CRYPTO_DMA_AES= 0,
     CRYPTO_DMA_SHA,
 } crypto_dma_mode_t;
 
 /**
- * @brief Resets set the outlink
+ * @brief Resets the DMA
  *
  */
-static inline void crypto_dma_ll_outlink_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);
     CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
 }
 
-
 /**
  * @brief Selects the crypto DMA mode
  *
@@ -63,6 +62,17 @@ static inline void crypto_dma_ll_outlink_set(uint32_t outlink_addr)
     SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, outlink_addr & OUT_LINK_REG_OUTLINK_ADDR);
 }
 
+/**
+ * @brief Sets up the inlink for a transfer
+ *
+ * @param inlink_addr Address of the inlink buffer
+ */
+static inline void crypto_dma_ll_inlink_set(uint32_t inlink_addr)
+{
+    CLEAR_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_ADDR);
+    SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, inlink_addr & IN_LINK_REG_INLINK_ADDR);
+}
+
 /**
  * @brief Starts the outlink
  *
@@ -72,6 +82,20 @@ static inline void crypto_dma_ll_outlink_start(void)
     SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START);
 }
 
+/**
+ * @brief Starts the inlink
+ *
+ */
+static inline void crypto_dma_ll_inlink_start(void)
+{
+    SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_START);
+}
+
+static inline bool crypto_dma_ll_inlink_is_eof(void)
+{
+    return ((REG_READ(CRYPTO_DMA_INT_RAW_REG) & INT_RAW_IN_SUC_EOF) == INT_RAW_IN_SUC_EOF);
+}
+
 
 #ifdef __cplusplus
 }

+ 235 - 0
components/hal/esp32s3/include/hal/aes_ll.h

@@ -0,0 +1,235 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdbool.h>
+#include "soc/hwcrypto_reg.h"
+#include "hal/aes_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief State of AES accelerator, busy, idle or done
+ *
+ */
+typedef enum {
+    ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
+    ESP_AES_STATE_BUSY,     /* Transform in progress */
+    ESP_AES_STATE_DONE,     /* Transform completed */
+} esp_aes_state_t;
+
+
+/**
+ * @brief Write the encryption/decryption key to hardware
+ *
+ * @param key Key to be written to the AES hardware
+ * @param key_word_len Number of words in the key
+ *
+ * @return volatile number of bytes written to hardware, used for fault injection check
+ */
+static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
+{
+    /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
+    volatile uint8_t key_in_hardware = 0;
+    uint32_t *key_words = (uint32_t *)key;
+
+    for (int i = 0; i < key_word_len; i++) {
+        REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
+        key_in_hardware += 4;
+    }
+    return key_in_hardware;
+}
+
+/**
+ * @brief Sets the mode
+ *
+ * @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
+ * @param key_bytes Number of bytes in the key
+ */
+static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
+{
+    const uint32_t MODE_DECRYPT_BIT = 4;
+    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
+
+    /* See TRM for the mapping between keylength and mode bit */
+    REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
+}
+
+/**
+ * @brief Writes message block to AES hardware
+ *
+ * @param input Block to be written
+ */
+static inline void aes_ll_write_block(const void *input)
+{
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t i0, i1, i2, i3;
+
+    /* Storing i0,i1,i2,i3 in registers not an array
+    helps a lot with optimisations at -Os level */
+    i0 = input_words[0];
+    REG_WRITE(AES_TEXT_IN_BASE, i0);
+
+    i1 = input_words[1];
+    REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
+
+    i2 = input_words[2];
+    REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
+
+    i3 = input_words[3];
+    REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
+}
+
+/**
+ * @brief Read the AES block
+ *
+ * @param output the output of the transform, length = AES_BLOCK_BYTES
+ */
+static inline void aes_ll_read_block(void *output)
+{
+    uint32_t *output_words = (uint32_t *)output;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
+        output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
+    }
+}
+
+/**
+ * @brief Starts block transform
+ *
+ */
+static inline void aes_ll_start_transform(void)
+{
+    REG_WRITE(AES_TRIGGER_REG, 1);
+}
+
+
+/**
+ * @brief Read state of AES accelerator
+ *
+ * @return esp_aes_state_t
+ */
+static inline esp_aes_state_t aes_ll_get_state(void)
+{
+    return REG_READ(AES_STATE_REG);
+}
+
+
+/**
+ * @brief Set mode of operation
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param mode
+ */
+static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
+{
+    REG_WRITE(AES_BLOCK_MODE_REG, mode);
+}
+
+/**
+ * @brief Set AES-CTR counter to INC32
+ *
+ * @note Only affects AES-CTR mode
+ *
+ */
+static inline void aes_ll_set_inc(void)
+{
+    REG_WRITE(AES_INC_SEL_REG, 0);
+}
+
+/**
+ * @brief Release the DMA
+ *
+ */
+static inline void aes_ll_dma_exit(void)
+{
+    REG_WRITE(AES_DMA_EXIT_REG, 0);
+}
+
+/**
+ * @brief Sets the number of blocks to be transformed
+ *
+ * @note Only used for DMA transforms
+ *
+ * @param num_blocks Number of blocks to transform
+ */
+static inline void aes_ll_set_num_blocks(size_t num_blocks)
+{
+    REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
+}
+
+/*
+ * Write IV to hardware iv registers
+ */
+static inline void aes_ll_set_iv(const uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
+
+    for (int i = 0; i < IV_WORDS; i++ ) {
+        REG_WRITE(&reg_addr_buf[i], iv_words[i]);
+    }
+}
+
+/*
+ * Read IV from hardware iv registers
+ */
+static inline void aes_ll_read_iv(uint8_t *iv)
+{
+    uint32_t *iv_words = (uint32_t *)iv;
+    const size_t REG_WIDTH = sizeof(uint32_t);
+
+    for (size_t i = 0; i < IV_WORDS; i++) {
+        iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
+    }
+}
+
+/**
+ * @brief Enable or disable DMA mode
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_dma_enable(bool enable)
+{
+    REG_WRITE(AES_DMA_ENABLE_REG, enable);
+}
+
+/**
+ * @brief Enable or disable transform completed interrupt
+ *
+ * @param enable true to enable, false to disable.
+ */
+static inline void aes_ll_interrupt_enable(bool enable)
+{
+    REG_WRITE(AES_INT_ENA_REG, enable);
+}
+
+/**
+ * @brief Clears the interrupt
+ *
+ */
+static inline void aes_ll_interrupt_clear(void)
+{
+    REG_WRITE(AES_INT_CLR_REG, 1);
+}
+
+
+#ifdef __cplusplus
+}
+#endif

+ 15 - 2
components/hal/esp32s3/include/hal/gdma_ll.h

@@ -52,6 +52,19 @@ extern "C" {
 #define GDMA_LL_TRIG_SRC_SHA     (7)
 #define GDMA_LL_TRIG_SRC_ADC_DAC (8)
 
+typedef enum {
+    GDMA_LL_PERIPH_ID_SPI2 = 0,
+    GDMA_LL_PERIPH_ID_SPI3,
+    GDMA_LL_PERIPH_ID_UART,
+    GDMA_LL_PERIPH_ID_I2S0,
+    GDMA_LL_PERIPH_ID_I2S1,
+    GDMA_LL_PERIPH_ID_LCD_CAM,
+    GDMA_LL_PERIPH_ID_AES,
+    GDMA_LL_PERIPH_ID_SHA,
+    GDMA_LL_PERIPH_ID_ADC_DAC,
+} gdma_ll_periph_id_t;
+
+
 ///////////////////////////////////// Common /////////////////////////////////////////
 /**
  * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default
@@ -287,7 +300,7 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui
 /**
  * @brief Connect DMA RX channel to a given peripheral
  */
-static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id)
+static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_ll_periph_id_t periph_id)
 {
     dev->peri_sel[channel].peri_in_sel = periph_id;
 }
@@ -482,7 +495,7 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui
 /**
  * @brief Connect DMA TX channel to a given peripheral
  */
-static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id)
+static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_ll_periph_id_t periph_id)
 {
     dev->peri_sel[channel].peri_out_sel = periph_id;
 }

+ 162 - 0
components/hal/include/hal/aes_hal.h

@@ -0,0 +1,162 @@
+// Copyright 2020 Espressif Systems (shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*******************************************************************************
+ * NOTICE
+ * The hal is not public api, don't use in application code.
+ * See readme.md in soc/include/hal/readme.md
+ ******************************************************************************/
+
+#pragma once
+
+#include <stddef.h>
+#include <stdbool.h>
+#include "soc/lldesc.h"
+#include "soc/soc_caps.h"
+#include "hal/aes_types.h"
+#include "hal/aes_ll.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @brief Sets the key used for AES encryption/decryption
+ *
+ * @param key pointer to the key
+ * @param key_bytes number of bytes in key
+ * @param mode key mode, 0 : decrypt, 1: encrypt
+ *
+ * @return uint8_t number of key bytes written to hardware, used for fault injection check
+ */
+uint8_t aes_hal_setkey(const uint8_t *key, size_t key_bytes, int mode);
+
+/**
+ * @brief encrypts/decrypts a single block
+ *
+ * @param input_block input block, size of AES_BLOCK_BYTES
+ * @param output_block output block, size of AES_BLOCK_BYTES
+ */
+void aes_hal_transform_block(const void *input_block, void *output_block);
+
+#if SOC_AES_SUPPORT_DMA
+/**
+ * @brief Inits the AES mode of operation
+ *
+ * @param mode mode of operation, e.g. CTR or CBC
+ */
+void aes_hal_mode_init(esp_aes_mode_t mode);
+
+/**
+ * @brief Sets the initialization vector for the transform
+ *
+ * @note The same IV must never be reused with the same key
+ *
+ * @param iv the initialization vector, length = IV_BYTES (16 bytes)
+ */
+void aes_hal_set_iv(const uint8_t *iv);
+
+/**
+ * @brief Reads the initialization vector
+ *
+ * @param iv initialization vector read from HW, length = IV_BYTES (16 bytes)
+ */
+void aes_hal_read_iv(uint8_t *iv);
+
+/**
+ * @brief Busy waits until the DMA operation is done (descriptor owner is CPU)
+ *
+ * @param output pointer to inlink descriptor
+ */
+void aes_hal_wait_dma_done(lldesc_t *output);
+
+/**
+ * @brief Starts an already configured AES DMA transform
+ *
+ * @param input outlink descriptor for data to be written to the peripheral
+ * @param output inlink descriptor for data to be read from the peripheral
+ * @param num_blocks Number of blocks to transform
+ */
+void aes_hal_transform_dma_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks);
+
+/**
+ * @brief Finish up a AES DMA conversion, release DMA
+ *
+ */
+void aes_hal_transform_dma_finish(void);
+
+/**
+ * @brief Enable or disable transform completed interrupt
+ *
+ * @param enable true to enable, false to disable.
+ */
+#define aes_hal_interrupt_enable(enable) aes_ll_interrupt_enable(enable)
+
+/**
+ * @brief Clears the interrupt
+ *
+ */
+#define aes_hal_interrupt_clear() aes_ll_interrupt_clear()
+
+#if SOC_AES_SUPPORT_GCM
+/**
+ * @brief Calculates the Hash sub-key H0 needed to start AES-GCM
+ *
+ * @param gcm_hash the Hash sub-key H0 output
+ */
+void aes_hal_gcm_calc_hash(uint8_t *gcm_hash);
+
+/**
+ * @brief Initializes the AES hardware for AES-GCM
+ *
+ * @param aad_num_blocks the number of Additional Authenticated Data (AAD) blocks
+ * @param num_valid_bit the number of effective bits of incomplete blocks in plaintext/cipertext
+ */
+void aes_hal_gcm_init(size_t aad_num_blocks, size_t num_valid_bit);
+
+/**
+ * @brief Starts a AES-GCM transform
+ *
+ * @param input outlink descriptor for data to be written to the peripheral
+ * @param output inlink descriptor for data to be read from the perihperal
+ * @param num_blocks Number of blocks to transform
+ */
+void aes_hal_transform_dma_gcm_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks);
+
+/**
+ * @brief Sets the J0 value, for more information see the GCM subchapter in the TRM
+ *
+ * @note Only affects AES-GCM
+ *
+ * @param j0 J0 value
+ */
+#define aes_hal_gcm_set_j0(j0)  aes_ll_gcm_set_j0(j0)
+
+/**
+ * @brief Read the tag after a AES-GCM transform
+ *
+ * @param tag Pointer to where to store the result
+ * @param tag_length number of bytes to read into tag
+ */
+void aes_hal_gcm_read_tag(uint8_t *tag, size_t tag_len);
+
+#endif //SOC_AES_SUPPORT_GCM
+
+#endif //SOC_AES_SUPPORT_DMA
+
+
+#ifdef __cplusplus
+}
+#endif

+ 48 - 0
components/hal/include/hal/aes_types.h

@@ -0,0 +1,48 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+/* padlock.c and aesni.c rely on these values! */
+#define ESP_AES_ENCRYPT     1
+#define ESP_AES_DECRYPT     0
+
+
+/* DMA AES working modes*/
+typedef enum {
+    ESP_AES_BLOCK_MODE_ECB = 0,
+    ESP_AES_BLOCK_MODE_CBC,
+    ESP_AES_BLOCK_MODE_OFB,
+    ESP_AES_BLOCK_MODE_CTR,
+    ESP_AES_BLOCK_MODE_CFB8,
+    ESP_AES_BLOCK_MODE_CFB128,
+    ESP_AES_BLOCK_MODE_GCM,
+    ESP_AES_BLOCK_MODE_MAX,
+} esp_aes_mode_t;
+
+/* Number of bytes in an AES block */
+#define AES_BLOCK_BYTES     (16)
+/* Number of words in an AES block */
+#define AES_BLOCK_WORDS     (4)
+/* Number of bytes in an IV */
+#define IV_BYTES            (16)
+/* Number of words in an IV */
+#define IV_WORDS            (4)
+/* Number of bytes in a GCM tag block */
+#define TAG_BYTES           (16)
+/* Number of words in a GCM tag block */
+#define TAG_WORDS           (4)
+
+#define AES_128_KEY_BYTES   (128/8)
+#define AES_192_KEY_BYTES   (192/8)
+#define AES_256_KEY_BYTES   (256/8)

+ 2 - 3
components/hal/sha_hal.c

@@ -26,7 +26,6 @@
 #include "hal/crypto_dma_ll.h"
 #elif SOC_SHA_GENERAL_DMA
 #include "hal/gdma_ll.h"
-#define DMA_PERIPH_SHA 7
 #endif
 
 #define SHA1_STATE_LEN_WORDS    (160 / 32)
@@ -99,7 +98,7 @@ static inline void sha_hal_dma_init(lldesc_t *input)
     gdma_ll_tx_enable_data_burst(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false);
     gdma_ll_tx_enable_auto_write_back(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false);
 
-    gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, DMA_PERIPH_SHA);
+    gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, GDMA_LL_PERIPH_ID_SHA);
 
 #if SOC_GDMA_SUPPORT_EXTMEM
     /* Atleast 40 bytes when accessing external RAM */
@@ -124,7 +123,7 @@ static inline void sha_hal_dma_init(lldesc_t *input)
 static inline void sha_hal_dma_init(lldesc_t *input)
 {
     crypto_dma_ll_set_mode(CRYPTO_DMA_SHA);
-    crypto_dma_ll_outlink_reset();
+    crypto_dma_ll_reset();
 
     crypto_dma_ll_outlink_set((uint32_t)input);
     crypto_dma_ll_outlink_start();

+ 0 - 1
components/idf_test/include/esp32/idf_performance_target.h

@@ -2,7 +2,6 @@
 
 // AES-CBC hardware throughput (accounts for worst-case performance with PSRAM workaround)
 #define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC                            8.2
-#define IDF_PERFORMANCE_MIN_AES_GCM_THROUGHPUT_MBSEC                            0.5
 
 // SHA256 hardware throughput at 240MHz, threshold set lower than worst case
 #define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC                             8.0

+ 2 - 1
components/idf_test/include/esp32s2/idf_performance_target.h

@@ -1,7 +1,8 @@
 #pragma once
 
 #define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC                            43.0
-#define IDF_PERFORMANCE_MIN_AES_GCM_THROUGHPUT_MBSEC                            2.1
+#define IDF_PERFORMANCE_MIN_AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC                  30.0
+#define IDF_PERFORMANCE_MIN_AES_GCM_UPDATE_THROUGHPUT_MBSEC                     2.1
 
 // SHA256 hardware throughput at 240MHz, threshold set lower than worst case
 #define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC                             90.0

+ 8 - 2
components/mbedtls/CMakeLists.txt

@@ -84,16 +84,19 @@ target_sources(mbedtls PRIVATE ${mbedtls_target_sources})
 # Choose perihperal type
 if(CONFIG_IDF_TARGET_ESP32)
     set(SHA_PERIPHERAL_TYPE "parallel_engine")
+    set(AES_PERIPHERAL_TYPE "block")
 else()
     set(SHA_PERIPHERAL_TYPE "dma")
+    set(AES_PERIPHERAL_TYPE "dma")
 endif()
 
 target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c"
                                   "${COMPONENT_DIR}/port/esp_mem.c"
                                   "${COMPONENT_DIR}/port/esp_timing.c"
                                   "${COMPONENT_DIR}/port/sha/esp_sha.c"
-                                  "${COMPONENT_DIR}/port/esp_aes_xts.c"
-                                  "${COMPONENT_DIR}/port/${idf_target}/aes.c"
+                                  "${COMPONENT_DIR}/port/aes/esp_aes_xts.c"
+                                  "${COMPONENT_DIR}/port/aes/esp_aes_common.c"
+                                  "${COMPONENT_DIR}/port/aes/${AES_PERIPHERAL_TYPE}/esp_aes.c"
                                   "${COMPONENT_DIR}/port/sha/${SHA_PERIPHERAL_TYPE}/sha.c"
 )
 
@@ -121,6 +124,9 @@ if(CONFIG_MBEDTLS_HARDWARE_SHA)
     )
 endif()
 
+if(CONFIG_MBEDTLS_HARDWARE_GCM)
+    target_sources(mbedcrypto PRIVATE  "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c")
+endif()
 
 foreach(target ${mbedtls_targets})
     target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")

+ 1 - 1
components/mbedtls/component.mk

@@ -5,7 +5,7 @@
 
 COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include esp_crt_bundle/include
 
-COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET) port/sha port/sha/parallel_engine esp_crt_bundle
+COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET) port/sha port/sha/parallel_engine port/aes port/aes/block esp_crt_bundle
 
 COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o
 

+ 90 - 147
components/mbedtls/port/esp32/aes.c → components/mbedtls/port/aes/block/esp_aes.c

@@ -1,5 +1,5 @@
 /**
- * \brief AES block cipher, ESP32 hardware accelerated version
+ * \brief AES block cipher, ESP block hardware accelerated version
  * Based on mbedTLS FIPS-197 compliant version.
  *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -28,9 +28,11 @@
 #include <string.h>
 #include "mbedtls/aes.h"
 #include "mbedtls/platform_util.h"
-#include "esp32/aes.h"
+#include "aes/esp_aes.h"
 #include "soc/hwcrypto_periph.h"
 #include <sys/lock.h>
+#include "hal/aes_hal.h"
+#include "aes/esp_aes_internal.h"
 
 #include <freertos/FreeRTOS.h>
 
@@ -49,10 +51,6 @@
 */
 static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
 
-static inline bool valid_key_length(const esp_aes_context *ctx)
-{
-    return ctx->key_bytes == 128/8 || ctx->key_bytes == 192/8 || ctx->key_bytes == 256/8;
-}
 
 void esp_aes_acquire_hardware( void )
 {
@@ -70,73 +68,16 @@ void esp_aes_release_hardware( void )
     portEXIT_CRITICAL(&aes_spinlock);
 }
 
-void esp_aes_init( esp_aes_context *ctx )
-{
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
-
-void esp_aes_free( esp_aes_context *ctx )
-{
-    if ( ctx == NULL ) {
-        return;
-    }
-
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
-
 
 
-/*
- * AES key schedule (same for encryption or decryption, as hardware handles schedule)
- *
- */
-int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
-                    unsigned int keybits )
-{
-    if (keybits != 128 && keybits != 192 && keybits != 256) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-    ctx->key_bytes = keybits / 8;
-    memcpy(ctx->key, key, ctx->key_bytes);
-    ctx->key_in_hardware = 0;
-    return 0;
-}
-
-/*
- * Helper function to copy key from esp_aes_context buffer
- * to hardware key registers.
- *
- * Call only while holding esp_aes_acquire_hardware().
- */
-static void esp_aes_setkey_hardware(esp_aes_context *ctx, int mode)
-{
-    const uint32_t MODE_DECRYPT_BIT = 4;
-    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
-
-    ctx->key_in_hardware = 0;
-
-    for (int i = 0; i < ctx->key_bytes/4; ++i) {
-        DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
-        ctx->key_in_hardware += 4;
-    }
-
-    DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
-
-    /* Fault injection check: all words of key data should have been written to hardware */
-    if (ctx->key_in_hardware < 16
-        || ctx->key_in_hardware != ctx->key_bytes) {
-        abort();
-    }
-}
-
 /* Run a single 16 byte block of AES, using the hardware engine.
  *
  * Call only while holding esp_aes_acquire_hardware().
  */
 static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
 {
-    const uint32_t *input_words = (const uint32_t *)input;
     uint32_t i0, i1, i2, i3;
+    const uint32_t *input_words = (uint32_t *)input;
     uint32_t *output_words = (uint32_t *)output;
 
     /* If no key is written to hardware yet, either the user hasn't called
@@ -148,26 +89,12 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
         bzero(output, 16);
         return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
     }
-
-    /* Storing i0,i1,i2,i3 in registers not an array
-       helps a lot with optimisations at -Os level */
     i0 = input_words[0];
-    DPORT_REG_WRITE(AES_TEXT_BASE, i0);
-
     i1 = input_words[1];
-    DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
-
     i2 = input_words[2];
-    DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
-
     i3 = input_words[3];
-    DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
-
-    DPORT_REG_WRITE(AES_START_REG, 1);
-
-    while (DPORT_REG_READ(AES_IDLE_REG) != 1) { }
 
-    esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, 4);
+    aes_hal_transform_block(input, output);
 
     /* Physical security check: Verify the AES accelerator actually ran, and wasn't
        skipped due to external fault injection while starting the peripheral.
@@ -176,7 +103,7 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
 
        Bypassing this check requires at least one additional fault.
     */
-    if(i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
+    if (i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
         // calling zeroing functions to narrow the
         // window for a double-fault of the abort step, here
         memset(output, 0, 16);
@@ -187,12 +114,19 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
     return 0;
 }
 
+void esp_aes_encrypt(esp_aes_context *ctx,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
+{
+    esp_internal_aes_encrypt(ctx, input, output);
+}
+
 /*
  * AES-ECB block encryption
  */
-int esp_internal_aes_encrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
+int esp_internal_aes_encrypt(esp_aes_context *ctx,
+                             const unsigned char input[16],
+                             unsigned char output[16] )
 {
     int r;
 
@@ -202,19 +136,26 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
     r = esp_aes_block(ctx, input, output);
     esp_aes_release_hardware();
     return r;
 }
 
+void esp_aes_decrypt(esp_aes_context *ctx,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
+{
+    esp_internal_aes_decrypt(ctx, input, output);
+}
+
 /*
  * AES-ECB block decryption
  */
 
-int esp_internal_aes_decrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
+int esp_internal_aes_decrypt(esp_aes_context *ctx,
+                             const unsigned char input[16],
+                             unsigned char output[16] )
 {
     int r;
 
@@ -224,7 +165,7 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
     r = esp_aes_block(ctx, input, output);
     esp_aes_release_hardware();
     return r;
@@ -233,10 +174,10 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
 /*
  * AES-ECB block encryption/decryption
  */
-int esp_aes_crypt_ecb( esp_aes_context *ctx,
-                       int mode,
-                       const unsigned char input[16],
-                       unsigned char output[16] )
+int esp_aes_crypt_ecb(esp_aes_context *ctx,
+                      int mode,
+                      const unsigned char input[16],
+                      unsigned char output[16] )
 {
     int r;
 
@@ -246,7 +187,7 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, mode);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
     r = esp_aes_block(ctx, input, output);
     esp_aes_release_hardware();
 
@@ -257,14 +198,13 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
 /*
  * AES-CBC buffer encryption/decryption
  */
-int esp_aes_crypt_cbc( esp_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int esp_aes_crypt_cbc(esp_aes_context *ctx,
+                      int mode,
+                      size_t length,
+                      unsigned char iv[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
-    int i;
     uint32_t *output_words = (uint32_t *)output;
     const uint32_t *input_words = (const uint32_t *)input;
     uint32_t *iv_words = (uint32_t *)iv;
@@ -280,17 +220,18 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
 
-    esp_aes_setkey_hardware(ctx, mode);
 
     if ( mode == ESP_AES_DECRYPT ) {
         while ( length > 0 ) {
             memcpy(temp, input_words, 16);
             esp_aes_block(ctx, input_words, output_words);
 
-            for ( i = 0; i < 4; i++ ) {
-                output_words[i] = output_words[i] ^ iv_words[i];
-            }
+            output_words[0] = output_words[0] ^ iv_words[0];
+            output_words[1] = output_words[1] ^ iv_words[1];
+            output_words[2] = output_words[2] ^ iv_words[2];
+            output_words[3] = output_words[3] ^ iv_words[3];
 
             memcpy( iv_words, temp, 16 );
 
@@ -301,9 +242,10 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
     } else { // ESP_AES_ENCRYPT
         while ( length > 0 ) {
 
-            for ( i = 0; i < 4; i++ ) {
-                output_words[i] = input_words[i] ^ iv_words[i];
-            }
+            output_words[0] = input_words[0] ^ iv_words[0];
+            output_words[1] = input_words[1] ^ iv_words[1];
+            output_words[2] = input_words[2] ^ iv_words[2];
+            output_words[3] = input_words[3] ^ iv_words[3];
 
             esp_aes_block(ctx, output_words, output_words);
             memcpy( iv_words, output_words, 16 );
@@ -322,13 +264,13 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
 /*
  * AES-CFB128 buffer encryption/decryption
  */
-int esp_aes_crypt_cfb128( esp_aes_context *ctx,
-                          int mode,
-                          size_t length,
-                          size_t *iv_off,
-                          unsigned char iv[16],
-                          const unsigned char *input,
-                          unsigned char *output )
+int esp_aes_crypt_cfb128(esp_aes_context *ctx,
+                         int mode,
+                         size_t length,
+                         size_t *iv_off,
+                         unsigned char iv[16],
+                         const unsigned char *input,
+                         unsigned char *output )
 {
     int c;
     size_t n = *iv_off;
@@ -339,8 +281,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
 
     if ( mode == ESP_AES_DECRYPT ) {
         while ( length-- ) {
@@ -376,12 +317,12 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
 /*
  * AES-CFB8 buffer encryption/decryption
  */
-int esp_aes_crypt_cfb8( esp_aes_context *ctx,
-                        int mode,
-                        size_t length,
-                        unsigned char iv[16],
-                        const unsigned char *input,
-                        unsigned char *output )
+int esp_aes_crypt_cfb8(esp_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
 {
     unsigned char c;
     unsigned char ov[17];
@@ -392,8 +333,8 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
 
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
     while ( length-- ) {
         memcpy( ov, iv, 16 );
@@ -420,13 +361,13 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
 /*
  * AES-CTR buffer encryption/decryption
  */
-int esp_aes_crypt_ctr( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int esp_aes_crypt_ctr(esp_aes_context *ctx,
+                      size_t length,
+                      size_t *nc_off,
+                      unsigned char nonce_counter[16],
+                      unsigned char stream_block[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
     int c, i;
     size_t n = *nc_off;
@@ -437,17 +378,18 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
 
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
     while ( length-- ) {
         if ( n == 0 ) {
             esp_aes_block(ctx, nonce_counter, stream_block);
 
-            for ( i = 16; i > 0; i-- )
+            for ( i = 16; i > 0; i-- ) {
                 if ( ++nonce_counter[i - 1] != 0 ) {
                     break;
                 }
+            }
         }
         c = *input++;
         *output++ = (unsigned char)( c ^ stream_block[n] );
@@ -465,25 +407,25 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
 /*
  * AES-OFB (Output Feedback Mode) buffer encryption/decryption
  */
-int esp_aes_crypt_ofb( esp_aes_context *ctx,
-                           size_t length,
-                           size_t *iv_off,
-                           unsigned char iv[16],
-                           const unsigned char *input,
-                           unsigned char *output )
+int esp_aes_crypt_ofb(esp_aes_context *ctx,
+                      size_t length,
+                      size_t *iv_off,
+                      unsigned char iv[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
     int ret = 0;
     size_t n;
 
-    if ( ctx == NULL || iv_off == NULL || iv == NULL ||
-        input == NULL || output == NULL ) {
-            return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
+    if (ctx == NULL || iv_off == NULL || iv == NULL ||
+            input == NULL || output == NULL ) {
+        return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
     }
 
     n = *iv_off;
 
-    if( n > 15 ) {
-        return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+    if (n > 15) {
+        return (MBEDTLS_ERR_AES_BAD_INPUT_DATA);
     }
 
     if (!valid_key_length(ctx)) {
@@ -491,11 +433,12 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
     }
 
     esp_aes_acquire_hardware();
+    ctx->key_in_hardware = 0;
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
 
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
-    while( length-- ) {
-        if( n == 0 ) {
+    while (length--) {
+        if ( n == 0 ) {
             esp_aes_block(ctx, iv, iv);
         }
         *output++ =  *input++ ^ iv[n];
@@ -507,5 +450,5 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
 
     esp_aes_release_hardware();
 
-    return( ret );
+    return ( ret );
 }

+ 249 - 322
components/mbedtls/port/esp32s3/aes.c → components/mbedtls/port/aes/dma/esp_aes.c

@@ -1,5 +1,5 @@
 /**
- * \brief AES block cipher, ESP32-S2 hardware accelerated version
+ * \brief AES block cipher, ESP DMA hardware accelerated version
  * Based on mbedTLS FIPS-197 compliant version.
  *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -26,17 +26,8 @@
  *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  */
 
-#include <stdio.h>
 #include <string.h>
-#include <sys/lock.h>
 #include "mbedtls/aes.h"
-#include "esp32s3/aes.h"
-#include "soc/cpu.h"
-#include "soc/dport_reg.h"
-#include "soc/hwcrypto_reg.h"
-#include "soc/periph_defs.h"
-#include "esp32s3/rom/lldesc.h"
-#include "esp32s3/rom/cache.h"
 #include "esp_intr_alloc.h"
 #include "driver/periph_ctrl.h"
 #include "esp_log.h"
@@ -44,18 +35,31 @@
 #include "esp_heap_caps.h"
 #include "sys/param.h"
 #include "esp_pm.h"
-#include "soc/soc_memory_layout.h"
-#include "soc/gdma_reg.h"
-#include "soc/gdma_struct.h"
-#include "soc/extmem_reg.h"
+#include "esp_crypto_lock.h"
+#include "hal/aes_hal.h"
+#include "aes/esp_aes_internal.h"
+
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/cache.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/cache.h"
+#endif
+
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 
-#define AES_BLOCK_BYTES 16
-#define IV_WORDS        4
+#if SOC_AES_SUPPORT_GCM
+#include "aes/esp_aes_gcm.h"
+#endif
+
+#if SOC_AES_GENERAL_DMA
+#define AES_LOCK() esp_crypto_aes_lock_acquire()
+#define AES_RELEASE() esp_crypto_aes_lock_release()
+#elif SOC_AES_CRYPTO_DMA
+#define AES_LOCK() esp_crypto_dma_lock_acquire()
+#define AES_RELEASE() esp_crypto_dma_lock_release()
+#endif
 
-#define DMA_PERIPH_AES 6 /* DMA peripheral indexes */
-#define DMA_PERIPH_SHA 7
 /* Max size of each chunk to process when output buffer is in unaligned external ram
    must be a multiple of block size
 */
@@ -65,22 +69,6 @@
    busy-waiting, 30000 bytes is approx 0.5 ms */
 #define AES_DMA_INTR_TRIG_LEN 2000
 
-#define ESP_PUT_BE64(a, val)                                    \
-    do {                                                        \
-        *(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \
-    } while (0)
-
-
-/* DMA AES working modes*/
-typedef enum {
-    ESP_AES_BLOCK_MODE_ECB = 0,
-    ESP_AES_BLOCK_MODE_CBC,
-    ESP_AES_BLOCK_MODE_OFB,
-    ESP_AES_BLOCK_MODE_CTR,
-    ESP_AES_BLOCK_MODE_CFB8,
-    ESP_AES_BLOCK_MODE_CFB128,
-} esp_aes_mode_t;
-
 
 #if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT)
 static SemaphoreHandle_t op_complete_sem;
@@ -92,143 +80,50 @@ static esp_pm_lock_handle_t s_pm_sleep_lock;
 
 static const char *TAG = "esp-aes";
 
-static _lock_t s_aes_lock;
-
-static inline bool valid_key_length(const esp_aes_context *ctx)
-{
-    return ctx->key_bytes == 128 / 8  || ctx->key_bytes == 256 / 8;
-}
-
-
-void esp_aes_acquire_hardware( void )
-{
-    _lock_acquire(&s_aes_lock);
-
-    /* Enable AES hardware */
-    //periph_module_enable(PERIPH_AES_DMA_MODULE);
-    /* Enable AES hardware */
-    REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN);
-    /* Clear reset on digital signature unit,
-       otherwise AES unit is held in reset also. */
-    REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG,
-                SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST | SYSTEM_CRYPTO_DS_RST);
-}
-
-/* Function to disable AES and Crypto DMA clocks and release locks */
-void esp_aes_release_hardware( void )
-{
-    /* Disable AES hardware */
-    //periph_module_disable(PERIPH_AES_DMA_MODULE);
-    /* Disable AES hardware */
-    REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST);
-    /* Don't return other units to reset, as this pulls
-       reset on RSA & SHA units, respectively. */
-    REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN);
-
-    _lock_release(&s_aes_lock);
-}
-
-
-/* Function to init AES context to zero */
-void esp_aes_init( esp_aes_context *ctx )
-{
-    if ( ctx == NULL ) {
-        return;
-    }
-
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
-
-/* Function to clear AES context */
-void esp_aes_free( esp_aes_context *ctx )
+/* Append a descriptor to the chain, set head if chain empty */
+static inline void lldesc_append(lldesc_t **head, lldesc_t *item)
 {
-    if ( ctx == NULL ) {
+    lldesc_t *it;
+    if (*head == NULL) {
+        *head = item;
         return;
     }
 
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
+    it = *head;
 
-/*
- * AES key schedule (same for encryption or decryption, as hardware handles schedule)
- *
- */
-int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
-                    unsigned int keybits )
-{
-    if (keybits == 192) {
-        return MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE;
-    }
-    if (keybits != 128  && keybits != 256) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
+    while (it->empty != 0) {
+        it = (lldesc_t *)it->empty;
     }
-    ctx->key_bytes = keybits / 8;
-    memcpy(ctx->key, key, ctx->key_bytes);
-    ctx->key_in_hardware = 0;
-    return 0;
+    it->eof = 0;
+    it->empty = (uint32_t)item;
 }
 
-/*
- * Helper function to copy key from esp_aes_context buffer
- * to hardware key registers.
- *
- * Call only while holding esp_aes_acquire_hardware().
- */
-static void esp_aes_setkey_hardware( esp_aes_context *ctx, int crypt_mode)
-{
-    const uint32_t MODE_DECRYPT_BIT = 4;
-    unsigned mode_reg_base = (crypt_mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
-
-    ctx->key_in_hardware = 0;
-
-    for (int i = 0; i < ctx->key_bytes / 4; ++i) {
-        REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
-        ctx->key_in_hardware += 4;
-    }
-
-    REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
-
-    /* Fault injection check: all words of key data should have been written to hardware */
-    if (ctx->key_in_hardware < 16
-            || ctx->key_in_hardware != ctx->key_bytes) {
-        abort();
-    }
-}
-
-/*
- * Sets the AES DMA block mode (ECB, CBC, CFB, OFB, GCM, CTR)
- * and intializes the required registers for that working mode
- */
-static inline void esp_aes_mode_init(esp_aes_mode_t mode)
+void esp_aes_acquire_hardware( void )
 {
-    /* Set the algorithm mode CBC, CFB ... */
-    REG_WRITE(AES_BLOCK_MODE_REG, mode);
-
-    /* Presently hard-coding the INC function to 32 bit */
-    if (mode == ESP_AES_BLOCK_MODE_CTR) {
-        REG_WRITE(AES_INC_SEL_REG, 0);
-    }
+    /* Released by esp_aes_release_hardware()*/
+    AES_LOCK();
+
+    /* Enable AES and DMA hardware */
+#if SOC_AES_CRYPTO_DMA
+    periph_module_enable(PERIPH_AES_DMA_MODULE);
+#elif SOC_AES_GENERAL_DMA
+    periph_module_enable(PERIPH_AES_MODULE);
+    periph_module_enable(PERIPH_GDMA_MODULE);
+#endif
 }
 
-/*
- * Write IV to hardware iv registers
- */
-static inline void esp_aes_set_iv(uint8_t *iv)
+/* Function to disable AES and Crypto DMA clocks and release locks */
+void esp_aes_release_hardware( void )
 {
-    uint32_t *iv_words = (uint32_t *)iv;
-    uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
-
-    for (int i = 0; i < IV_WORDS; i++ ) {
-        REG_WRITE(&reg_addr_buf[i], iv_words[i]);
-    }
-}
+    /* Disable AES and DMA hardware */
+#if SOC_AES_CRYPTO_DMA
+    periph_module_disable(PERIPH_AES_DMA_MODULE);
+#elif SOC_AES_GENERAL_DMA
+    periph_module_disable(PERIPH_AES_MODULE);
+    periph_module_disable(PERIPH_GDMA_MODULE);
+#endif
 
-/*
- * Read IV from hardware iv registers
- */
-static inline void esp_aes_get_iv(uint8_t *iv)
-{
-    esp_dport_access_read_buffer((uint32_t *)iv, AES_IV_BASE, IV_WORDS);
+    AES_RELEASE();
 }
 
 
@@ -236,7 +131,7 @@ static inline void esp_aes_get_iv(uint8_t *iv)
 static IRAM_ATTR void esp_aes_complete_isr(void *arg)
 {
     BaseType_t higher_woken;
-    REG_WRITE(AES_INT_CLR_REG, 1);
+    aes_hal_interrupt_clear();
     xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
     if (higher_woken) {
         portYIELD_FROM_ISR();
@@ -245,8 +140,8 @@ static IRAM_ATTR void esp_aes_complete_isr(void *arg)
 
 static esp_err_t esp_aes_isr_initialise( void )
 {
-    REG_WRITE(AES_INT_CLR_REG, 1);
-    REG_WRITE(AES_INT_ENA_REG, 1);
+    aes_hal_interrupt_clear();
+    aes_hal_interrupt_enable(true);
     if (op_complete_sem == NULL) {
         op_complete_sem = xSemaphoreCreateBinary();
 
@@ -281,8 +176,6 @@ static esp_err_t esp_aes_isr_initialise( void )
 /* Wait for AES hardware block operation to complete */
 static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
 {
-    __attribute__((unused)) volatile uint32_t dma_done;
-
 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
     if (use_intr) {
         if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
@@ -297,76 +190,9 @@ static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
     }
 #endif
 
-    /* Checking this if interrupt is used also, to avoid
-       issues with AES fault injection
-    */
-    while (REG_READ(AES_STATE_REG) != AES_STATE_DONE) {
-    }
-
-
-    /* Wait for DMA write operation to complete */
-    while (1) {
-        dma_done = REG_READ(CRYPTO_DMA_INT_RAW_REG);
-        // Wait for ownership of buffer to be transferred back to CPU
-        if (  (output_desc->owner == 0) ) {
-            break;
-        }
-    }
+    aes_hal_wait_dma_done(output_desc);
 }
 
-/* Init DMA related registers for AES operation */
-static void esp_aes_dma_init(lldesc_t *input, lldesc_t *output)
-{
-    /* Enable DMA mode */
-    REG_WRITE(AES_DMA_ENABLE_REG, 1);
-    REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
-    REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
-    REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
-    REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
-
-    /* Initialize DMA registers - this is probably mostly one off initialization
-
-         Note: hardcoded to DMA channel 0
-      */
-    /* Note: burst mode has alignment requirements that we have not checked here */
-    GDMA.conf0[0].outdscr_burst_en = 0;
-    GDMA.conf0[0].indscr_burst_en = 0;
-    GDMA.conf0[0].out_data_burst_en = 0;
-    GDMA.conf0[0].in_data_burst_en = 0;
-
-    GDMA.peri_sel[0].peri_out_sel = DMA_PERIPH_AES;
-    GDMA.peri_sel[0].peri_in_sel = DMA_PERIPH_AES;
-
-    /* Set descriptor addresses: NOTE BACKWARDS AS DMA IN/OUT is reverse of AES in/out */
-    GDMA.out_link[0].addr = (uint32_t)input;
-    GDMA.in_link[0].addr = (uint32_t)output;
-
-    GDMA.sram_size[0].in_size = 3; /* 40 bytes, also minimum size for EDMA */
-    GDMA.sram_size[0].out_size = 3;
-    GDMA.conf1[0].in_ext_mem_bk_size = 0; // 16 bytes
-    GDMA.conf1[0].out_ext_mem_bk_size = 0; // 16 bytes
-
-    /*
-      printf("DESC HEAD pointers IN/outlink %p OUT/inlink / %p\n", in_desc_head, out_desc_head);
-
-      printf("before starting in_desc_head owner %d out_desc_head owner %d INT_RAW 0x%08x\n",
-      in_desc_head->owner,
-      out_desc_head->owner,
-      DMA.int_raw.val);
-
-    */
-
-    //REG_SET_BIT(EXTMEM_CACHE_MMU_OWNER_REG, 1<<23);  //mark PSRAM DCache as belonging to DMA
-
-    GDMA.conf0[0].in_rst = 1;
-    GDMA.conf0[0].in_rst = 0;
-    GDMA.conf0[0].out_rst = 1;
-    GDMA.conf0[0].out_rst = 0;
-
-    /* Start transfer */
-    GDMA.out_link[0].start = 1;
-    GDMA.in_link[0].start = 1;
-}
 
 static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out);
 
@@ -450,7 +276,7 @@ cleanup:
 static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out)
 {
     lldesc_t stream_in_desc, stream_out_desc;
-    lldesc_t *in_desc_head, *out_desc_head;
+    lldesc_t *in_desc_head = NULL, *out_desc_head = NULL;
     lldesc_t *block_desc = NULL, *block_in_desc, *block_out_desc;
     size_t lldesc_num;
     uint8_t stream_in[16] = {};
@@ -503,7 +329,6 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
             return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc);
         }
 
-
         /* Set up dma descriptors for input and output */
         lldesc_num = lldesc_get_required_num(block_bytes);
 
@@ -540,11 +365,6 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
     in_desc_head =  (block_bytes > 0) ? block_in_desc : &stream_in_desc;
     out_desc_head = (block_bytes > 0) ? block_out_desc : &stream_out_desc;
 
-    esp_aes_dma_init(in_desc_head, out_desc_head);
-
-    /* Write the number of blocks */
-    REG_WRITE(AES_BLOCK_NUM_REG, blocks);
-
 
 #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
     /* Only use interrupt for long AES operations */
@@ -557,15 +377,12 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
     } else
 #endif
     {
-        REG_WRITE(AES_INT_ENA_REG, 0);
+        aes_hal_interrupt_enable(false);
     }
 
-    /* Start AES operation */
-    REG_WRITE(AES_TRIGGER_REG, 1);
+    aes_hal_transform_dma_start(in_desc_head, out_desc_head, blocks);
     esp_aes_dma_wait_complete(use_intr, out_desc_head);
 
-
-
 #if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
     if (block_bytes > 0) {
         if (esp_ptr_external_ram(output)) {
@@ -574,9 +391,7 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
     }
 #endif
 
-    REG_WRITE(AES_DMA_EXIT_REG, 0);
-    /* Disable DMA mode */
-    REG_WRITE(AES_DMA_ENABLE_REG, 0);
+    aes_hal_transform_dma_finish();
 
     if (stream_bytes > 0) {
         memcpy(output + block_bytes, stream_out, stream_bytes);
@@ -589,6 +404,118 @@ cleanup:
 }
 
 
+#if SOC_AES_SUPPORT_GCM
+
+/* Encrypt/decrypt with AES-GCM the input using DMA */
+int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len)
+{
+    lldesc_t *in_desc_head = NULL, *out_desc_head = NULL, *len_desc = NULL;
+    lldesc_t stream_in_desc, stream_out_desc;
+    lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL;
+    size_t lldesc_num;
+    uint32_t len_buf[4] = {};
+    uint8_t stream_in[16] = {};
+    uint8_t stream_out[16] = {};
+    unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block
+    unsigned block_bytes = len - stream_bytes;     // bytes which are in a full block
+
+    unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0);
+
+    bool use_intr = false;
+    int ret = 0;
+
+    /* If no key is written to hardware yet, either the user hasn't called
+       mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
+       know which mode to use - or a fault skipped the
+       key write to hardware. Treat this as a fatal error and zero the output block.
+    */
+    if (ctx->key_in_hardware != ctx->key_bytes) {
+        bzero(output, len);
+        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+    }
+
+    /* Set up dma descriptors for input and output */
+    lldesc_num = lldesc_get_required_num(block_bytes);
+
+    /* Allocate both in and out descriptors to save a malloc/free per function call, add 1 for length descriptor */
+    block_desc = heap_caps_calloc( (lldesc_num * 2) + 1, sizeof(lldesc_t), MALLOC_CAP_DMA);
+    if (block_desc == NULL) {
+        ESP_LOGE(TAG, "Failed to allocate memory");
+        ret = -1;
+        goto cleanup;
+    }
+
+    block_in_desc = block_desc;
+    len_desc = block_desc + lldesc_num;
+    block_out_desc = block_desc + lldesc_num + 1;
+
+    if (aad_desc != NULL) {
+        lldesc_append(&in_desc_head, aad_desc);
+    }
+
+    if (block_bytes > 0) {
+        lldesc_setup_link(block_in_desc, input, block_bytes, 0);
+        lldesc_setup_link(block_out_desc, output, block_bytes, 0);
+
+        lldesc_append(&in_desc_head, block_in_desc);
+        lldesc_append(&out_desc_head, block_out_desc);
+    }
+
+    /* Any leftover bytes which are appended as an additional DMA list */
+    if (stream_bytes > 0) {
+        memcpy(stream_in, input + block_bytes, stream_bytes);
+
+        lldesc_setup_link(&stream_in_desc, stream_in, AES_BLOCK_BYTES, 0);
+        lldesc_setup_link(&stream_out_desc, stream_out, AES_BLOCK_BYTES, 0);
+
+        lldesc_append(&in_desc_head, &stream_in_desc);
+        lldesc_append(&out_desc_head, &stream_out_desc);
+    }
+
+
+    len_buf[1] = __builtin_bswap32(aad_len * 8);
+    len_buf[3] = __builtin_bswap32(len * 8);
+
+    len_desc->length = sizeof(len_buf);
+    len_desc->size = sizeof(len_buf);
+    len_desc->owner = 1;
+    len_desc->eof = 1;
+    len_desc->buf = (uint8_t *)len_buf;
+
+    lldesc_append(&in_desc_head, len_desc);
+
+#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
+    /* Only use interrupt for long AES operations */
+    if (len > AES_DMA_INTR_TRIG_LEN) {
+        use_intr = true;
+        if (esp_aes_isr_initialise() == ESP_FAIL) {
+            ret = -1;
+            goto cleanup;
+        }
+    } else
+#endif
+    {
+        aes_hal_interrupt_enable(false);
+    }
+
+    /* Start AES operation */
+    aes_hal_transform_dma_gcm_start(in_desc_head, out_desc_head, blocks);
+
+    esp_aes_dma_wait_complete(use_intr, out_desc_head);
+
+    aes_hal_transform_dma_finish();
+
+    if (stream_bytes > 0) {
+        memcpy(output + block_bytes, stream_out, stream_bytes);
+    }
+
+cleanup:
+    free(block_desc);
+    return ret;
+}
+
+#endif //SOC_AES_SUPPORT_GCM
+
 static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
                                   unsigned char *output )
 {
@@ -612,9 +539,9 @@ static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *inp
 /*
  * AES-ECB single block encryption
  */
-int esp_internal_aes_encrypt( esp_aes_context *ctx,
-                              const unsigned char input[16],
-                              unsigned char output[16] )
+int esp_internal_aes_encrypt(esp_aes_context *ctx,
+                             const unsigned char input[16],
+                             unsigned char output[16] )
 {
     int r;
 
@@ -628,17 +555,17 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
+    aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
     r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
     esp_aes_release_hardware();
 
     return r;
 }
 
-void esp_aes_encrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
+void esp_aes_encrypt(esp_aes_context *ctx,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
 {
     esp_internal_aes_encrypt(ctx, input, output);
 }
@@ -646,9 +573,9 @@ void esp_aes_encrypt( esp_aes_context *ctx,
 /*
  * AES-ECB single block decryption
  */
-int esp_internal_aes_decrypt( esp_aes_context *ctx,
-                              const unsigned char input[16],
-                              unsigned char output[16] )
+int esp_internal_aes_decrypt(esp_aes_context *ctx,
+                             const unsigned char input[16],
+                             unsigned char output[16] )
 {
     int r;
 
@@ -662,17 +589,17 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
+    aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
     r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
     esp_aes_release_hardware();
 
     return r;
 }
 
-void esp_aes_decrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
+void esp_aes_decrypt(esp_aes_context *ctx,
+                     const unsigned char input[16],
+                     unsigned char output[16] )
 {
     esp_internal_aes_decrypt(ctx, input, output);
 }
@@ -681,10 +608,10 @@ void esp_aes_decrypt( esp_aes_context *ctx,
 /*
  * AES-ECB block encryption/decryption
  */
-int esp_aes_crypt_ecb( esp_aes_context *ctx,
-                       int mode,
-                       const unsigned char input[16],
-                       unsigned char output[16] )
+int esp_aes_crypt_ecb(esp_aes_context *ctx,
+                      int mode,
+                      const unsigned char input[16],
+                      unsigned char output[16] )
 {
     int r;
 
@@ -698,8 +625,8 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, mode);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
+    aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
     r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
     esp_aes_release_hardware();
 
@@ -709,12 +636,12 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
 /*
  * AES-CBC buffer encryption/decryption
  */
-int esp_aes_crypt_cbc( esp_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int esp_aes_crypt_cbc(esp_aes_context *ctx,
+                      int mode,
+                      size_t length,
+                      unsigned char iv[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
     int r = 0;
     if (esp_aes_validate_input(ctx, input, output)) {
@@ -739,9 +666,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
 
     esp_aes_acquire_hardware();
     ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, mode);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_CBC);
-    esp_aes_set_iv(iv);
+    ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
+    aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
+    aes_hal_set_iv(iv);
 
     r = esp_aes_process_dma(ctx, input, output, length, NULL);
     if (r != 0) {
@@ -749,7 +676,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
         return r;
     }
 
-    esp_aes_get_iv(iv);
+    aes_hal_read_iv(iv);
     esp_aes_release_hardware();
 
     return r;
@@ -758,12 +685,12 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
 /*
  * AES-CFB8 buffer encryption/decryption
  */
-int esp_aes_crypt_cfb8( esp_aes_context *ctx,
-                        int mode,
-                        size_t length,
-                        unsigned char iv[16],
-                        const unsigned char *input,
-                        unsigned char *output )
+int esp_aes_crypt_cfb8(esp_aes_context *ctx,
+                       int mode,
+                       size_t length,
+                       unsigned char iv[16],
+                       const unsigned char *input,
+                       unsigned char *output )
 {
     unsigned char c;
     unsigned char ov[17];
@@ -792,11 +719,11 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
     if (block_bytes > 0) {
 
         ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, mode);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB8);
-        esp_aes_set_iv(iv);
+        ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
+        aes_hal_set_iv(iv);
         r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
-        esp_aes_get_iv(iv);
+        aes_hal_read_iv(iv);
 
         if (r != 0) {
             esp_aes_release_hardware();
@@ -811,8 +738,8 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
     // Process remaining bytes block-at-a-time in ECB mode
     if (length > 0) {
         ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, MBEDTLS_AES_ENCRYPT);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
+        ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
 
         while ( length-- ) {
             memcpy( ov, iv, 16 );
@@ -844,13 +771,13 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
 /*
  * AES-CFB128 buffer encryption/decryption
  */
-int esp_aes_crypt_cfb128( esp_aes_context *ctx,
-                          int mode,
-                          size_t length,
-                          size_t *iv_off,
-                          unsigned char iv[16],
-                          const unsigned char *input,
-                          unsigned char *output )
+int esp_aes_crypt_cfb128(esp_aes_context *ctx,
+                         int mode,
+                         size_t length,
+                         size_t *iv_off,
+                         unsigned char iv[16],
+                         const unsigned char *input,
+                         unsigned char *output )
 
 {
     uint8_t c;
@@ -898,9 +825,9 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
         stream_bytes = length % AES_BLOCK_BYTES;
         esp_aes_acquire_hardware();
         ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, mode);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB128);
-        esp_aes_set_iv(iv);
+        ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
+        aes_hal_set_iv(iv);
 
         r = esp_aes_process_dma(ctx, input, output, length, iv);
         if (r != 0) {
@@ -910,7 +837,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
 
         if (stream_bytes == 0) {
             // if we didn't need the partial 'stream block' then the new IV is in the IV register
-            esp_aes_get_iv(iv);
+            aes_hal_read_iv(iv);
         } else {
             // if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it),
             // In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
@@ -932,12 +859,12 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
  * AES-OFB (Output Feedback Mode) buffer encryption/decryption
  */
 
-int esp_aes_crypt_ofb( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int esp_aes_crypt_ofb(esp_aes_context *ctx,
+                      size_t length,
+                      size_t *iv_off,
+                      unsigned char iv[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
     int r = 0;
     size_t n;
@@ -971,9 +898,9 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
 
         esp_aes_acquire_hardware();
         ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_OFB);
-        esp_aes_set_iv(iv);
+        ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
+        aes_hal_set_iv(iv);
 
         r = esp_aes_process_dma(ctx, input, output, length, iv);
         if (r != 0) {
@@ -981,7 +908,7 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
             return r;
         }
 
-        esp_aes_get_iv(iv);
+        aes_hal_read_iv(iv);
         esp_aes_release_hardware();
     }
 
@@ -993,13 +920,13 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
 /*
  * AES-CTR buffer encryption/decryption
  */
-int esp_aes_crypt_ctr( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output )
+int esp_aes_crypt_ctr(esp_aes_context *ctx,
+                      size_t length,
+                      size_t *nc_off,
+                      unsigned char nonce_counter[16],
+                      unsigned char stream_block[16],
+                      const unsigned char *input,
+                      unsigned char *output )
 {
     int r = 0;
     size_t n;
@@ -1036,10 +963,10 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
 
         esp_aes_acquire_hardware();
         ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
+        ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
 
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CTR);
-        esp_aes_set_iv(nonce_counter);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
+        aes_hal_set_iv(nonce_counter);
 
         r = esp_aes_process_dma(ctx, input, output, length, stream_block);
 
@@ -1048,7 +975,7 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
             return r;
         }
 
-        esp_aes_get_iv(nonce_counter);
+        aes_hal_read_iv(nonce_counter);
 
         esp_aes_release_hardware();
 

+ 83 - 0
components/mbedtls/port/aes/esp_aes_common.c

@@ -0,0 +1,83 @@
+/**
+ * \brief AES block cipher, ESP hardware accelerated version, common
+ * Based on mbedTLS FIPS-197 compliant version.
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#include "aes/esp_aes_internal.h"
+#include "mbedtls/aes.h"
+#include "hal/aes_hal.h"
+#include "hal/aes_types.h"
+#include "soc/soc_caps.h"
+
+#include <string.h>
+#include "mbedtls/platform.h"
+
+bool valid_key_length(const esp_aes_context *ctx)
+{
+    bool valid_len = (ctx->key_bytes == AES_128_KEY_BYTES) || (ctx->key_bytes == AES_256_KEY_BYTES);
+
+#if SOC_AES_SUPPORT_AES_192
+    valid_len |= ctx->key_bytes == AES_192_KEY_BYTES;
+#endif
+
+    return valid_len;
+}
+
+
+void esp_aes_init( esp_aes_context *ctx )
+{
+    bzero( ctx, sizeof( esp_aes_context ) );
+}
+
+void esp_aes_free( esp_aes_context *ctx )
+{
+    if ( ctx == NULL ) {
+        return;
+    }
+
+    bzero( ctx, sizeof( esp_aes_context ) );
+}
+
+/*
+ * AES key schedule (same for encryption or decryption, as hardware handles schedule)
+ *
+ */
+int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits )
+{
+#if !SOC_AES_SUPPORT_AES_192
+    if (keybits == 192) {
+        return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+    }
+#endif
+    if (keybits != 128 && keybits != 192 && keybits != 256) {
+        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
+    }
+    ctx->key_bytes = keybits / 8;
+    memcpy(ctx->key, key, ctx->key_bytes);
+    ctx->key_in_hardware = 0;
+    return 0;
+}

+ 695 - 0
components/mbedtls/port/aes/esp_aes_gcm.c

@@ -0,0 +1,695 @@
+/**
+ * \brief GCM block cipher, ESP DMA hardware accelerated version
+ * Based on mbedTLS FIPS-197 compliant version.
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ */
+/*
+ *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+
+#include "soc/soc_caps.h"
+
+#if SOC_AES_SUPPORT_GCM
+
+#include "aes/esp_aes.h"
+#include "aes/esp_aes_gcm.h"
+#include "aes/esp_aes_internal.h"
+#include "hal/aes_hal.h"
+
+#include "esp_log.h"
+#include "mbedtls/aes.h"
+#include "esp_heap_caps.h"
+#include "soc/soc_memory_layout.h"
+
+#include <string.h>
+
+#define ESP_PUT_BE64(a, val)                                    \
+    do {                                                        \
+        *(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \
+    } while (0)
+
+/* For simplicity limit the maxium amount of aad bytes to a single DMA descriptor
+   This should cover all normal, e.g. mbedtls, use cases */
+#define ESP_AES_GCM_AAD_MAX_BYTES 4080
+
+static const char *TAG = "esp-aes-gcm";
+
+static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z);
+
+/*
+ * Calculates the Initial Counter Block, J0
+ * and copies to to the esp_gcm_context
+ */
+static void esp_gcm_derive_J0(esp_gcm_context *ctx)
+{
+    uint8_t len_buf[16];
+
+    memset(ctx->J0, 0, AES_BLOCK_BYTES);
+    memset(len_buf, 0, AES_BLOCK_BYTES);
+
+    /* If IV is 96 bits J0 = ( IV || 0^31 || 1 ) */
+    if (ctx->iv_len == 12) {
+        memcpy(ctx->J0, ctx->iv, ctx->iv_len);
+        ctx->J0[AES_BLOCK_BYTES - 1] |= 1;
+    } else {
+        /* For IV != 96 bit, J0 = GHASH(IV || 0[s+64] || [len(IV)]64) */
+        /* First calculate GHASH on IV */
+        esp_gcm_ghash(ctx, ctx->iv, ctx->iv_len, ctx->J0);
+        /* Next create 128 bit block which is equal to
+        64 bit 0 + iv length truncated to 64 bits */
+        ESP_PUT_BE64(len_buf + 8, ctx->iv_len * 8);
+        /*   Calculate GHASH on last block */
+        esp_gcm_ghash(ctx, len_buf, 16, ctx->J0);
+
+
+    }
+}
+
+
+/*
+ * Increment J0 as per GCM spec, by applying the Standard Incrementing
+   Function INC_32 to it.
+ * j is the counter which needs to be incremented which is
+ * copied to ctx->J0 after incrementing
+ */
+static void increment32_j0(esp_gcm_context *ctx, uint8_t *j)
+{
+    uint8_t j_len = AES_BLOCK_BYTES;
+    memcpy(j, ctx->J0, AES_BLOCK_BYTES);
+    if (j) {
+        for (uint32_t i = j_len; i > (j_len - 4); i--) {
+            if (++j[i - 1] != 0) {
+                break;
+            }
+        }
+        memcpy(ctx->J0, j, AES_BLOCK_BYTES);
+    }
+}
+
+/* Function to xor two data blocks */
+static void xor_data(uint8_t *d, const uint8_t *s)
+{
+    uint32_t *dst = (uint32_t *) d;
+    uint32_t *src = (uint32_t *) s;
+    *dst++ ^= *src++;
+    *dst++ ^= *src++;
+    *dst++ ^= *src++;
+    *dst++ ^= *src++;
+}
+
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
+        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
+        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
+        | ( (uint32_t) (b)[(i) + 3]       );            \
+}
+#endif
+
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i)                            \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/* Based on MbedTLS's implemenation
+ *
+ * Precompute small multiples of H, that is set
+ *      HH[i] || HL[i] = H times i,
+ * where i is seen as a field element as in [MGV], ie high-order bits
+ * correspond to low powers of P. The result is stored in the same way, that
+ * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
+ * corresponds to P^127.
+ */
+static int gcm_gen_table( esp_gcm_context *ctx )
+{
+    int i, j;
+    uint64_t hi, lo;
+    uint64_t vl, vh;
+    unsigned char *h;
+
+    h = ctx->H;
+
+    /* pack h as two 64-bits ints, big-endian */
+    GET_UINT32_BE( hi, h,  0  );
+    GET_UINT32_BE( lo, h,  4  );
+    vh = (uint64_t) hi << 32 | lo;
+
+    GET_UINT32_BE( hi, h,  8  );
+    GET_UINT32_BE( lo, h,  12 );
+    vl = (uint64_t) hi << 32 | lo;
+
+    /* 8 = 1000 corresponds to 1 in GF(2^128) */
+    ctx->HL[8] = vl;
+    ctx->HH[8] = vh;
+
+    /* 0 corresponds to 0 in GF(2^128) */
+    ctx->HH[0] = 0;
+    ctx->HL[0] = 0;
+
+    for ( i = 4; i > 0; i >>= 1 ) {
+        uint32_t T = ( vl & 1 ) * 0xe1000000U;
+        vl  = ( vh << 63 ) | ( vl >> 1 );
+        vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
+
+        ctx->HL[i] = vl;
+        ctx->HH[i] = vh;
+    }
+
+    for ( i = 2; i <= 8; i *= 2 ) {
+        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
+        vh = *HiH;
+        vl = *HiL;
+        for ( j = 1; j < i; j++ ) {
+            HiH[j] = vh ^ ctx->HH[j];
+            HiL[j] = vl ^ ctx->HL[j];
+        }
+    }
+
+    return ( 0 );
+}
+/*
+ * Shoup's method for multiplication use this table with
+ *      last4[x] = x times P^128
+ * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
+ */
+static const uint64_t last4[16] = {
+    0x0000, 0x1c20, 0x3840, 0x2460,
+    0x7080, 0x6ca0, 0x48c0, 0x54e0,
+    0xe100, 0xfd20, 0xd940, 0xc560,
+    0x9180, 0x8da0, 0xa9c0, 0xb5e0
+};
+/* Based on MbedTLS's implemenation
+ *
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
+static void gcm_mult( esp_gcm_context *ctx, const unsigned char x[16],
+                      unsigned char output[16] )
+{
+    int i = 0;
+    unsigned char lo, hi, rem;
+    uint64_t zh, zl;
+
+    lo = x[15] & 0xf;
+
+    zh = ctx->HH[lo];
+    zl = ctx->HL[lo];
+
+    for ( i = 15; i >= 0; i-- ) {
+        lo = x[i] & 0xf;
+        hi = x[i] >> 4;
+
+        if ( i != 15 ) {
+            rem = (unsigned char) zl & 0xf;
+            zl = ( zh << 60 ) | ( zl >> 4 );
+            zh = ( zh >> 4 );
+            zh ^= (uint64_t) last4[rem] << 48;
+            zh ^= ctx->HH[lo];
+            zl ^= ctx->HL[lo];
+
+        }
+
+        rem = (unsigned char) zl & 0xf;
+        zl = ( zh << 60 ) | ( zl >> 4 );
+        zh = ( zh >> 4 );
+        zh ^= (uint64_t) last4[rem] << 48;
+        zh ^= ctx->HH[hi];
+        zl ^= ctx->HL[hi];
+    }
+
+    PUT_UINT32_BE( zh >> 32, output, 0 );
+    PUT_UINT32_BE( zh, output, 4 );
+    PUT_UINT32_BE( zl >> 32, output, 8 );
+    PUT_UINT32_BE( zl, output, 12 );
+}
+
+
+
+/* Update the key value in gcm context */
+int esp_aes_gcm_setkey( esp_gcm_context *ctx,
+                        mbedtls_cipher_id_t cipher,
+                        const unsigned char *key,
+                        unsigned int keybits )
+{
+    if (keybits != 128 && keybits != 192 && keybits != 256) {
+        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
+    }
+
+
+    ctx->aes_ctx.key_bytes = keybits / 8;
+
+    memcpy(ctx->aes_ctx.key, key, ctx->aes_ctx.key_bytes);
+
+    return ( 0 );
+}
+
+
+/* AES-GCM GHASH calculation z = GHASH(x) using h0 hash key
+*/
+static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z)
+{
+
+    uint8_t tmp[AES_BLOCK_BYTES];
+
+    memset(tmp, 0, AES_BLOCK_BYTES);
+    /* GHASH(X) is calculated on input string which is multiple of 128 bits
+     * If input string bit length is not multiple of 128 bits it needs to
+     * be padded by 0
+     *
+     * Steps:
+     * 1. Let X1, X2, ... , Xm-1, Xm denote the unique sequence of blocks such
+     * that X = X1 || X2 || ... || Xm-1 || Xm.
+     * 2. Let Y0 be the “zero block,” 0128.
+     * 3. Fori=1,...,m,letYi =(Yi-1 ^ Xi)•H.
+     * 4. Return Ym
+     */
+
+    /* If input bit string is >= 128 bits, process full 128 bit blocks */
+    while (x_len >= AES_BLOCK_BYTES) {
+
+        xor_data(z, x);
+        gcm_mult(ctx, z, z);
+
+        x += AES_BLOCK_BYTES;
+        x_len -= AES_BLOCK_BYTES;
+    }
+
+    /* If input bit string is not multiple of 128 create last 128 bit
+     * block by padding necessary 0s
+     */
+    if (x_len) {
+        memcpy(tmp, x, x_len);
+        xor_data(z, tmp);
+        gcm_mult(ctx, z, z);
+    }
+}
+
+
+/* Function to init AES GCM context to zero */
+void esp_aes_gcm_init( esp_gcm_context *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+
+    bzero(ctx, sizeof(esp_gcm_context));
+
+    ctx->gcm_state = ESP_AES_GCM_STATE_INIT;
+}
+
+/* Function to clear AES-GCM context */
+void esp_aes_gcm_free( esp_gcm_context *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+    bzero(ctx, sizeof(esp_gcm_context));
+}
+
+/* Setup AES-GCM */
+int esp_aes_gcm_starts( esp_gcm_context *ctx,
+                        int mode,
+                        const unsigned char *iv,
+                        size_t iv_len,
+                        const unsigned char *aad,
+                        size_t aad_len )
+{
+    /* IV and AD are limited to 2^32 bits, so 2^29 bytes */
+    /* IV is not allowed to be zero length */
+    if ( iv_len == 0 ||
+            ( (uint32_t) iv_len  ) >> 29 != 0 ||
+            ( (uint32_t) aad_len ) >> 29 != 0 ) {
+        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
+    }
+
+    if (!ctx) {
+        ESP_LOGE(TAG, "No AES context supplied");
+        return -1;
+    }
+
+    if (!iv) {
+        ESP_LOGE(TAG, "No IV supplied");
+        return -1;
+    }
+
+    if ( (aad_len > 0) && !aad) {
+        ESP_LOGE(TAG, "No aad supplied");
+        return -1;
+    }
+
+    /* Initialize AES-GCM context */
+    memset(ctx->ghash, 0, sizeof(ctx->ghash));
+    ctx->data_len = 0;
+
+    ctx->iv = iv;
+    ctx->iv_len = iv_len;
+    ctx->aad = aad;
+    ctx->aad_len = aad_len;
+    ctx->mode = mode;
+
+    /* H and the lookup table are only generated once per ctx */
+    if (ctx->gcm_state == ESP_AES_GCM_STATE_INIT) {
+        /* Lock the AES engine to calculate ghash key H in hardware */
+        esp_aes_acquire_hardware();
+        ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode);
+        aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM);
+
+        aes_hal_gcm_calc_hash(ctx->H);
+
+        esp_aes_release_hardware();
+
+        gcm_gen_table(ctx);
+    }
+
+    ctx->gcm_state = ESP_AES_GCM_STATE_START;
+
+    /* Once H is obtained we need to derive J0 (Initial Counter Block) */
+    esp_gcm_derive_J0(ctx);
+
+    /* The initial counter block keeps updating during the esp_gcm_update call
+     * however to calculate final authentication tag T we need original J0
+     * so we make a copy here
+     */
+    memcpy(ctx->ori_j0, ctx->J0, 16);
+
+    esp_gcm_ghash(ctx, ctx->aad, ctx->aad_len, ctx->ghash);
+
+    return ( 0 );
+}
+
+/* Perform AES-GCM operation */
+int esp_aes_gcm_update( esp_gcm_context *ctx,
+                        size_t length,
+                        const unsigned char *input,
+                        unsigned char *output )
+{
+    size_t nc_off = 0;
+    uint8_t nonce_counter[AES_BLOCK_BYTES] = {0};
+    uint8_t stream[AES_BLOCK_BYTES] = {0};
+
+    if (!ctx) {
+        ESP_LOGE(TAG, "No GCM context supplied");
+        return -1;
+    }
+    if (!input) {
+        ESP_LOGE(TAG, "No input supplied");
+        return -1;
+    }
+    if (!output) {
+        ESP_LOGE(TAG, "No output supplied");
+        return -1;
+    }
+
+    if ( output > input && (size_t) ( output - input ) < length ) {
+        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
+    }
+    /* If this is the first time esp_gcm_update is getting called
+     * calculate GHASH on aad and preincrement the ICB
+     */
+    if (ctx->gcm_state == ESP_AES_GCM_STATE_START) {
+        /* Jo needs to be incremented first time, later the CTR
+         * operation will auto update it
+         */
+        increment32_j0(ctx, nonce_counter);
+        ctx->gcm_state = ESP_AES_GCM_STATE_UPDATE;
+    } else if (ctx->gcm_state == ESP_AES_GCM_STATE_UPDATE) {
+        memcpy(nonce_counter, ctx->J0, AES_BLOCK_BYTES);
+    }
+
+    /* Perform intermediate GHASH on "encrypted" data during decryption */
+    if (ctx->mode == ESP_AES_DECRYPT) {
+        esp_gcm_ghash(ctx, input, length, ctx->ghash);
+    }
+
+    /* Output = GCTR(J0, Input): Encrypt/Decrypt the input */
+    esp_aes_crypt_ctr(&ctx->aes_ctx, length, &nc_off, nonce_counter, stream, input, output);
+
+    /* ICB gets auto incremented after GCTR operation here so update the context */
+    memcpy(ctx->J0, nonce_counter, AES_BLOCK_BYTES);
+
+    /* Keep updating the length counter for final tag calculation */
+    ctx->data_len += length;
+
+    /* Perform intermediate GHASH on "encrypted" data during encryption*/
+    if (ctx->mode == ESP_AES_ENCRYPT) {
+        esp_gcm_ghash(ctx, output, length, ctx->ghash);
+    }
+
+    return 0;
+}
+
+/* Function to read the tag value */
+int esp_aes_gcm_finish( esp_gcm_context *ctx,
+                        unsigned char *tag,
+                        size_t tag_len )
+{
+    size_t nc_off = 0;
+    uint8_t len_block[AES_BLOCK_BYTES] = {0};
+
+    if ( tag_len > 16 || tag_len < 4 ) {
+        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
+    }
+
+    /* Calculate final GHASH on aad_len, data length */
+    ESP_PUT_BE64(len_block, ctx->aad_len * 8);
+    ESP_PUT_BE64(len_block + 8, ctx->data_len * 8);
+    esp_gcm_ghash(ctx, len_block, AES_BLOCK_BYTES, ctx->ghash);
+
+    /* Tag T = GCTR(J0, ) where T is truncated to tag_len */
+    esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, 0, ctx->ghash, tag);
+
+    return 0;
+}
+
+/* Due to restrictions in the hardware (e.g. need to do the whole conversion in one go),
+   some combinations of inputs are not supported */
+static bool esp_aes_gcm_input_support_hw_accel(size_t length, const unsigned char *aad, size_t aad_len,
+                                               const unsigned char *input, unsigned char *output)
+{
+    bool support_hw_accel = true;
+
+    if (aad_len > ESP_AES_GCM_AAD_MAX_BYTES) {
+        support_hw_accel = false;
+    } else if (!esp_ptr_dma_capable(aad) && aad_len > 0) {
+        /* aad in non internal DMA memory */
+        support_hw_accel = false;
+    } else if (!esp_ptr_dma_capable(input) && length > 0) {
+        /* input in non internal DMA memory */
+        support_hw_accel = false;
+    } else if (!esp_ptr_dma_capable(output) && length > 0) {
+        /* output in non internal DMA memory */
+        support_hw_accel = false;
+    } else if (length == 0) {
+        support_hw_accel = false;
+    }
+
+    return support_hw_accel;
+}
+
+static int esp_aes_gcm_crypt_and_tag_partial_hw( esp_gcm_context *ctx,
+        int mode,
+        size_t length,
+        const unsigned char *iv,
+        size_t iv_len,
+        const unsigned char *aad,
+        size_t aad_len,
+        const unsigned char *input,
+        unsigned char *output,
+        size_t tag_len,
+        unsigned char *tag )
+{
+    int ret = 0;
+
+    if ( ( ret = esp_aes_gcm_starts( ctx, mode, iv, iv_len, aad, aad_len ) ) != 0 ) {
+        return ( ret );
+    }
+
+    if ( ( ret = esp_aes_gcm_update( ctx, length, input, output ) ) != 0 ) {
+        return ( ret );
+    }
+
+    if ( ( ret = esp_aes_gcm_finish( ctx, tag, tag_len ) ) != 0 ) {
+        return ( ret );
+    }
+
+    return ret;
+}
+
+int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
+                               int mode,
+                               size_t length,
+                               const unsigned char *iv,
+                               size_t iv_len,
+                               const unsigned char *aad,
+                               size_t aad_len,
+                               const unsigned char *input,
+                               unsigned char *output,
+                               size_t tag_len,
+                               unsigned char *tag )
+{
+    int ret;
+    lldesc_t aad_desc[2] = {};
+    lldesc_t *aad_head_desc = NULL;
+    size_t remainder_bit;
+    uint8_t stream_in[AES_BLOCK_BYTES] = {};
+    unsigned stream_bytes = aad_len % AES_BLOCK_BYTES; // bytes which aren't in a full block
+    unsigned block_bytes = aad_len - stream_bytes;     // bytes which are in a full block
+
+    /* Due to hardware limition only certain cases are fully supported in HW */
+    if (!esp_aes_gcm_input_support_hw_accel(length, aad, aad_len, input, output)) {
+        return esp_aes_gcm_crypt_and_tag_partial_hw(ctx, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag);
+    }
+
+    /* Limit aad len to a single DMA descriptor to simplify DMA handling
+       In practice, e.g. with mbedtls the length of aad will always be short
+    */
+    if (aad_len > LLDESC_MAX_NUM_PER_DESC) {
+        return -1;
+    }
+    /* IV and AD are limited to 2^32 bits, so 2^29 bytes */
+    /* IV is not allowed to be zero length */
+    if ( iv_len == 0 ||
+            ( (uint32_t) iv_len  ) >> 29 != 0 ||
+            ( (uint32_t) aad_len ) >> 29 != 0 ) {
+        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
+    }
+
+    if (!ctx) {
+        ESP_LOGE(TAG, "No AES context supplied");
+        return -1;
+    }
+
+    if (!iv) {
+        ESP_LOGE(TAG, "No IV supplied");
+        return -1;
+    }
+
+    if ( (aad_len > 0) && !aad) {
+        ESP_LOGE(TAG, "No aad supplied");
+        return -1;
+    }
+
+    /* Initialize AES-GCM context */
+    memset(ctx->ghash, 0, sizeof(ctx->ghash));
+    ctx->data_len = 0;
+
+    ctx->iv = iv;
+    ctx->iv_len = iv_len;
+    ctx->aad = aad;
+    ctx->aad_len = aad_len;
+    ctx->mode = mode;
+
+    esp_aes_acquire_hardware();
+    ctx->aes_ctx.key_in_hardware = 0;
+    ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode);
+
+    if (block_bytes > 0) {
+        aad_desc[0].length = block_bytes;
+        aad_desc[0].size = block_bytes;
+        aad_desc[0].owner = 1;
+        aad_desc[0].buf = aad;
+    }
+
+    if (stream_bytes > 0) {
+        memcpy(stream_in, aad + block_bytes, stream_bytes);
+
+        aad_desc[0].empty = (uint32_t)&aad_desc[1];
+        aad_desc[1].length = AES_BLOCK_BYTES;
+        aad_desc[1].size = AES_BLOCK_BYTES;
+        aad_desc[1].owner = 1;
+        aad_desc[1].buf = stream_in;
+    }
+
+    if (block_bytes > 0) {
+        aad_head_desc = &aad_desc[0];
+    } else if (stream_bytes > 0) {
+        aad_head_desc = &aad_desc[1];
+    }
+
+    aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM);
+
+    /* See TRM GCM chapter for description of this calculation */
+    remainder_bit = (8 * length) % 128;
+    aes_hal_gcm_init( (aad_len + AES_BLOCK_BYTES - 1) / AES_BLOCK_BYTES, remainder_bit);
+    aes_hal_gcm_calc_hash(ctx->H);
+
+    gcm_gen_table(ctx);
+    esp_gcm_derive_J0(ctx);
+
+    aes_hal_gcm_set_j0(ctx->J0);
+
+    ret = esp_aes_process_dma_gcm(&ctx->aes_ctx, input, output, length, aad_head_desc, aad_len);
+
+    aes_hal_gcm_read_tag(tag, tag_len);
+
+    esp_aes_release_hardware();
+
+    return ( ret );
+}
+
+
+int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
+                              size_t length,
+                              const unsigned char *iv,
+                              size_t iv_len,
+                              const unsigned char *aad,
+                              size_t aad_len,
+                              const unsigned char *tag,
+                              size_t tag_len,
+                              const unsigned char *input,
+                              unsigned char *output )
+{
+    int ret;
+    unsigned char check_tag[16];
+    size_t i;
+    int diff;
+
+    if ( ( ret = esp_aes_gcm_crypt_and_tag( ctx, ESP_AES_DECRYPT, length,
+                                            iv, iv_len, aad, aad_len,
+                                            input, output, tag_len, check_tag ) ) != 0 ) {
+        return ( ret );
+    }
+
+    /* Check tag in "constant-time" */
+    for ( diff = 0, i = 0; i < tag_len; i++ ) {
+        diff |= tag[i] ^ check_tag[i];
+    }
+
+    if ( diff != 0 ) {
+        bzero( output, length );
+        return ( MBEDTLS_ERR_GCM_AUTH_FAILED );
+    }
+
+    return ( 0 );
+}
+
+#endif //SOC_AES_SUPPORT_GCM

+ 1 - 13
components/mbedtls/port/esp_aes_xts.c → components/mbedtls/port/aes/esp_aes_xts.c

@@ -38,19 +38,7 @@
 #include <sys/lock.h>
 #include "mbedtls/aes.h"
 
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/aes.h"
-#endif
-
-#if CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/aes.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/aes.h"
-#endif
-
-#if CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/aes.h"
-#endif
+#include "aes/esp_aes.h"
 
 void esp_aes_xts_init( esp_aes_xts_context *ctx )
 {

+ 0 - 1524
components/mbedtls/port/esp32s2/aes.c

@@ -1,1524 +0,0 @@
-/**
- * \brief AES block cipher, ESP32-S2 hardware accelerated version
- * Based on mbedTLS FIPS-197 compliant version.
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- */
-/*
- *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
- *
- *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
- *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/lock.h>
-#include "mbedtls/aes.h"
-#include "esp32s2/aes.h"
-#include "esp32s2/gcm.h"
-#include "soc/cpu.h"
-#include "soc/dport_reg.h"
-#include "soc/hwcrypto_reg.h"
-#include "soc/crypto_dma_reg.h"
-#include "soc/periph_defs.h"
-#include "esp32s2/rom/lldesc.h"
-#include "esp32s2/rom/cache.h"
-#include "esp_intr_alloc.h"
-#include "driver/periph_ctrl.h"
-#include "esp_log.h"
-#include "soc/lldesc.h"
-#include "esp_heap_caps.h"
-#include "sys/param.h"
-#include "esp_pm.h"
-#include "esp_crypto_lock.h"
-
-#include "freertos/FreeRTOS.h"
-#include "freertos/semphr.h"
-
-#define AES_BLOCK_BYTES 16
-#define IV_WORDS        4
-
-/* Max size of each chunk to process when output buffer is in unaligned external ram
-   must be a multiple of block size
-*/
-#define AES_MAX_CHUNK_WRITE_SIZE 1600
-
-/* Input over this length will yield and wait for interrupt instead of
-   busy-waiting, 30000 bytes is approx 0.5 ms */
-#define AES_DMA_INTR_TRIG_LEN 2000
-
-#define ESP_PUT_BE64(a, val)                                    \
-    do {                                                        \
-        *(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \
-    } while (0)
-
-
-/* DMA AES working modes*/
-typedef enum {
-    ESP_AES_BLOCK_MODE_ECB = 0,
-    ESP_AES_BLOCK_MODE_CBC,
-    ESP_AES_BLOCK_MODE_OFB,
-    ESP_AES_BLOCK_MODE_CTR,
-    ESP_AES_BLOCK_MODE_CFB8,
-    ESP_AES_BLOCK_MODE_CFB128,
-    ESP_AES_BLOCK_MODE_GCM,
-} esp_aes_mode_t;
-
-
-#if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT)
-static SemaphoreHandle_t op_complete_sem;
-#if defined(CONFIG_PM_ENABLE)
-static esp_pm_lock_handle_t s_pm_cpu_lock;
-static esp_pm_lock_handle_t s_pm_sleep_lock;
-#endif
-#endif
-
-static const char *TAG = "esp-aes";
-
-static inline bool valid_key_length(const esp_aes_context *ctx)
-{
-    return ctx->key_bytes == 128 / 8 || ctx->key_bytes == 192 / 8 || ctx->key_bytes == 256 / 8;
-}
-
-
-void esp_aes_acquire_hardware( void )
-{
-    /* Need to lock DMA since it is shared with SHA block */
-    esp_crypto_dma_lock_acquire();
-
-    /* Enable AES hardware */
-    periph_module_enable(PERIPH_AES_DMA_MODULE);
-}
-
-/* Function to disable AES and Crypto DMA clocks and release locks */
-void esp_aes_release_hardware( void )
-{
-    /* Disable AES hardware */
-    periph_module_disable(PERIPH_AES_DMA_MODULE);
-
-    esp_crypto_dma_lock_release();
-}
-
-
-/* Function to init AES context to zero */
-void esp_aes_init( esp_aes_context *ctx )
-{
-    if ( ctx == NULL ) {
-        return;
-    }
-
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
-
-/* Function to clear AES context */
-void esp_aes_free( esp_aes_context *ctx )
-{
-    if ( ctx == NULL ) {
-        return;
-    }
-
-    bzero( ctx, sizeof( esp_aes_context ) );
-}
-
-/*
- * AES key schedule (same for encryption or decryption, as hardware handles schedule)
- *
- */
-int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
-                    unsigned int keybits )
-{
-    if (keybits != 128 && keybits != 192 && keybits != 256) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-    ctx->key_bytes = keybits / 8;
-    memcpy(ctx->key, key, ctx->key_bytes);
-    ctx->key_in_hardware = 0;
-    return 0;
-}
-
-/*
- * Helper function to copy key from esp_aes_context buffer
- * to hardware key registers.
- *
- * Call only while holding esp_aes_acquire_hardware().
- */
-static void esp_aes_setkey_hardware( esp_aes_context *ctx, int crypt_mode)
-{
-    const uint32_t MODE_DECRYPT_BIT = 4;
-    unsigned mode_reg_base = (crypt_mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
-
-    ctx->key_in_hardware = 0;
-
-    for (int i = 0; i < ctx->key_bytes / 4; ++i) {
-        REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
-        ctx->key_in_hardware += 4;
-    }
-
-    REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
-
-    /* Fault injection check: all words of key data should have been written to hardware */
-    if (ctx->key_in_hardware < 16
-            || ctx->key_in_hardware != ctx->key_bytes) {
-        abort();
-    }
-}
-
-/*
- * Sets the AES DMA block mode (ECB, CBC, CFB, OFB, GCM, CTR)
- * and intializes the required registers for that working mode
- */
-static inline void esp_aes_mode_init(esp_aes_mode_t mode)
-{
-    /* Set the algorithm mode CBC, CFB ... */
-    REG_WRITE(AES_BLOCK_MODE_REG, mode);
-
-    /* Presently hard-coding the INC function to 32 bit */
-    if (mode == ESP_AES_BLOCK_MODE_CTR) {
-        REG_WRITE(AES_INC_SEL_REG, 0);
-    }
-}
-
-/*
- * Write IV to hardware iv registers
- */
-static inline void esp_aes_set_iv(uint8_t *iv)
-{
-    uint32_t *iv_words = (uint32_t*)iv;
-    uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
-
-    for (int i = 0; i<IV_WORDS; i++ ) {
-        REG_WRITE(&reg_addr_buf[i], iv_words[i]);
-    }
-}
-
-/*
- * Read IV from hardware iv registers
- */
-static inline void esp_aes_get_iv(uint8_t *iv)
-{
-    esp_dport_access_read_buffer((uint32_t*)iv, AES_IV_BASE, IV_WORDS);
-}
-
-
-#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
-static IRAM_ATTR void esp_aes_complete_isr(void *arg)
-{
-    BaseType_t higher_woken;
-    REG_WRITE(AES_INT_CLR_REG, 1);
-    xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
-    if (higher_woken) {
-        portYIELD_FROM_ISR();
-    }
-}
-
-static esp_err_t esp_aes_isr_initialise( void )
-{
-    REG_WRITE(AES_INT_CLR_REG, 1);
-    REG_WRITE(AES_INT_ENA_REG, 1);
-    if (op_complete_sem == NULL) {
-        op_complete_sem = xSemaphoreCreateBinary();
-
-        if (op_complete_sem == NULL) {
-            ESP_LOGE(TAG, "Failed to create intr semaphore");
-            return ESP_FAIL;
-        }
-
-        esp_intr_alloc(ETS_AES_INTR_SOURCE, 0, esp_aes_complete_isr, NULL, NULL);
-    }
-
-    /* AES is clocked proportionally to CPU clock, take power management lock */
-#ifdef CONFIG_PM_ENABLE
-    if (s_pm_cpu_lock == NULL) {
-        if (esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "aes_sleep", &s_pm_sleep_lock) != ESP_OK) {
-            ESP_LOGE(TAG, "Failed to create PM sleep lock");
-            return ESP_FAIL;
-        }
-        if (esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "aes_cpu", &s_pm_cpu_lock) != ESP_OK) {
-            ESP_LOGE(TAG, "Failed to create PM CPU lock");
-            return ESP_FAIL;
-        }
-    }
-    esp_pm_lock_acquire(s_pm_cpu_lock);
-    esp_pm_lock_acquire(s_pm_sleep_lock);
-#endif
-
-    return ESP_OK;
-}
-#endif // CONFIG_MBEDTLS_AES_USE_INTERRUPT
-
-/* Wait for AES hardware block operation to complete */
-static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
-{
-    volatile uint32_t dma_done;
-
-#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
-    if (use_intr) {
-        if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
-            /* indicates a fundamental problem with driver */
-            ESP_LOGE("AES", "Timed out waiting for completion of AES Interrupt");
-            abort();
-        }
-#ifdef CONFIG_PM_ENABLE
-        esp_pm_lock_release(s_pm_cpu_lock);
-        esp_pm_lock_release(s_pm_sleep_lock);
-#endif  // CONFIG_PM_ENABLE
-    }
-#endif
-
-    /* Checking this if interrupt is used also, to avoid
-       issues with AES fault injection
-    */
-    while (REG_READ(AES_STATE_REG) != AES_STATE_DONE) {
-    }
-
-
-    /* Wait for DMA write operation to complete */
-    while (1) {
-        dma_done = REG_READ(CRYPTO_DMA_INT_RAW_REG);
-        // Wait for ownership of buffer to be transferred back to CPU
-        if ( ((dma_done & INT_RAW_IN_SUC_EOF) == INT_RAW_IN_SUC_EOF) && (output_desc->owner == 0) ) {
-            break;
-        }
-    }
-}
-
-/* Init DMA related registers for AES operation */
-static void esp_aes_dma_init(lldesc_t *input, lldesc_t *output)
-{
-    /* Enable DMA mode */
-    REG_WRITE(AES_DMA_ENABLE_REG, 1);
-
-    /* Reset DMA */
-    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_IN_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
-
-    /* Set DMA for AES Use */
-    REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 0);
-
-    /* Set descriptors */
-    CLEAR_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_ADDR);
-    SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, ((uint32_t)(input))&OUT_LINK_REG_OUTLINK_ADDR);
-    CLEAR_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_ADDR);
-    SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, ((uint32_t)(output))&IN_LINK_REG_INLINK_ADDR);
-
-    /* Start transfer */
-    SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START);
-    SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_START);
-}
-
-static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out);
-
-
-/* Output buffers in external ram needs to be 16-byte aligned and DMA cant access input in the iCache mem range,
-   reallocate them into internal memory and encrypt in chunks to avoid
-   having to malloc too big of a buffer
-*/
-
-static int esp_aes_process_dma_ext_ram(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out, bool realloc_input, bool realloc_output)
-{
-    size_t chunk_len;
-    int ret = 0;
-    int offset = 0;
-    unsigned char *input_buf = NULL;
-    unsigned char *output_buf = NULL;
-    const unsigned char *dma_input;
-    chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len);
-
-    if (realloc_input) {
-        input_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA);
-
-        if (input_buf == NULL) {
-            ESP_LOGE(TAG, "Failed to allocate memory");
-            ret = -1;
-            goto cleanup;
-        }
-    }
-
-    if (realloc_output) {
-        output_buf = heap_caps_malloc(chunk_len, MALLOC_CAP_DMA);
-
-        if (output_buf == NULL) {
-            ESP_LOGE(TAG, "Failed to allocate memory");
-            ret = -1;
-            goto cleanup;
-        }
-    } else {
-        output_buf = output;
-    }
-
-    while (len) {
-        chunk_len = MIN(AES_MAX_CHUNK_WRITE_SIZE, len);
-
-        /* If input needs realloc then copy it, else use the input with offset*/
-        if (realloc_input) {
-            memcpy(input_buf, input + offset, chunk_len);
-            dma_input = input_buf;
-        } else {
-            dma_input = input + offset;
-        }
-
-        if (esp_aes_process_dma(ctx, dma_input, output_buf, chunk_len, stream_out) != 0) {
-            ret = -1;
-            goto cleanup;
-        }
-
-        if (realloc_output) {
-            memcpy(output + offset, output_buf, chunk_len);
-        } else {
-            output_buf = output + offset + chunk_len;
-        }
-
-        len -= chunk_len;
-        offset += chunk_len;
-    }
-
-cleanup:
-
-     if (realloc_input) {
-         free(input_buf);
-     }
-     if (realloc_output) {
-         free(output_buf);
-     }
-
-    return ret;
-}
-
-/* Encrypt/decrypt the input using DMA */
-static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out)
-{
-    lldesc_t stream_in_desc, stream_out_desc;
-    lldesc_t *in_desc_head, *out_desc_head;
-    lldesc_t *block_desc = NULL, *block_in_desc, *block_out_desc;
-    size_t lldesc_num;
-    uint8_t stream_in[16] = {};
-    unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block
-    unsigned block_bytes = len - stream_bytes;     // bytes which are in a full block
-    unsigned char *non_icache_input = NULL;
-    unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0);
-    bool use_intr = false;
-    bool input_needs_realloc = false;
-    bool output_needs_realloc = false;
-    int ret = 0;
-
-    assert(len > 0); // caller shouldn't ever have len set to zero
-    assert(stream_bytes == 0 || stream_out != NULL); // stream_out can be NULL if we're processing full block(s)
-
-    /* If no key is written to hardware yet, either the user hasn't called
-       mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
-       know which mode to use - or a fault skipped the
-       key write to hardware. Treat this as a fatal error and zero the output block.
-    */
-    if (ctx->key_in_hardware != ctx->key_bytes) {
-        bzero(output, len);
-        return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
-    }
-
-    if (block_bytes > 0) {
-        /* Flush cache if input in external ram */
-#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
-        if (esp_ptr_external_ram(input)) {
-            Cache_WriteBack_All();
-        }
-        if (esp_ptr_external_ram(output)) {
-            if (((intptr_t)(output) & 0xF) != 0) {
-                // Non aligned ext-mem buffer
-                output_needs_realloc = true;
-            }
-        }
-#endif
-        /* DMA cannot access memory in the iCache range, copy input to internal ram */
-        if (!esp_ptr_dma_ext_capable(input) && !esp_ptr_dma_capable(input)) {
-            input_needs_realloc = true;
-        }
-
-        if (!esp_ptr_dma_ext_capable(output) && !esp_ptr_dma_capable(output)) {
-            output_needs_realloc = true;
-        }
-
-        /* If either input or output is unaccessible to the DMA then they need to be reallocated */
-        if (input_needs_realloc || output_needs_realloc) {
-            return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc);
-        }
-
-
-        /* Set up dma descriptors for input and output */
-        lldesc_num = lldesc_get_required_num(block_bytes);
-
-        /* Allocate both in and out descriptors to save a malloc/free per function call */
-        block_desc = heap_caps_malloc(sizeof(lldesc_t) * lldesc_num * 2, MALLOC_CAP_DMA);
-        if (block_desc == NULL) {
-            ESP_LOGE(TAG, "Failed to allocate memory");
-            ret = -1;
-            goto cleanup;
-        }
-
-        block_in_desc = block_desc;
-        block_out_desc = block_desc + lldesc_num;
-
-        lldesc_setup_link(block_desc, input, block_bytes, 0);
-        lldesc_setup_link(block_desc + lldesc_num, output, block_bytes, 0);
-    }
-
-    /* Any leftover bytes which are appended as an additional DMA list */
-    if (stream_bytes > 0) {
-        memcpy(stream_in, input + block_bytes, stream_bytes);
-
-        lldesc_setup_link(&stream_in_desc, stream_in, AES_BLOCK_BYTES, 0);
-        lldesc_setup_link(&stream_out_desc, stream_out, AES_BLOCK_BYTES, 0);
-
-        if (block_bytes > 0) {
-            /* Link with block descriptors*/
-            block_in_desc[lldesc_num - 1].empty = (uint32_t)&stream_in_desc;
-            block_out_desc[lldesc_num - 1].empty = (uint32_t)&stream_out_desc;
-        }
-    }
-
-    // block buffers are sent to DMA first, unless there aren't any
-    in_desc_head =  (block_bytes > 0) ? block_in_desc : &stream_in_desc;
-    out_desc_head = (block_bytes > 0) ? block_out_desc : &stream_out_desc;
-
-    esp_aes_dma_init(in_desc_head, out_desc_head);
-
-    /* Write the number of blocks */
-    REG_WRITE(AES_BLOCK_NUM_REG, blocks);
-
-
-#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
-    /* Only use interrupt for long AES operations */
-    if (len > AES_DMA_INTR_TRIG_LEN) {
-        use_intr = true;
-        if (esp_aes_isr_initialise() == ESP_FAIL) {
-            ret = -1;
-            goto cleanup;
-        }
-    } else
-#endif
-    {
-        REG_WRITE(AES_INT_ENA_REG, 0);
-    }
-
-    /* Start AES operation */
-    REG_WRITE(AES_TRIGGER_REG, 1);
-    esp_aes_dma_wait_complete(use_intr, out_desc_head);
-
-
-
-#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
-    if (block_bytes > 0) {
-        if (esp_ptr_external_ram(output)) {
-            Cache_Invalidate_DCache_All();
-        }
-    }
-#endif
-
-    REG_WRITE(AES_DMA_EXIT_REG, 0);
-    /* Disable DMA mode */
-    REG_WRITE(AES_DMA_ENABLE_REG, 0);
-
-    if (stream_bytes > 0) {
-        memcpy(output + block_bytes, stream_out, stream_bytes);
-    }
-
-cleanup:
-    free(non_icache_input);
-    free(block_desc);
-    return ret;
-}
-
-
-static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
-                       unsigned char *output )
-{
-    if (!ctx) {
-        ESP_LOGE(TAG, "No AES context supplied");
-        return -1;
-    }
-    if (!input) {
-        ESP_LOGE(TAG, "No input supplied");
-        return -1;
-    }
-    if (!output) {
-        ESP_LOGE(TAG, "No output supplied");
-        return -1;
-    }
-
-    return 0;
-}
-
-
-/*
- * AES-ECB single block encryption
- */
-int esp_internal_aes_encrypt( esp_aes_context *ctx,
-                              const unsigned char input[16],
-                              unsigned char output[16] )
-{
-    int r;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    esp_aes_acquire_hardware();
-    ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
-    r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
-    esp_aes_release_hardware();
-
-    return r;
-}
-
-void esp_aes_encrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
-{
-    esp_internal_aes_encrypt(ctx, input, output);
-}
-
-/*
- * AES-ECB single block decryption
- */
-int esp_internal_aes_decrypt( esp_aes_context *ctx,
-                              const unsigned char input[16],
-                              unsigned char output[16] )
-{
-    int r;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    esp_aes_acquire_hardware();
-    ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
-    r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
-    esp_aes_release_hardware();
-
-    return r;
-}
-
-void esp_aes_decrypt( esp_aes_context *ctx,
-                      const unsigned char input[16],
-                      unsigned char output[16] )
-{
-    esp_internal_aes_decrypt(ctx, input, output);
-}
-
-
-/*
- * AES-ECB block encryption/decryption
- */
-int esp_aes_crypt_ecb( esp_aes_context *ctx,
-                       int mode,
-                       const unsigned char input[16],
-                       unsigned char output[16] )
-{
-    int r;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    esp_aes_acquire_hardware();
-    ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, mode);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
-    r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
-    esp_aes_release_hardware();
-
-    return r;
-}
-
-/*
- * AES-CBC buffer encryption/decryption
- */
-int esp_aes_crypt_cbc( esp_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
-{
-    int r = 0;
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!iv) {
-        ESP_LOGE(TAG, "No IV supplied");
-        return -1;
-    }
-
-    /* For CBC input length should be multiple of
-     * AES BLOCK BYTES
-     * */
-    if ( (length % AES_BLOCK_BYTES) || (length == 0) ) {
-        return ERR_ESP_AES_INVALID_INPUT_LENGTH;
-    }
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    esp_aes_acquire_hardware();
-    ctx->key_in_hardware = 0;
-    esp_aes_setkey_hardware(ctx, mode);
-    esp_aes_mode_init(ESP_AES_BLOCK_MODE_CBC);
-    esp_aes_set_iv(iv);
-
-    r = esp_aes_process_dma(ctx, input, output, length, NULL);
-    if (r != 0) {
-        esp_aes_release_hardware();
-        return r;
-    }
-
-    esp_aes_get_iv(iv);
-    esp_aes_release_hardware();
-
-    return r;
-}
-
-/*
- * AES-CFB8 buffer encryption/decryption
- */
-int esp_aes_crypt_cfb8( esp_aes_context *ctx,
-                        int mode,
-                        size_t length,
-                        unsigned char iv[16],
-                        const unsigned char *input,
-                        unsigned char *output )
-{
-    unsigned char c;
-    unsigned char ov[17];
-    int r = 0;
-    size_t block_bytes = length - (length % AES_BLOCK_BYTES);
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!iv) {
-        ESP_LOGE(TAG, "No IV supplied");
-        return -1;
-    }
-
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    /* The DMA engine will only output correct IV if it runs
-       full blocks of input in CFB8 mode
-    */
-    esp_aes_acquire_hardware();
-
-    if (block_bytes > 0) {
-
-        ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, mode);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB8);
-        esp_aes_set_iv(iv);
-        r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
-        esp_aes_get_iv(iv);
-
-        if (r != 0) {
-            esp_aes_release_hardware();
-            return r;
-        }
-
-        length -= block_bytes;
-        input += block_bytes;
-        output += block_bytes;
-    }
-
-    // Process remaining bytes block-at-a-time in ECB mode
-    if (length > 0) {
-        ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, MBEDTLS_AES_ENCRYPT);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
-
-        while ( length-- ) {
-            memcpy( ov, iv, 16 );
-
-            r = esp_aes_process_dma(ctx, iv, iv, AES_BLOCK_BYTES, NULL);
-            if (r != 0) {
-                esp_aes_release_hardware();
-                return r;
-            }
-
-            if ( mode == MBEDTLS_AES_DECRYPT ) {
-                ov[16] = *input;
-            }
-
-            c = *output++ = ( iv[0] ^ *input++ );
-
-            if ( mode == MBEDTLS_AES_ENCRYPT ) {
-                ov[16] = c;
-            }
-            memcpy( iv, ov + 1, 16 );
-        }
-
-    }
-    esp_aes_release_hardware();
-
-    return r;
-}
-
-/*
- * AES-CFB128 buffer encryption/decryption
- */
-int esp_aes_crypt_cfb128( esp_aes_context *ctx,
-                          int mode,
-                          size_t length,
-                          size_t *iv_off,
-                          unsigned char iv[16],
-                          const unsigned char *input,
-                          unsigned char *output )
-
-{
-    uint8_t c;
-    int r = 0;
-    size_t stream_bytes = 0;
-    size_t n;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!iv) {
-        ESP_LOGE(TAG, "No IV supplied");
-        return -1;
-    }
-
-    if (!iv_off) {
-        ESP_LOGE(TAG, "No IV offset supplied");
-        return -1;
-    }
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    n = *iv_off;
-
-    /* First process the *iv_off bytes
-     * which are pending from the previous call to this API
-     */
-    while (n > 0 && length > 0) {
-        if (mode == MBEDTLS_AES_ENCRYPT) {
-            iv[n] = *output++ = *input++ ^ iv[n];
-        } else {
-            c = *input++;
-            *output++ = c ^ iv[n];
-            iv[n] = c;
-        }
-        n = (n + 1) % AES_BLOCK_BYTES;
-        length--;
-    }
-
-
-    if (length > 0) {
-        stream_bytes = length % AES_BLOCK_BYTES;
-        esp_aes_acquire_hardware();
-        ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, mode);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB128);
-        esp_aes_set_iv(iv);
-
-        r = esp_aes_process_dma(ctx, input, output, length, iv);
-        if (r != 0) {
-            esp_aes_release_hardware();
-            return r;
-        }
-
-        if (stream_bytes == 0) {
-            // if we didn't need the partial 'stream block' then the new IV is in the IV register
-            esp_aes_get_iv(iv);
-        } else {
-            // if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it),
-            // In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
-            // block uses ciphertext as its IV input)
-            //
-            // Note: It may be more efficient to not process the partial block via DMA in this case.
-            if (mode == MBEDTLS_AES_DECRYPT) {
-                memcpy(iv, input + length - stream_bytes, stream_bytes);
-            }
-        }
-        esp_aes_release_hardware();
-    }
-
-    *iv_off = n + stream_bytes;
-    return r;
-}
-
-/*
- * AES-OFB (Output Feedback Mode) buffer encryption/decryption
- */
-
-int esp_aes_crypt_ofb( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output )
-{
-    int r = 0;
-    size_t n;
-    size_t stream_bytes = 0;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!iv) {
-        ESP_LOGE(TAG, "No IV supplied");
-        return -1;
-    }
-
-    if (!iv_off) {
-        ESP_LOGE(TAG, "No IV offset supplied");
-        return -1;
-    }
-
-    n = *iv_off;
-
-    /* If there is an offset then use the output of the previous AES block
-        (the updated IV) to calculate the new output */
-    while (n > 0 && length > 0) {
-        *output++ = (*input++ ^ iv[n]);
-        n = (n + 1) & 0xF;
-        length--;
-    }
-    if (length > 0) {
-        stream_bytes = (length % AES_BLOCK_BYTES);
-
-        esp_aes_acquire_hardware();
-        ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_OFB);
-        esp_aes_set_iv(iv);
-
-        r = esp_aes_process_dma(ctx, input, output, length, iv);
-        if (r != 0) {
-            esp_aes_release_hardware();
-            return r;
-        }
-
-        esp_aes_get_iv(iv);
-        esp_aes_release_hardware();
-    }
-
-    *iv_off = n + stream_bytes;
-
-    return r;
-}
-
-/*
- * AES-CTR buffer encryption/decryption
- */
-int esp_aes_crypt_ctr( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output )
-{
-    int r = 0;
-    size_t n;
-
-    if (esp_aes_validate_input(ctx, input, output)) {
-        return -1;
-    }
-
-    if (!nonce_counter) {
-        ESP_LOGE(TAG, "No nonce supplied");
-        return -1;
-    }
-
-    if (!nc_off) {
-        ESP_LOGE(TAG, "No nonce offset supplied");
-        return -1;
-    }
-
-    n = *nc_off;
-
-    if (!valid_key_length(ctx)) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    /* Process any unprocessed bytes left in stream block from
-       last operation */
-    while (n > 0 && length > 0) {
-        *output++ = (unsigned char)(*input++ ^ stream_block[n]);
-        n = (n + 1) & 0xF;
-        length--;
-    }
-
-    if (length > 0) {
-
-        esp_aes_acquire_hardware();
-        ctx->key_in_hardware = 0;
-        esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
-
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_CTR);
-        esp_aes_set_iv(nonce_counter);
-
-        r = esp_aes_process_dma(ctx, input, output, length, stream_block);
-
-        if (r != 0) {
-            esp_aes_release_hardware();
-            return r;
-        }
-
-        esp_aes_get_iv(nonce_counter);
-
-        esp_aes_release_hardware();
-
-    }
-    *nc_off = n + (length % AES_BLOCK_BYTES);
-
-    return r;
-}
-
-static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z);
-
-/*
- * Calculates the Initial Counter Block, J0
- * and copies to to the esp_gcm_context
- */
-static void esp_gcm_derive_J0(esp_gcm_context *ctx)
-{
-    uint8_t len_buf[16];
-
-    memset(ctx->J0, 0, AES_BLOCK_BYTES);
-    memset(len_buf, 0, AES_BLOCK_BYTES);
-
-    /* If IV is 96 bits J0 = ( IV || 0^31 || 1 ) */
-    if (ctx->iv_len == 12) {
-        memcpy(ctx->J0, ctx->iv, ctx->iv_len);
-        ctx->J0[AES_BLOCK_BYTES - 1] |= 1;
-    } else {
-   /* For IV != 96 bit, J0 = GHASH(IV || 0[s+64] || [len(IV)]64) */
-        /* First calculate GHASH on IV */
-        esp_gcm_ghash(ctx, ctx->iv, ctx->iv_len, ctx->J0);
-        /* Next create 128 bit block which is equal to
-        64 bit 0 + iv length truncated to 64 bits */
-        ESP_PUT_BE64(len_buf + 8, ctx->iv_len * 8);
-        /*   Calculate GHASH on last block */
-        esp_gcm_ghash(ctx, len_buf, 16, ctx->J0);
-
-
-    }
-}
-
-
-/*
- * Increment J0 as per GCM spec, by applying the Standard Incrementing
-   Function INC_32 to it.
- * j is the counter which needs to be incremented which is
- * copied to ctx->J0 after incrementing
- */
-static void increment32_j0(esp_gcm_context *ctx, uint8_t *j)
-{
-    uint8_t j_len = AES_BLOCK_BYTES;
-    memcpy(j, ctx->J0, AES_BLOCK_BYTES);
-    if (j) {
-        for (uint32_t i = j_len; i > (j_len - 4); i--) {
-            if (++j[i - 1] != 0) {
-                break;
-            }
-        }
-        memcpy(ctx->J0, j, AES_BLOCK_BYTES);
-    }
-}
-
-/* Function to xor two data blocks */
-static void xor_data(uint8_t *d, const uint8_t *s)
-{
-    uint32_t *dst = (uint32_t *) d;
-    uint32_t *src = (uint32_t *) s;
-    *dst++ ^= *src++;
-    *dst++ ^= *src++;
-    *dst++ ^= *src++;
-    *dst++ ^= *src++;
-}
-
-
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_UINT32_BE
-#define GET_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )             \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
-        | ( (uint32_t) (b)[(i) + 3]       );            \
-}
-#endif
-
-#ifndef PUT_UINT32_BE
-#define PUT_UINT32_BE(n,b,i)                            \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
-}
-#endif
-
-/* Based on MbedTLS's implemenation
- *
- * Precompute small multiples of H, that is set
- *      HH[i] || HL[i] = H times i,
- * where i is seen as a field element as in [MGV], ie high-order bits
- * correspond to low powers of P. The result is stored in the same way, that
- * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
- * corresponds to P^127.
- */
-static int gcm_gen_table( esp_gcm_context *ctx )
-{
-    int i, j;
-    uint64_t hi, lo;
-    uint64_t vl, vh;
-    unsigned char *h;
-
-    h = ctx->H;
-
-    /* pack h as two 64-bits ints, big-endian */
-    GET_UINT32_BE( hi, h,  0  );
-    GET_UINT32_BE( lo, h,  4  );
-    vh = (uint64_t) hi << 32 | lo;
-
-    GET_UINT32_BE( hi, h,  8  );
-    GET_UINT32_BE( lo, h,  12 );
-    vl = (uint64_t) hi << 32 | lo;
-
-    /* 8 = 1000 corresponds to 1 in GF(2^128) */
-    ctx->HL[8] = vl;
-    ctx->HH[8] = vh;
-
-    /* 0 corresponds to 0 in GF(2^128) */
-    ctx->HH[0] = 0;
-    ctx->HL[0] = 0;
-
-    for( i = 4; i > 0; i >>= 1 )
-    {
-        uint32_t T = ( vl & 1 ) * 0xe1000000U;
-        vl  = ( vh << 63 ) | ( vl >> 1 );
-        vh  = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
-
-        ctx->HL[i] = vl;
-        ctx->HH[i] = vh;
-    }
-
-    for( i = 2; i <= 8; i *= 2 )
-    {
-        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
-        vh = *HiH;
-        vl = *HiL;
-        for( j = 1; j < i; j++ )
-        {
-            HiH[j] = vh ^ ctx->HH[j];
-            HiL[j] = vl ^ ctx->HL[j];
-        }
-    }
-
-    return( 0 );
-}
-/*
- * Shoup's method for multiplication use this table with
- *      last4[x] = x times P^128
- * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
- */
-static const uint64_t last4[16] =
-{
-    0x0000, 0x1c20, 0x3840, 0x2460,
-    0x7080, 0x6ca0, 0x48c0, 0x54e0,
-    0xe100, 0xfd20, 0xd940, 0xc560,
-    0x9180, 0x8da0, 0xa9c0, 0xb5e0
-};
-/* Based on MbedTLS's implemenation
- *
- * Sets output to x times H using the precomputed tables.
- * x and output are seen as elements of GF(2^128) as in [MGV].
- */
-static void gcm_mult( esp_gcm_context *ctx, const unsigned char x[16],
-                      unsigned char output[16] )
-{
-    int i = 0;
-    unsigned char lo, hi, rem;
-    uint64_t zh, zl;
-
-    lo = x[15] & 0xf;
-
-    zh = ctx->HH[lo];
-    zl = ctx->HL[lo];
-
-    for( i = 15; i >= 0; i-- )
-    {
-        lo = x[i] & 0xf;
-        hi = x[i] >> 4;
-
-        if( i != 15 )
-        {
-            rem = (unsigned char) zl & 0xf;
-            zl = ( zh << 60 ) | ( zl >> 4 );
-            zh = ( zh >> 4 );
-            zh ^= (uint64_t) last4[rem] << 48;
-            zh ^= ctx->HH[lo];
-            zl ^= ctx->HL[lo];
-
-        }
-
-        rem = (unsigned char) zl & 0xf;
-        zl = ( zh << 60 ) | ( zl >> 4 );
-        zh = ( zh >> 4 );
-        zh ^= (uint64_t) last4[rem] << 48;
-        zh ^= ctx->HH[hi];
-        zl ^= ctx->HL[hi];
-    }
-
-    PUT_UINT32_BE( zh >> 32, output, 0 );
-    PUT_UINT32_BE( zh, output, 4 );
-    PUT_UINT32_BE( zl >> 32, output, 8 );
-    PUT_UINT32_BE( zl, output, 12 );
-}
-
-
-
-/* Update the key value in gcm context */
-int esp_aes_gcm_setkey( esp_gcm_context *ctx,
-                        mbedtls_cipher_id_t cipher,
-                        const unsigned char *key,
-                        unsigned int keybits )
-{
-    if (keybits != 128 && keybits != 192 && keybits != 256) {
-        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
-    }
-
-    ctx->aes_ctx.key_bytes = keybits / 8;
-
-    memcpy(ctx->aes_ctx.key, key, ctx->aes_ctx.key_bytes);
-
-    return ( 0 );
-}
-
-
-/* AES-GCM GHASH calculation z = GHASH(x) using h0 hash key
-*/
-static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z)
-{
-
-    uint8_t tmp[AES_BLOCK_BYTES];
-
-    memset(tmp, 0, AES_BLOCK_BYTES);
-    /* GHASH(X) is calculated on input string which is multiple of 128 bits
-     * If input string bit length is not multiple of 128 bits it needs to
-     * be padded by 0
-     *
-     * Steps:
-     * 1. Let X1, X2, ... , Xm-1, Xm denote the unique sequence of blocks such
-     * that X = X1 || X2 || ... || Xm-1 || Xm.
-     * 2. Let Y0 be the “zero block,” 0128.
-     * 3. Fori=1,...,m,letYi =(Yi-1 ^ Xi)•H.
-     * 4. Return Ym
-     */
-
-    /* If input bit string is >= 128 bits, process full 128 bit blocks */
-    while (x_len >= AES_BLOCK_BYTES) {
-
-        xor_data(z, x);
-        gcm_mult(ctx, z, z);
-
-        x += AES_BLOCK_BYTES;
-        x_len -= AES_BLOCK_BYTES;
-    }
-
-    /* If input bit string is not multiple of 128 create last 128 bit
-     * block by padding necessary 0s
-     */
-    if (x_len) {
-        memcpy(tmp, x, x_len);
-        xor_data(z, tmp);
-        gcm_mult(ctx, z, z);
-    }
-}
-
-
-/* Function to init AES GCM context to zero */
-void esp_aes_gcm_init( esp_gcm_context *ctx)
-{
-    if (ctx == NULL) {
-        return;
-    }
-
-    bzero(ctx, sizeof(esp_gcm_context));
-
-    ctx->gcm_state = ESP_AES_GCM_STATE_INIT;
-}
-
-/* Function to clear AES-GCM context */
-void esp_aes_gcm_free( esp_gcm_context *ctx)
-{
-    if (ctx == NULL) {
-        return;
-    }
-    bzero(ctx, sizeof(esp_gcm_context));
-}
-
-/* Setup AES-GCM */
-int esp_aes_gcm_starts( esp_gcm_context *ctx,
-                        int mode,
-                        const unsigned char *iv,
-                        size_t iv_len,
-                        const unsigned char *aad,
-                        size_t aad_len )
-{
-    /* IV and AD are limited to 2^64 bits, so 2^61 bytes */
-    /* IV is not allowed to be zero length */
-    if ( iv_len == 0 ||
-            ( (uint64_t) iv_len  ) >> 61 != 0 ||
-            ( (uint64_t) aad_len ) >> 61 != 0 ) {
-        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
-    }
-
-    if (!ctx) {
-        ESP_LOGE(TAG, "No AES context supplied");
-        return -1;
-    }
-
-    if (!iv) {
-        ESP_LOGE(TAG, "No IV supplied");
-        return -1;
-    }
-
-    if ( (aad_len > 0) && !aad) {
-        ESP_LOGE(TAG, "No aad supplied");
-        return -1;
-    }
-
-    /* Initialize AES-GCM context */
-    memset(ctx->ghash, 0, sizeof(ctx->ghash));
-    ctx->data_len = 0;
-
-    ctx->iv = iv;
-    ctx->iv_len = iv_len;
-    ctx->aad = aad;
-    ctx->aad_len = aad_len;
-    ctx->mode = mode;
-
-    /* H and the lookup table are only generated once per ctx */
-    if (ctx->gcm_state == ESP_AES_GCM_STATE_INIT) {
-        /* Lock the AES engine to calculate ghash key H in hardware */
-        esp_aes_acquire_hardware();
-        esp_aes_setkey_hardware( &ctx->aes_ctx, mode);
-        esp_aes_mode_init(ESP_AES_BLOCK_MODE_GCM);
-        /* Enable DMA mode */
-        REG_WRITE(AES_DMA_ENABLE_REG, 1);
-        REG_WRITE(AES_TRIGGER_REG, 1);
-        while (REG_READ(AES_STATE_REG) != AES_STATE_IDLE);
-
-        memcpy(ctx->H, (uint8_t *)AES_H_BASE, AES_BLOCK_BYTES);
-
-        esp_aes_release_hardware();
-
-        gcm_gen_table(ctx);
-    }
-
-    ctx->gcm_state = ESP_AES_GCM_STATE_START;
-
-    /* Once H is obtained we need to derive J0 (Initial Counter Block) */
-    esp_gcm_derive_J0(ctx);
-
-    /* The initial counter block keeps updating during the esp_gcm_update call
-     * however to calculate final authentication tag T we need original J0
-     * so we make a copy here
-     */
-    memcpy(ctx->ori_j0, ctx->J0, 16);
-
-    esp_gcm_ghash(ctx, ctx->aad, ctx->aad_len, ctx->ghash);
-
-    return ( 0 );
-}
-
-/* Perform AES-GCM operation */
-int esp_aes_gcm_update( esp_gcm_context *ctx,
-                        size_t length,
-                        const unsigned char *input,
-                        unsigned char *output )
-{
-    size_t nc_off = 0;
-    uint8_t nonce_counter[AES_BLOCK_BYTES] = {0};
-    uint8_t stream[AES_BLOCK_BYTES] = {0};
-
-    if (!ctx) {
-        ESP_LOGE(TAG, "No GCM context supplied");
-        return -1;
-    }
-    if (!input) {
-        ESP_LOGE(TAG, "No input supplied");
-        return -1;
-    }
-    if (!output) {
-        ESP_LOGE(TAG, "No output supplied");
-        return -1;
-    }
-
-    if ( output > input && (size_t) ( output - input ) < length ) {
-        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
-    }
-    /* If this is the first time esp_gcm_update is getting called
-     * calculate GHASH on aad and preincrement the ICB
-     */
-    if (ctx->gcm_state == ESP_AES_GCM_STATE_START) {
-        /* Jo needs to be incremented first time, later the CTR
-         * operation will auto update it
-         */
-        increment32_j0(ctx, nonce_counter);
-        ctx->gcm_state = ESP_AES_GCM_STATE_UPDATE;
-    } else if (ctx->gcm_state == ESP_AES_GCM_STATE_UPDATE) {
-        memcpy(nonce_counter, ctx->J0, AES_BLOCK_BYTES);
-    }
-
-    /* Perform intermediate GHASH on "encrypted" data during decryption */
-    if (ctx->mode == ESP_AES_DECRYPT) {
-        esp_gcm_ghash(ctx, input, length, ctx->ghash);
-    }
-
-    /* Output = GCTR(J0, Input): Encrypt/Decrypt the input */
-    esp_aes_crypt_ctr(&ctx->aes_ctx, length, &nc_off, nonce_counter, stream, input, output);
-
-    /* ICB gets auto incremented after GCTR operation here so update the context */
-    memcpy(ctx->J0, nonce_counter, AES_BLOCK_BYTES);
-
-    /* Keep updating the length counter for final tag calculation */
-    ctx->data_len += length;
-
-    /* Perform intermediate GHASH on "encrypted" data during encryption*/
-    if (ctx->mode == ESP_AES_ENCRYPT) {
-        esp_gcm_ghash(ctx, output, length, ctx->ghash);
-    }
-
-    return 0;
-}
-
-/* Function to read the tag value */
-int esp_aes_gcm_finish( esp_gcm_context *ctx,
-                        unsigned char *tag,
-                        size_t tag_len )
-{
-    size_t nc_off = 0;
-    uint8_t len_block[AES_BLOCK_BYTES] = {0};
-
-    if ( tag_len > 16 || tag_len < 4 ) {
-        return ( MBEDTLS_ERR_GCM_BAD_INPUT );
-    }
-
-    /* Calculate final GHASH on aad_len, data length */
-    ESP_PUT_BE64(len_block, ctx->aad_len * 8);
-    ESP_PUT_BE64(len_block + 8, ctx->data_len * 8);
-    esp_gcm_ghash(ctx, len_block, AES_BLOCK_BYTES, ctx->ghash);
-
-    /* Tag T = GCTR(J0, ) where T is truncated to tag_len */
-    esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, 0, ctx->ghash, tag);
-
-    return 0;
-}
-
-int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
-                               int mode,
-                               size_t length,
-                               const unsigned char *iv,
-                               size_t iv_len,
-                               const unsigned char *add,
-                               size_t add_len,
-                               const unsigned char *input,
-                               unsigned char *output,
-                               size_t tag_len,
-                               unsigned char *tag )
-{
-    int ret;
-
-
-    if ( ( ret = esp_aes_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) {
-        return ( ret );
-    }
-
-    if ( ( ret = esp_aes_gcm_update( ctx, length, input, output ) ) != 0 ) {
-        return ( ret );
-    }
-
-    if ( ( ret = esp_aes_gcm_finish( ctx, tag, tag_len ) ) != 0 ) {
-        return ( ret );
-    }
-
-    return ( 0 );
-}
-
-int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
-                              size_t length,
-                              const unsigned char *iv,
-                              size_t iv_len,
-                              const unsigned char *add,
-                              size_t add_len,
-                              const unsigned char *tag,
-                              size_t tag_len,
-                              const unsigned char *input,
-                              unsigned char *output )
-{
-    int ret;
-    unsigned char check_tag[16];
-    size_t i;
-    int diff;
-
-    if ( ( ret = esp_aes_gcm_crypt_and_tag( ctx, ESP_AES_DECRYPT, length,
-                                            iv, iv_len, add, add_len,
-                                            input, output, tag_len, check_tag ) ) != 0 ) {
-        return ( ret );
-    }
-
-    /* Check tag in "constant-time" */
-    for ( diff = 0, i = 0; i < tag_len; i++ ) {
-        diff |= tag[i] ^ check_tag[i];
-    }
-
-    if ( diff != 0 ) {
-        bzero( output, length );
-        return ( MBEDTLS_ERR_GCM_AUTH_FAILED );
-    }
-
-    return ( 0 );
-}

+ 31 - 44
components/mbedtls/port/include/esp32s3/aes.h → components/mbedtls/port/include/aes/esp_aes.h

@@ -1,9 +1,9 @@
 /**
- * \brief AES block cipher, ESP32 hardware accelerated version
+ * \brief AES block cipher, ESP hardware accelerated version
  * Based on mbedTLS FIPS-197 compliant version.
  *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
+ *  Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -21,31 +21,23 @@
  *
  */
 
-#ifndef ESP_AES_H
-#define ESP_AES_H
+#pragma once
 
 #include "esp_types.h"
-#include "esp32s3/rom/aes.h"
+#include "hal/aes_types.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* padlock.c and aesni.c rely on these values! */
-#define ESP_AES_ENCRYPT     1
-#define ESP_AES_DECRYPT     0
+
 
 #define ERR_ESP_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
 #define ERR_ESP_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
 
-
 /**
  * \brief          AES context structure
  *
- * \note           buf is able to hold 32 extra bytes, which can be used:
- *                 - for alignment purposes if VIA padlock is used, and/or
- *                 - to simplify key expansion in the 256-bit case by
- *                 generating an extra round key
  */
 typedef struct {
     uint8_t key_bytes;
@@ -53,17 +45,20 @@ typedef struct {
     uint8_t key[32];
 } esp_aes_context;
 
-
 /**
  * \brief The AES XTS context-type definition.
  */
-typedef struct {
+typedef struct
+{
     esp_aes_context crypt; /*!< The AES context to use for AES block
                                         encryption or decryption. */
     esp_aes_context tweak; /*!< The AES context used for tweak
                                         computation. */
 } esp_aes_xts_context;
 
+
+
+
 /**
  * \brief Lock access to AES hardware unit
  *
@@ -99,7 +94,7 @@ void esp_aes_init( esp_aes_context *ctx );
  */
 void esp_aes_free( esp_aes_context *ctx );
 
-/*
+/**
  * \brief          This function initializes the specified AES XTS context.
  *
  *                 It must be the first API called before using
@@ -116,16 +111,6 @@ void esp_aes_xts_init( esp_aes_xts_context *ctx );
  */
 void esp_aes_xts_free( esp_aes_xts_context *ctx );
 
-/**
- * \brief          AES set key schedule (encryption or decryption)
- *
- * \param ctx      AES context to be initialized
- * \param key      encryption key
- * \param keybits  must be 128, 192 or 256
- *
- * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
- */
-
 /**
  * \brief          AES set key schedule (encryption or decryption)
  *
@@ -313,21 +298,26 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
 int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
-                            const unsigned char *key,
-                            unsigned int keybits );
+                                const unsigned char *key,
+                                unsigned int keybits );
 
 /**
- * \brief           Internal AES block encryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_ENCRYPT_ALT)
+ * \brief          This function prepares an XTS context for decryption and
+ *                 sets the decryption key.
  *
- * \param ctx       AES context
- * \param input     Plaintext block
- * \param output    Output (ciphertext) block
+ * \param ctx      The AES XTS context to which the key should be bound.
+ * \param key      The decryption key. This is comprised of the XTS key1
+ *                 concatenated with the XTS key2.
+ * \param keybits  The size of \p key passed in bits. Valid options are:
+ *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
+ *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
+ *
+ * \return         \c 0 on success.
+ * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
 int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
-                            const unsigned char *key,
-                            unsigned int keybits );
+                                const unsigned char *key,
+                                unsigned int keybits );
 
 
 /**
@@ -341,9 +331,6 @@ int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
  */
 int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
 
-/** Deprecated, see esp_aes_internal_encrypt */
-void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
-
 /**
  * \brief           Internal AES block decryption function
  *                  (Only exposed to allow overriding it,
@@ -355,15 +342,15 @@ void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsig
  */
 int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
 
-/** Deprecated, see esp_aes_internal_decrypt */
-void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
-
 /** AES-XTS buffer encryption/decryption */
 int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
 
+/** Deprecated, see esp_aes_internal_decrypt */
+void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
+
+/** Deprecated, see esp_aes_internal_encrypt */
+void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
 
 #ifdef __cplusplus
 }
 #endif
-
-#endif /* aes.h */

+ 13 - 12
components/mbedtls/port/include/esp32s3/gcm.h → components/mbedtls/port/include/aes/esp_aes_gcm.h

@@ -1,5 +1,5 @@
 /**
- * \brief AES block cipher, ESP32C hardware accelerated version
+ * \brief AES GCM block cipher, ESP hardware accelerated version
  * Based on mbedTLS FIPS-197 compliant version.
  *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@@ -21,11 +21,12 @@
  *
  */
 
-#ifndef ESP_GCM_H
-#define ESP_GCM_H
+#pragma once
 
-#include "aes.h"
+#include "aes/esp_aes.h"
 #include "mbedtls/cipher.h"
+#include "soc/lldesc.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -36,6 +37,7 @@ extern "C" {
 
 typedef enum {
     ESP_AES_GCM_STATE_INIT,
+    ESP_AES_GCM_STATE_START,
     ESP_AES_GCM_STATE_UPDATE,
     ESP_AES_GCM_STATE_FINISH
 } esp_aes_gcm_state;
@@ -59,6 +61,7 @@ typedef struct {
     esp_aes_gcm_state gcm_state;
 } esp_gcm_context;
 
+
 /**
  * \brief           This function initializes the specified GCM context
  *
@@ -96,8 +99,8 @@ int esp_aes_gcm_setkey( esp_gcm_context *ctx,
  * \param iv        The initialization vector.
  * \param iv_len    The length of the IV.
  * \param add       The buffer holding the additional data, or NULL
- *                  if \p add_len is 0.
- * \param add_len   The length of the additional data. If 0,
+ *                  if \p aad_len is 0.
+ * \param aad_len   The length of the additional data. If 0,
  *                  \p add is NULL.
  *
  * \return          \c 0 on success.
@@ -176,7 +179,7 @@ void esp_aes_gcm_free( esp_gcm_context *ctx);
  * \param iv        The initialization vector.
  * \param iv_len    The length of the IV.
  * \param add       The buffer holding the additional data.
- * \param add_len   The length of the additional data.
+ * \param aad_len   The length of the additional data.
  * \param input     The buffer holding the input data.
  * \param output    The buffer for holding the output data.
  * \param tag_len   The length of the tag to generate.
@@ -190,7 +193,7 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
                                const unsigned char *iv,
                                size_t iv_len,
                                const unsigned char *add,
-                               size_t add_len,
+                               size_t aad_len,
                                const unsigned char *input,
                                unsigned char *output,
                                size_t tag_len,
@@ -211,7 +214,7 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
  * \param iv        The initialization vector.
  * \param iv_len    The length of the IV.
  * \param add       The buffer holding the additional data.
- * \param add_len   The length of the additional data.
+ * \param aad_len   The length of the additional data.
  * \param tag       The buffer holding the tag.
  * \param tag_len   The length of the tag.
  * \param input     The buffer holding the input data.
@@ -225,7 +228,7 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
                               const unsigned char *iv,
                               size_t iv_len,
                               const unsigned char *add,
-                              size_t add_len,
+                              size_t aad_len,
                               const unsigned char *tag,
                               size_t tag_len,
                               const unsigned char *input,
@@ -234,5 +237,3 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
 #ifdef __cplusplus
 }
 #endif
-
-#endif /* gcm.h */

+ 23 - 9
components/mbedtls/port/include/esp32s3/crypto_dma.h → components/mbedtls/port/include/aes/esp_aes_internal.h

@@ -1,4 +1,7 @@
 /**
+ * \brief AES block cipher, ESP-IDF hardware accelerated version
+ * Based on mbedTLS FIPS-197 compliant version.
+ *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  *  Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
  *  SPDX-License-Identifier: Apache-2.0
@@ -15,26 +18,37 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- *
+ *  Internal API
  */
 
-#ifndef ESP_CRYPTO_DMA_H
-#define ESP_CRYPTO_DMA_H
+#pragma once
 
-#include <freertos/FreeRTOS.h>
+
+#include "aes/esp_aes.h"
+#include "aes/esp_aes_gcm.h"
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+bool valid_key_length(const esp_aes_context *ctx);
+
 
-/* Since crypto DMA is shared between DMA-AES and SHA blocks
- * Needs to be taken by respective blocks before using Crypto DMA
+/**
+ * @brief           Run a AES-GCM conversion using DMA
+ *
+ * @param ctx       Aes context
+ * @param input     Pointer to input data
+ * @param output    Pointer to output data
+ * @param len       Length of the input data
+ * @param aad_desc  GCM additional data DMA descriptor
+ * @param aad_len   GCM additional data length
+ * @return int      -1 on error
  */
-extern _lock_t crypto_dma_lock;
+int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len);
+
 
 #ifdef __cplusplus
 }
 #endif
-
-#endif /* crypto_dma.h */

+ 1 - 9
components/mbedtls/port/include/aes_alt.h

@@ -28,15 +28,7 @@ extern "C" {
 #endif
 
 #if defined(MBEDTLS_AES_ALT)
-#if CONFIG_IDF_TARGET_ESP32
-#include "esp32/aes.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/aes.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/aes.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/aes.h"
-#endif
+#include "aes/esp_aes.h"
 
 typedef esp_aes_context mbedtls_aes_context;
 

+ 2 - 324
components/mbedtls/port/include/esp32/aes.h

@@ -24,330 +24,8 @@
 #ifndef ESP_AES_H
 #define ESP_AES_H
 
-#include "esp_types.h"
-#include "esp32/rom/aes.h"
+#warning "esp32/aes.h is deprecated, please use aes/esp_aes.h instead"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* padlock.c and aesni.c rely on these values! */
-#define ESP_AES_ENCRYPT     1
-#define ESP_AES_DECRYPT     0
-
-#define ERR_ESP_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
-#define ERR_ESP_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
-
-/**
- * \brief          AES context structure
- *
- */
-typedef struct {
-    uint8_t key_bytes;
-    volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
-    uint8_t key[32];
-} esp_aes_context;
-
-/**
- * \brief The AES XTS context-type definition.
- */
-typedef struct
-{
-    esp_aes_context crypt; /*!< The AES context to use for AES block
-                                        encryption or decryption. */
-    esp_aes_context tweak; /*!< The AES context used for tweak
-                                        computation. */
-} esp_aes_xts_context;
-
-
-/**
- * \brief Lock access to AES hardware unit
- *
- * AES hardware unit can only be used by one
- * consumer at a time.
- *
- * esp_aes_xxx API calls automatically manage locking & unlocking of
- * hardware, this function is only needed if you want to call
- * ets_aes_xxx functions directly.
- */
-void esp_aes_acquire_hardware( void );
-
-/**
- * \brief Unlock access to AES hardware unit
- *
- * esp_aes_xxx API calls automatically manage locking & unlocking of
- * hardware, this function is only needed if you want to call
- * ets_aes_xxx functions directly.
- */
-void esp_aes_release_hardware( void );
-
-/**
- * \brief          Initialize AES context
- *
- * \param ctx      AES context to be initialized
- */
-void esp_aes_init( esp_aes_context *ctx );
-
-/**
- * \brief          Clear AES context
- *
- * \param ctx      AES context to be cleared
- */
-void esp_aes_free( esp_aes_context *ctx );
-
-/**
- * \brief          This function initializes the specified AES XTS context.
- *
- *                 It must be the first API called before using
- *                 the context.
- *
- * \param ctx      The AES XTS context to initialize.
- */
-void esp_aes_xts_init( esp_aes_xts_context *ctx );
-
-/**
- * \brief          This function releases and clears the specified AES XTS context.
- *
- * \param ctx      The AES XTS context to clear.
- */
-void esp_aes_xts_free( esp_aes_xts_context *ctx );
-
-/**
- * \brief          AES set key schedule (encryption or decryption)
- *
- * \param ctx      AES context to be initialized
- * \param key      encryption key
- * \param keybits  must be 128, 192 or 256
- *
- * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
- */
-int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
-
-/**
- * \brief          AES-ECB block encryption/decryption
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param input    16-byte input block
- * \param output   16-byte output block
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
-
-/**
- * \brief          AES-CBC buffer encryption/decryption
- *                 Length should be a multiple of the block
- *                 size (16 bytes)
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful, or ERR_AES_INVALID_INPUT_LENGTH
- */
-int esp_aes_crypt_cbc( esp_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-
-/**
- * \brief          AES-CFB128 buffer encryption/decryption.
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv_off   offset in IV (updated after use)
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_cfb128( esp_aes_context *ctx,
-                          int mode,
-                          size_t length,
-                          size_t *iv_off,
-                          unsigned char iv[16],
-                          const unsigned char *input,
-                          unsigned char *output );
-
-/**
- * \brief          AES-CFB8 buffer encryption/decryption.
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_cfb8( esp_aes_context *ctx,
-                        int mode,
-                        size_t length,
-                        unsigned char iv[16],
-                        const unsigned char *input,
-                        unsigned char *output );
-
-/**
- * \brief               AES-CTR buffer encryption/decryption
- *
- * Warning: You have to keep the maximum use of your counter in mind!
- *
- * Note: Due to the nature of CTR you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \param ctx           AES context
- * \param length        The length of the data
- * \param nc_off        The offset in the current stream_block (for resuming
- *                      within current cipher stream). The offset pointer to
- *                      should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block  The saved stream-block for resuming. Is overwritten
- *                      by the function.
- * \param input         The input data stream
- * \param output        The output data stream
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_ctr( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-/**
- * \brief          This function prepares an XTS context for encryption and
- *                 sets the encryption key.
- *
- * \param ctx      The AES XTS context to which the key should be bound.
- * \param key      The encryption key. This is comprised of the XTS key1
- *                 concatenated with the XTS key2.
- * \param keybits  The size of \p key passed in bits. Valid options are:
- *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
- *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
- *
- * \return         \c 0 on success.
- * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
- */
-int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
-                                const unsigned char *key,
-                                unsigned int keybits );
-
-/**
- * \brief       This function performs an AES-OFB (Output Feedback Mode)
- *              encryption or decryption operation.
- *
- * \param ctx      The AES context to use for encryption or decryption.
- *                 It must be initialized and bound to a key.
- * \param length   The length of the input data.
- * \param iv_off   The offset in IV (updated after use).
- *                 It must point to a valid \c size_t.
- * \param iv       The initialization vector (updated after use).
- *                 It must be a readable and writeable buffer of \c 16 Bytes.
- * \param input    The buffer holding the input data.
- *                 It must be readable and of size \p length Bytes.
- * \param output   The buffer holding the output data.
- *                 It must be writeable and of size \p length Bytes.
- *
- * \return         \c 0 on success.
- */
-int esp_aes_crypt_ofb( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-/**
- * \brief          This function prepares an XTS context for decryption and
- *                 sets the decryption key.
- *
- * \param ctx      The AES XTS context to which the key should be bound.
- * \param key      The decryption key. This is comprised of the XTS key1
- *                 concatenated with the XTS key2.
- * \param keybits  The size of \p key passed in bits. Valid options are:
- *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
- *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
- *
- * \return         \c 0 on success.
- * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
- */
-int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
-                                const unsigned char *key,
-                                unsigned int keybits );
-
-
-/**
- * \brief           Internal AES block encryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_ENCRYPT_ALT)
- *
- * \param ctx       AES context
- * \param input     Plaintext block
- * \param output    Output (ciphertext) block
- */
-int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
-
-/**
- * \brief           Internal AES block decryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_DECRYPT_ALT)
- *
- * \param ctx       AES context
- * \param input     Ciphertext block
- * \param output    Output (plaintext) block
- */
-int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
-
-/** AES-XTS buffer encryption/decryption */
-int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
-
-#ifdef __cplusplus
-}
-#endif
+#include "aes/esp_aes.h"
 
 #endif /* aes.h */

+ 2 - 338
components/mbedtls/port/include/esp32s2/aes.h

@@ -24,346 +24,10 @@
 #ifndef ESP_AES_H
 #define ESP_AES_H
 
-#include "esp_types.h"
-#include "esp32s2/rom/aes.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+//#warning "esp32s2/aes.h is deprecated, please use aes/esp_aes.h instead"
 
-/* padlock.c and aesni.c rely on these values! */
-#define ESP_AES_ENCRYPT     1
-#define ESP_AES_DECRYPT     0
+#include "aes/esp_aes.h"
 
-#define ERR_ESP_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
-#define ERR_ESP_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
-
-
-/**
- * \brief          AES context structure
- *
- * \note           buf is able to hold 32 extra bytes, which can be used:
- *                 - for alignment purposes if VIA padlock is used, and/or
- *                 - to simplify key expansion in the 256-bit case by
- *                 generating an extra round key
- */
-typedef struct {
-    uint8_t key_bytes;
-    volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
-    uint8_t key[32];
-} esp_aes_context;
-
-
-/**
- * \brief The AES XTS context-type definition.
- */
-typedef struct {
-    esp_aes_context crypt; /*!< The AES context to use for AES block
-                                        encryption or decryption. */
-    esp_aes_context tweak; /*!< The AES context used for tweak
-                                        computation. */
-} esp_aes_xts_context;
-
-/**
- * \brief Lock access to AES hardware unit
- *
- * AES hardware unit can only be used by one
- * consumer at a time.
- *
- * esp_aes_xxx API calls automatically manage locking & unlocking of
- * hardware, this function is only needed if you want to call
- * ets_aes_xxx functions directly.
- */
-void esp_aes_acquire_hardware( void );
-
-/**
- * \brief Unlock access to AES hardware unit
- *
- * esp_aes_xxx API calls automatically manage locking & unlocking of
- * hardware, this function is only needed if you want to call
- * ets_aes_xxx functions directly.
- */
-void esp_aes_release_hardware( void );
-
-/**
- * \brief          Initialize AES context
- *
- * \param ctx      AES context to be initialized
- */
-void esp_aes_init( esp_aes_context *ctx );
-
-/**
- * \brief          Clear AES context
- *
- * \param ctx      AES context to be cleared
- */
-void esp_aes_free( esp_aes_context *ctx );
-
-/*
- * \brief          This function initializes the specified AES XTS context.
- *
- *                 It must be the first API called before using
- *                 the context.
- *
- * \param ctx      The AES XTS context to initialize.
- */
-void esp_aes_xts_init( esp_aes_xts_context *ctx );
-
-/**
- * \brief          This function releases and clears the specified AES XTS context.
- *
- * \param ctx      The AES XTS context to clear.
- */
-void esp_aes_xts_free( esp_aes_xts_context *ctx );
-
-/**
- * \brief          AES set key schedule (encryption or decryption)
- *
- * \param ctx      AES context to be initialized
- * \param key      encryption key
- * \param keybits  must be 128, 192 or 256
- *
- * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
- */
-
-/**
- * \brief          AES set key schedule (encryption or decryption)
- *
- * \param ctx      AES context to be initialized
- * \param key      encryption key
- * \param keybits  must be 128, 192 or 256
- *
- * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
- */
-int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
-
-/**
- * \brief          AES-ECB block encryption/decryption
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param input    16-byte input block
- * \param output   16-byte output block
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
-
-/**
- * \brief          AES-CBC buffer encryption/decryption
- *                 Length should be a multiple of the block
- *                 size (16 bytes)
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful, or ERR_AES_INVALID_INPUT_LENGTH
- */
-int esp_aes_crypt_cbc( esp_aes_context *ctx,
-                       int mode,
-                       size_t length,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-
-/**
- * \brief          AES-CFB128 buffer encryption/decryption.
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv_off   offset in IV (updated after use)
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_cfb128( esp_aes_context *ctx,
-                          int mode,
-                          size_t length,
-                          size_t *iv_off,
-                          unsigned char iv[16],
-                          const unsigned char *input,
-                          unsigned char *output );
-
-/**
- * \brief          AES-CFB8 buffer encryption/decryption.
- *
- * Note: Due to the nature of CFB you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \note           Upon exit, the content of the IV is updated so that you can
- *                 call the function same function again on the following
- *                 block(s) of data and get the same result as if it was
- *                 encrypted in one call. This allows a "streaming" usage.
- *                 If on the other hand you need to retain the contents of the
- *                 IV, you should either save it manually or use the cipher
- *                 module instead.
- *
- * \param ctx      AES context
- * \param mode     AES_ENCRYPT or AES_DECRYPT
- * \param length   length of the input data
- * \param iv       initialization vector (updated after use)
- * \param input    buffer holding the input data
- * \param output   buffer holding the output data
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_cfb8( esp_aes_context *ctx,
-                        int mode,
-                        size_t length,
-                        unsigned char iv[16],
-                        const unsigned char *input,
-                        unsigned char *output );
-
-/**
- * \brief               AES-CTR buffer encryption/decryption
- *
- * Warning: You have to keep the maximum use of your counter in mind!
- *
- * Note: Due to the nature of CTR you should use the same key schedule for
- * both encryption and decryption. So a context initialized with
- * esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
- *
- * \param ctx           AES context
- * \param length        The length of the data
- * \param nc_off        The offset in the current stream_block (for resuming
- *                      within current cipher stream). The offset pointer to
- *                      should be 0 at the start of a stream.
- * \param nonce_counter The 128-bit nonce and counter.
- * \param stream_block  The saved stream-block for resuming. Is overwritten
- *                      by the function.
- * \param input         The input data stream
- * \param output        The output data stream
- *
- * \return         0 if successful
- */
-int esp_aes_crypt_ctr( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *nc_off,
-                       unsigned char nonce_counter[16],
-                       unsigned char stream_block[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-/**
- * \brief       This function performs an AES-OFB (Output Feedback Mode)
- *              encryption or decryption operation.
- *
- * \param ctx      The AES context to use for encryption or decryption.
- *                 It must be initialized and bound to a key.
- * \param length   The length of the input data.
- * \param iv_off   The offset in IV (updated after use).
- *                 It must point to a valid \c size_t.
- * \param iv       The initialization vector (updated after use).
- *                 It must be a readable and writeable buffer of \c 16 Bytes.
- * \param input    The buffer holding the input data.
- *                 It must be readable and of size \p length Bytes.
- * \param output   The buffer holding the output data.
- *                 It must be writeable and of size \p length Bytes.
- *
- * \return         \c 0 on success.
- */
-int esp_aes_crypt_ofb( esp_aes_context *ctx,
-                       size_t length,
-                       size_t *iv_off,
-                       unsigned char iv[16],
-                       const unsigned char *input,
-                       unsigned char *output );
-
-/**
- * \brief          This function prepares an XTS context for encryption and
- *                 sets the encryption key.
- *
- * \param ctx      The AES XTS context to which the key should be bound.
- * \param key      The encryption key. This is comprised of the XTS key1
- *                 concatenated with the XTS key2.
- * \param keybits  The size of \p key passed in bits. Valid options are:
- *                 <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
- *                 <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
- *
- * \return         \c 0 on success.
- * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
- */
-int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
-                            const unsigned char *key,
-                            unsigned int keybits );
-
-/**
- * \brief           Internal AES block encryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_ENCRYPT_ALT)
- *
- * \param ctx       AES context
- * \param input     Plaintext block
- * \param output    Output (ciphertext) block
- */
-int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
-                            const unsigned char *key,
-                            unsigned int keybits );
-
-
-/**
- * \brief           Internal AES block encryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_ENCRYPT_ALT)
- *
- * \param ctx       AES context
- * \param input     Plaintext block
- * \param output    Output (ciphertext) block
- */
-int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
-
-/** Deprecated, see esp_aes_internal_encrypt */
-void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
-
-/**
- * \brief           Internal AES block decryption function
- *                  (Only exposed to allow overriding it,
- *                  see AES_DECRYPT_ALT)
- *
- * \param ctx       AES context
- * \param input     Ciphertext block
- * \param output    Output (plaintext) block
- */
-int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
-
-/** Deprecated, see esp_aes_internal_decrypt */
-void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
-
-/** AES-XTS buffer encryption/decryption */
-int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
-
-
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* aes.h */

+ 3 - 215
components/mbedtls/port/include/esp32s2/gcm.h

@@ -20,220 +20,8 @@
  *
  *
  */
+#pragma once
 
-#ifndef ESP_GCM_H
-#define ESP_GCM_H
+#warning "esp32s2/gcm.h is deprecated, please use aes/esp_aes_gcm.h instead"
 
-#include "aes.h"
-#include "mbedtls/cipher.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define MBEDTLS_ERR_GCM_AUTH_FAILED      -0x0012  /**< Authenticated decryption failed. */
-#define MBEDTLS_ERR_GCM_BAD_INPUT        -0x0014  /**< Bad input parameters to function.*/
-
-typedef enum {
-    ESP_AES_GCM_STATE_INIT,
-    ESP_AES_GCM_STATE_START,
-    ESP_AES_GCM_STATE_UPDATE,
-    ESP_AES_GCM_STATE_FINISH
-} esp_aes_gcm_state;
-/**
- * \brief          The GCM context structure.
- */
-typedef struct {
-    uint8_t H[16];                        /*!< Initial hash value */
-    uint8_t ghash[16];                    /*!< GHASH value. */
-    uint8_t J0[16];
-    uint64_t HL[16];                      /*!< Precalculated HTable low. */
-    uint64_t HH[16];                      /*!< Precalculated HTable high. */
-    uint8_t ori_j0[16];                   /*!< J0 from first iteration. */
-    const uint8_t *iv;
-    size_t iv_len;                       /*!< The length of IV. */
-    uint64_t aad_len;                     /*!< The total length of the additional data. */
-    size_t data_len;
-    int mode;
-    const unsigned char *aad;             /*!< The additional data. */
-    esp_aes_context aes_ctx;
-    esp_aes_gcm_state gcm_state;
-} esp_gcm_context;
-
-/**
- * \brief           This function initializes the specified GCM context
- *
- * \param ctx       The GCM context to initialize.
- */
-void esp_aes_gcm_init( esp_gcm_context *ctx);
-
-/**
- * \brief           This function associates a GCM context with a
- *                  key.
- *
- * \param ctx       The GCM context to initialize.
- * \param cipher    The 128-bit block cipher to use.
- * \param key       The encryption key.
- * \param keybits   The key size in bits. Valid options are:
- *                  <ul><li>128 bits</li>
- *                  <li>192 bits</li>
- *                  <li>256 bits</li></ul>
- *
- * \return          \c 0 on success.
- * \return          A cipher-specific error code on failure.
- */
-int esp_aes_gcm_setkey( esp_gcm_context *ctx,
-                        mbedtls_cipher_id_t cipher,
-                        const unsigned char *key,
-                        unsigned int keybits );
-
-/**
- * \brief           This function starts a GCM encryption or decryption
- *                  operation.
- *
- * \param ctx       The GCM context.
- * \param mode      The operation to perform: #MBEDTLS_GCM_ENCRYPT or
- *                  #MBEDTLS_GCM_DECRYPT.
- * \param iv        The initialization vector.
- * \param iv_len    The length of the IV.
- * \param add       The buffer holding the additional data, or NULL
- *                  if \p add_len is 0.
- * \param add_len   The length of the additional data. If 0,
- *                  \p add is NULL.
- *
- * \return          \c 0 on success.
- */
-int esp_aes_gcm_starts( esp_gcm_context *ctx,
-                        int mode,
-                        const unsigned char *iv,
-                        size_t iv_len,
-                        const unsigned char *aad,
-                        size_t aad_len );
-
-/**
- * \brief           This function feeds an input buffer into an ongoing GCM
- *                  encryption or decryption operation.
- *
- *    `             The function expects input to be a multiple of 16
- *                  Bytes. Only the last call before calling
- *                  mbedtls_gcm_finish() can be less than 16 Bytes.
- *
- * \note            For decryption, the output buffer cannot be the same as
- *                  input buffer. If the buffers overlap, the output buffer
- *                  must trail at least 8 Bytes behind the input buffer.
- *
- * \param ctx       The GCM context.
- * \param length    The length of the input data. This must be a multiple of
- *                  16 except in the last call before mbedtls_gcm_finish().
- * \param input     The buffer holding the input data.
- * \param output    The buffer for holding the output data.
- *
- * \return         \c 0 on success.
- * \return         #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
- */
-int esp_aes_gcm_update( esp_gcm_context *ctx,
-                        size_t length,
-                        const unsigned char *input,
-                        unsigned char *output );
-
-/**
- * \brief           This function finishes the GCM operation and generates
- *                  the authentication tag.
- *
- *                  It wraps up the GCM stream, and generates the
- *                  tag. The tag can have a maximum length of 16 Bytes.
- *
- * \param ctx       The GCM context.
- * \param tag       The buffer for holding the tag.
- * \param tag_len   The length of the tag to generate. Must be at least four.
- *
- * \return          \c 0 on success.
- * \return          #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
- */
-int esp_aes_gcm_finish( esp_gcm_context *ctx,
-                        unsigned char *tag,
-                        size_t tag_len );
-
-/**
- * \brief           This function clears a GCM context
- *
- * \param ctx       The GCM context to clear.
- */
-void esp_aes_gcm_free( esp_gcm_context *ctx);
-
-/**
- * \brief           This function performs GCM encryption or decryption of a buffer.
- *
- * \note            For encryption, the output buffer can be the same as the
- *                  input buffer. For decryption, the output buffer cannot be
- *                  the same as input buffer. If the buffers overlap, the output
- *                  buffer must trail at least 8 Bytes behind the input buffer.
- *
- * \param ctx       The GCM context to use for encryption or decryption.
- * \param mode      The operation to perform: #MBEDTLS_GCM_ENCRYPT or
- *                  #MBEDTLS_GCM_DECRYPT.
- * \param length    The length of the input data. This must be a multiple of
- *                  16 except in the last call before mbedtls_gcm_finish().
- * \param iv        The initialization vector.
- * \param iv_len    The length of the IV.
- * \param add       The buffer holding the additional data.
- * \param add_len   The length of the additional data.
- * \param input     The buffer holding the input data.
- * \param output    The buffer for holding the output data.
- * \param tag_len   The length of the tag to generate.
- * \param tag       The buffer for holding the tag.
- *
- * \return         \c 0 on success.
- */
-int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
-                               int mode,
-                               size_t length,
-                               const unsigned char *iv,
-                               size_t iv_len,
-                               const unsigned char *add,
-                               size_t add_len,
-                               const unsigned char *input,
-                               unsigned char *output,
-                               size_t tag_len,
-                               unsigned char *tag );
-
-
-/**
- * \brief           This function performs a GCM authenticated decryption of a
- *                  buffer.
- *
- * \note            For decryption, the output buffer cannot be the same as
- *                  input buffer. If the buffers overlap, the output buffer
- *                  must trail at least 8 Bytes behind the input buffer.
- *
- * \param ctx       The GCM context.
- * \param length    The length of the input data. This must be a multiple
- *                  of 16 except in the last call before mbedtls_gcm_finish().
- * \param iv        The initialization vector.
- * \param iv_len    The length of the IV.
- * \param add       The buffer holding the additional data.
- * \param add_len   The length of the additional data.
- * \param tag       The buffer holding the tag.
- * \param tag_len   The length of the tag.
- * \param input     The buffer holding the input data.
- * \param output    The buffer for holding the output data.
- *
- * \return         0 if successful and authenticated.
- * \return         #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
- */
-int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
-                              size_t length,
-                              const unsigned char *iv,
-                              size_t iv_len,
-                              const unsigned char *add,
-                              size_t add_len,
-                              const unsigned char *tag,
-                              size_t tag_len,
-                              const unsigned char *input,
-                              unsigned char *output );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* gcm.h */
+#include "aes/esp_aes_gcm.h"

+ 5 - 24
components/mbedtls/port/include/gcm_alt.h

@@ -23,35 +23,16 @@
 #ifndef GCM_ALT_H
 #define GCM_ALT_H
 
+#include "soc/soc_caps.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #if defined(MBEDTLS_GCM_ALT)
 
-#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
-#if CONFIG_IDF_TARGET_ESP32C3
-#include "esp32s3/gcm.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/gcm.h"
-#endif
-
-
-typedef esp_gcm_context mbedtls_gcm_context;
-
-#define mbedtls_gcm_init            esp_aes_gcm_init
-#define mbedtls_gcm_free            esp_aes_gcm_free
-#define mbedtls_gcm_setkey          esp_aes_gcm_setkey
-#define mbedtls_gcm_starts          esp_aes_gcm_starts
-#define mbedtls_gcm_update          esp_aes_gcm_update
-#define mbedtls_gcm_finish          esp_aes_gcm_finish
-#define mbedtls_gcm_auth_decrypt    esp_aes_gcm_auth_decrypt
-#define mbedtls_gcm_crypt_and_tag   esp_aes_gcm_crypt_and_tag
-
-#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
-
-#if CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/gcm.h"
+#if SOC_AES_SUPPORT_GCM
+#include "aes/esp_aes_gcm.h"
 
 
 typedef esp_gcm_context mbedtls_gcm_context;
@@ -65,7 +46,7 @@ typedef esp_gcm_context mbedtls_gcm_context;
 #define mbedtls_gcm_auth_decrypt    esp_aes_gcm_auth_decrypt
 #define mbedtls_gcm_crypt_and_tag   esp_aes_gcm_crypt_and_tag
 
-#endif // CONFIG_IDF_TARGET_ESP32S2
+#endif // SOC_AES_SUPPORT_GCM
 
 #endif /* MBEDTLS_GCM_ALT */
 

+ 23 - 202
components/mbedtls/test/test_aes.c

@@ -335,9 +335,9 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
     memset(key, 0x44, 16);
 
     // allocate internal memory
-    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(plaintext);
@@ -383,113 +383,6 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
     free(decryptedtext);
 }
 
-TEST_CASE("mbedtls GCM stream test", "[aes]")
-{
-
-    const unsigned SZ = 100;
-    mbedtls_gcm_context ctx;
-    uint8_t nonce[16];
-    uint8_t key[16];
-    uint8_t tag[16];
-    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
-
-    /* Cipher produced via this Python:
-        import os, binascii
-        from cryptography.hazmat.primitives.ciphers.aead import AESGCM
-
-        key = b'\x56' * 16
-        iv = b'\x89' * 16
-        data = b'\xab' * 100
-
-        aesgcm = AESGCM(key)
-
-        ct = aesgcm.encrypt(iv, data, '')
-
-        ct_arr = ""
-        for idx, b in enumerate(ct):
-            if idx % 8 == 0:
-                ct_arr += '\n'
-            ct_arr += "0x{}, ".format(binascii.hexlify(b))
-        print(ct_arr)
-    */
-    const uint8_t expected_cipher[] = {
-        0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41,
-        0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3,
-        0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e,
-        0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45,
-        0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67,
-        0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3,
-        0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e,
-        0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83,
-        0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf,
-        0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b,
-        0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9,
-        0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54,
-        0x7c, 0x71, 0x29, 0x0d
-    };
-    const uint8_t expected_tag[] = {
-        0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52,
-        0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee,
-    };
-
-
-    memset(nonce, 0x89, 16);
-    memset(key, 0x56, 16);
-
-    // allocate internal memory
-    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-
-    TEST_ASSERT_NOT_NULL(chipertext);
-    TEST_ASSERT_NOT_NULL(plaintext);
-    TEST_ASSERT_NOT_NULL(decryptedtext);
-
-    memset(plaintext, 0xAB, SZ);
-    /* Test that all the end results are the same
-        no matter how many bytes we encrypt each call
-        */
-    for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) {
-        memset(nonce, 0x89, 16);
-        memset(chipertext, 0x0, SZ);
-        memset(decryptedtext, 0x0, SZ);
-        memset(tag, 0x0, 16);
-
-        mbedtls_gcm_init(&ctx);
-        mbedtls_gcm_setkey(&ctx, cipher, key, 128);
-        mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce), NULL, 0 );
-
-        // Encrypt
-        for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
-            // Limit length of last call to avoid exceeding buffer size
-            size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
-            mbedtls_gcm_update(&ctx, length, plaintext + idx, chipertext + idx );
-        }
-        mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
-        TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
-        TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag));
-
-        // Decrypt
-        memset(nonce, 0x89, 16);
-        mbedtls_gcm_free( &ctx );
-        mbedtls_gcm_init(&ctx);
-        mbedtls_gcm_setkey(&ctx, cipher, key, 128);
-        mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce), NULL, 0 );
-
-        for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
-            // Limit length of last call to avoid exceeding buffer size
-
-            size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
-            mbedtls_gcm_update(&ctx, length, chipertext + idx, decryptedtext + idx );
-        }
-        mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
-        TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
-        mbedtls_gcm_free( &ctx );
-    }
-    free(plaintext);
-    free(chipertext);
-    free(decryptedtext);
-}
 
 TEST_CASE("mbedtls OFB stream test", "[aes]")
 {
@@ -534,9 +427,9 @@ TEST_CASE("mbedtls OFB stream test", "[aes]")
     memset(key, 0x44, 16);
 
     // allocate internal memory
-    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(plaintext);
@@ -620,9 +513,9 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]")
     memset(key, 0x44, 16);
 
     // allocate internal memory
-    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(plaintext);
@@ -703,9 +596,9 @@ TEST_CASE("mbedtls CFB128 stream test", "[aes]")
     memset(key, 0x44, 16);
 
     // allocate internal memory
-    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(plaintext);
@@ -790,7 +683,7 @@ void aes_psram_ctr_test(uint32_t input_buf_caps, uint32_t output_buf_caps)
     // allocate memory according the requested caps
     uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps);
     uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(plaintext);
@@ -1392,7 +1285,7 @@ const uint8_t expected_cipher_long_input_end[] = {
     0x6a, 0xde, 0xe3, 0x53,
 };
 
-void aes_icache_ctr_test(uint32_t output_buf_caps)
+void aes_ext_flash_ctr_test(uint32_t output_buf_caps)
 {
     mbedtls_aes_context ctx;
     uint8_t nonce[16];
@@ -1402,9 +1295,8 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
     memset(nonce, 0x2F, 16);
     memset(key, 0x1E, 16);
 
-    // allocate internal memory
     uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps);
-    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
 
     TEST_ASSERT_NOT_NULL(chipertext);
     TEST_ASSERT_NOT_NULL(decryptedtext);
@@ -1414,7 +1306,7 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
 
     size_t offset;
 
-    // Encrypt with input buffer in external ram
+    // Encrypt with input buffer in external flash
     offset = 0;
     memset(nonce, 0x2F, 16);
     mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext);
@@ -1423,7 +1315,7 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
     // Decrypt
     offset = 0;
     memset(nonce, 0x2F, 16);
-    // Decrypt with input buffer in instruction memory, the crypto DMA can't access this
+    // Decrypt with input buffer in external flash, the crypto DMA can't access this
     mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext);
 
     TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ);
@@ -1435,87 +1327,16 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
 /* Tests how crypto DMA handles data in external memory */
 TEST_CASE("mbedtls AES PSRAM tests", "[aes]")
 {
-    aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
-    aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    aes_psram_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+    aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
     aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
     aes_psram_one_buf_ctr_test();
 }
 
-/* Tests how crypto DMA handles data from iCache */
-TEST_CASE("mbedtls AES iCache tests", "[aes]")
+/* Tests how crypto DMA handles data from external flash */
+TEST_CASE("mbedtls AES external flash tests", "[aes]")
 {
-    aes_icache_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
-    aes_icache_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    aes_ext_flash_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+    aes_ext_flash_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 }
 #endif // CONFIG_SPIRAM_USE_MALLOC
-
-TEST_CASE("mbedtls AES GCM self-tests", "[aes]")
-{
-    TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass.");
-}
-
-
-TEST_CASE("mbedtls AES GCM crypt-and-tag", "[aes]")
-{
-    const unsigned CALL_SZ = 32 * 1024;
-    mbedtls_gcm_context ctx;
-    unsigned char tag_buf[16];
-    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
-    uint8_t iv[16];
-    uint8_t key[16];
-
-    memset(iv, 0xEE, 16);
-    memset(key, 0x44, 16);
-
-    // allocate internal memory
-    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    TEST_ASSERT_NOT_NULL(buf);
-    uint8_t aad[16];
-    memset(aad, 0x22, 16);
-
-    mbedtls_gcm_init(&ctx);
-    mbedtls_gcm_setkey( &ctx, cipher, key, 128);
-
-    memset(buf, 0xAA, CALL_SZ);
-    mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
-
-
-    /* Sanity check: make sure the last ciphertext block matches
-       what we expect to see.
-
-       Last block and tag produced via this Python:
-
-        import os, binascii
-        from cryptography.hazmat.primitives.ciphers.aead import AESGCM
-
-        key = b'\x44' * 16
-        iv = b'\xEE' * 16
-        data = b'\xAA' * 100
-        aad = b'\x22 * 16
-
-        aesgcm = AESGCM(key)
-
-        ct = aesgcm.encrypt(iv, data, aad)
-    */
-    const uint8_t expected_last_block[] = {
-        0x7d, 0x3d, 0x16, 0x84, 0xd0, 0xb4, 0x38, 0x30,
-        0xd1, 0x24, 0x6f, 0x7e, 0x9a, 0x9c, 0x81, 0x58,
-    };
-
-    const uint8_t expected_tag[] = {
-        0x7e, 0x16, 0x04, 0x07, 0x4b, 0x7e, 0x6b, 0xf7,
-        0x5d, 0xce, 0x9e, 0x7d, 0x3f, 0x85, 0xc5, 0xa5,
-    };
-
-    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
-    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
-
-
-    memset(iv, 0xEE, 16);
-
-    TEST_ASSERT_EQUAL(mbedtls_gcm_auth_decrypt(&ctx, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), expected_tag, sizeof(expected_tag), buf, buf), 0);
-    TEST_ASSERT_EACH_EQUAL_HEX8(0xAA, buf, CALL_SZ);
-
-
-    free(buf);
-}

+ 494 - 0
components/mbedtls/test/test_aes_gcm.c

@@ -0,0 +1,494 @@
+/* mbedTLS GCM test
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <esp_system.h>
+#include "mbedtls/aes.h"
+#include "mbedtls/gcm.h"
+#include "unity.h"
+#include "sdkconfig.h"
+#include "esp_heap_caps.h"
+#include "test_utils.h"
+#include "ccomp_timer.h"
+#include "sys/param.h"
+
+#if CONFIG_MBEDTLS_HARDWARE_GCM
+
+/*
+    Python example code for generating test vectors
+
+    import os, binascii
+    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+
+    def as_c_array(byte_arr):
+        hex_str = ''
+        for idx, byte in enumerate(byte_arr):
+            hex_str += "0x{:02x}, ".format(byte)
+            bytes_per_line = 8
+            if idx % bytes_per_line == bytes_per_line - 1:
+                hex_str += '\n'
+
+        return hex_str
+
+    key = b'\x44' * 16
+    iv = b'\xEE' * 16
+    data = b'\xAA' * 3200
+    aad = b'\x76' * 16
+
+    aesgcm = AESGCM(key)
+
+    ct = aesgcm.encrypt(iv, data, aad)
+
+    print(as_c_array(ct))
+*/
+
+TEST_CASE("mbedtls GCM stream test", "[aes-gcm]")
+{
+
+    const unsigned SZ = 100;
+    mbedtls_gcm_context ctx;
+    uint8_t nonce[16];
+    uint8_t key[16];
+    uint8_t tag[16];
+    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+
+    const uint8_t expected_cipher[] = {
+        0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41,
+        0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3,
+        0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e,
+        0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45,
+        0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67,
+        0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3,
+        0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e,
+        0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83,
+        0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf,
+        0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b,
+        0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9,
+        0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54,
+        0x7c, 0x71, 0x29, 0x0d
+    };
+    const uint8_t expected_tag[] = {
+        0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52,
+        0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee,
+    };
+
+
+    memset(nonce, 0x89, 16);
+    memset(key, 0x56, 16);
+
+    // allocate internal memory
+    uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+
+    TEST_ASSERT_NOT_NULL(chipertext);
+    TEST_ASSERT_NOT_NULL(plaintext);
+    TEST_ASSERT_NOT_NULL(decryptedtext);
+
+    memset(plaintext, 0xAB, SZ);
+    /* Test that all the end results are the same
+        no matter how many bytes we encrypt each call
+        */
+    for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) {
+        memset(nonce, 0x89, 16);
+        memset(chipertext, 0x0, SZ);
+        memset(decryptedtext, 0x0, SZ);
+        memset(tag, 0x0, 16);
+
+        mbedtls_gcm_init(&ctx);
+        mbedtls_gcm_setkey(&ctx, cipher, key, 128);
+        mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce), NULL, 0 );
+
+        // Encrypt
+        for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
+            // Limit length of last call to avoid exceeding buffer size
+            size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
+            mbedtls_gcm_update(&ctx, length, plaintext + idx, chipertext + idx );
+        }
+        mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag));
+
+        // Decrypt
+        memset(nonce, 0x89, 16);
+        mbedtls_gcm_free( &ctx );
+        mbedtls_gcm_init(&ctx);
+        mbedtls_gcm_setkey(&ctx, cipher, key, 128);
+        mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce), NULL, 0 );
+
+        for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
+            // Limit length of last call to avoid exceeding buffer size
+
+            size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
+            mbedtls_gcm_update(&ctx, length, chipertext + idx, decryptedtext + idx );
+        }
+        mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
+        mbedtls_gcm_free( &ctx );
+    }
+    free(plaintext);
+    free(chipertext);
+    free(decryptedtext);
+}
+
+TEST_CASE("mbedtls AES GCM self-tests", "[aes-gcm]")
+{
+    TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass.");
+}
+
+typedef struct  {
+    uint8_t *plaintext;
+    size_t plaintext_length;
+    uint32_t output_caps;
+    uint8_t *add_buf;
+    size_t add_length;
+    uint8_t *iv;
+    size_t iv_length;
+    uint8_t *key;
+    size_t key_bits;
+    size_t tag_len;
+} aes_gcm_test_cfg_t;
+
+typedef struct {
+    const uint8_t *expected_tag;
+    const uint8_t *ciphertext_last_block; // Last block of the chipertext
+} aes_gcm_test_expected_res_t;
+
+
+typedef enum {
+    AES_GCM_TEST_CRYPT_N_TAG,
+    AES_GCM_TEST_START_UPDATE_FINISH,
+} aes_gcm_test_type_t;
+
+static void aes_gcm_test(aes_gcm_test_cfg_t *cfg, aes_gcm_test_expected_res_t *res, aes_gcm_test_type_t aes_gcm_type)
+{
+    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+    mbedtls_gcm_context ctx;
+
+    uint8_t tag_buf_encrypt[16] = {};
+    uint8_t tag_buf_decrypt[16] = {};
+    uint8_t iv_buf[16] = {};
+
+    uint8_t *ciphertext = heap_caps_malloc(cfg->plaintext_length, cfg->output_caps);
+    uint8_t *output = heap_caps_malloc(cfg->plaintext_length, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+
+    if (cfg->plaintext_length != 0) {
+        TEST_ASSERT_NOT_NULL(ciphertext);
+        TEST_ASSERT_NOT_NULL(output);
+    }
+
+    memset(ciphertext, 0, cfg->plaintext_length);
+    memset(output, 0, cfg->plaintext_length);
+    memcpy(iv_buf, cfg->iv, cfg->iv_length);
+
+    mbedtls_gcm_init(&ctx);
+    mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits);
+
+    /* Encrypt and tag */
+    if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
+        mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt);
+    } else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH){
+        TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length) == 0 );
+        TEST_ASSERT(mbedtls_gcm_update( &ctx, cfg->plaintext_length, cfg->plaintext, ciphertext) == 0 );
+        TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf_encrypt, cfg->tag_len) == 0 );
+    }
+    size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0;
+    /* Sanity check: make sure the last ciphertext block matches what we expect to see. */
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length));
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len);
+
+
+    /* Decrypt and authenticate */
+    if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
+        TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0);
+    } else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH){
+        TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length) == 0 );
+        TEST_ASSERT(mbedtls_gcm_update( &ctx, cfg->plaintext_length, ciphertext, output) == 0 );
+        TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf_decrypt, cfg->tag_len) == 0 );
+
+        /* mbedtls_gcm_auth_decrypt already checks tag so only needed for AES_GCM_TEST_START_UPDATE_FINISH */
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len);
+    }
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length);
+
+    free(ciphertext);
+    free(output);
+}
+
+
+
+TEST_CASE("mbedtls AES GCM", "[aes-gcm]")
+{
+    uint8_t iv[16];
+    uint8_t key[16];
+    uint8_t add[30];
+
+    memset(iv, 0xB1, sizeof(iv));
+    memset(key, 0x27, sizeof(key));
+    memset(add, 0x90, sizeof(add));
+
+    size_t length[] = {10, 16, 500, 5000, 12345};
+
+    const uint8_t expected_last_block[][16] = {
+
+        {0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
+        0x60, 0x72},
+
+        {0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
+        0x60, 0x72, 0x9a, 0x81, 0x8d, 0x3c, 0x69, 0x66},
+
+        {0x9d, 0x7a, 0xac, 0x84,0xe3, 0x70, 0x43, 0x0f,
+        0xa7, 0x83, 0x43, 0xc9, 0x04, 0xf8, 0x7d, 0x48},
+
+        {0xee, 0xfd, 0xab, 0x2a, 0x09, 0x44, 0x41, 0x6a,
+        0x91, 0xb0, 0x74, 0x24, 0xee, 0x35, 0xb1, 0x39},
+
+        {0x51, 0xf7, 0x1f, 0x67, 0x1a, 0x4a, 0x12, 0x37,
+        0x60, 0x3b, 0x68, 0x01, 0x20, 0x4f, 0xf3, 0xd9},
+    };
+
+    const uint8_t expected_tag[][16] = {
+
+        {0x06, 0x4f, 0xb5, 0x91, 0x12, 0x24, 0xb4, 0x24,
+        0x0b, 0xc2, 0x85, 0x59, 0x6a, 0x7c, 0x1f, 0xc9},
+
+        {0x45, 0xc2, 0xa8, 0xfe, 0xff, 0x49, 0x1f, 0x45,
+        0x8e, 0x29, 0x74, 0x41, 0xed, 0x9b, 0x54, 0x28},
+
+        {0xe1, 0xf9, 0x40, 0xfa, 0x29, 0x6f, 0x30, 0xae,
+        0xb6, 0x9b, 0x33, 0xdb, 0x8a, 0xf9, 0x70, 0xc4},
+
+        {0x22, 0xe1, 0x22, 0x34, 0x0c, 0x91, 0x0b, 0xcf,
+        0xa3, 0x42, 0xe0, 0x48, 0xe6, 0xfe, 0x2e, 0x28},
+
+        {0xfb, 0xfe, 0x5a, 0xed, 0x26, 0x5c, 0x5e, 0x66,
+        0x4e, 0xb2, 0x48, 0xce, 0xe9, 0x88, 0x1c, 0xe0},
+    };
+
+    aes_gcm_test_cfg_t cfg = {
+        .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
+        .iv = iv,
+        .iv_length = sizeof(iv),
+        .key = key,
+        .key_bits = 8*sizeof(key),
+        .add_buf = add,
+        .add_length = sizeof(add),
+        .tag_len = 16
+    };
+
+    aes_gcm_test_expected_res_t res = {
+    };
+
+    for (int i = 0; i < sizeof(length)/sizeof(length[0]); i++) {
+        printf("Test AES-GCM with plaintext length = %d\n", length[i]);
+        uint8_t *input = heap_caps_malloc(length[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+        TEST_ASSERT(input != NULL || length[i] == 0);
+        memset(input, 0x36, length[i]);
+
+        cfg.plaintext = input;
+        cfg.plaintext_length = length[i];
+        res.expected_tag = expected_tag[i];
+        res.ciphertext_last_block = expected_last_block[i],
+
+        aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
+        aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
+
+        free(input);
+    }
+}
+
+
+TEST_CASE("mbedtls AES GCM - Different add messages", "[aes-gcm]")
+{
+    const unsigned CALL_SZ = 160;
+    uint8_t iv[16];
+    uint8_t key[16];
+    uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    TEST_ASSERT_NOT_NULL(input);
+
+    memset(input, 0x67, CALL_SZ);
+    memset(iv, 0xA2, sizeof(iv));
+    memset(key, 0x48, sizeof(key));
+
+    const uint8_t expected_last_block[] = {
+        0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d,
+        0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed
+    };
+
+    size_t add_len[] = {0, 10, 16, 500, 5000};
+
+    const uint8_t expected_tag[][16] = {
+        {0xe3, 0x91, 0xad, 0x40, 0x96, 0xb7, 0x8c, 0x53,
+         0x4d, 0x15, 0x7d, 0x55, 0x15, 0xdf, 0x10, 0x69},
+
+        {0xc2, 0x38, 0x36, 0xe9, 0x12, 0x72, 0x5b, 0x31,
+         0x0c, 0xde, 0xb5, 0xc9, 0x8c, 0xa3, 0xcb, 0xe7},
+
+        {0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba,
+         0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac},
+
+        {0x3c, 0x28, 0x03, 0xc2, 0x14, 0x40, 0xec, 0xb6,
+         0x25, 0xfb, 0xdd, 0x55, 0xa0, 0xb2, 0x47, 0x7b},
+
+        {0xfa, 0x66, 0x4a, 0x97, 0x2d, 0x02, 0x32, 0x5b,
+         0x92, 0x94, 0xf1, 0x00, 0x1c, 0xfa, 0xe3, 0x07}
+    };
+
+    aes_gcm_test_cfg_t cfg = {
+        .plaintext = input,
+        .plaintext_length = CALL_SZ,
+        .output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
+        .iv = iv,
+        .iv_length = sizeof(iv),
+        .key = key,
+        .key_bits = 8*sizeof(key),
+        .tag_len = 16
+    };
+
+    aes_gcm_test_expected_res_t res = {
+        .ciphertext_last_block = expected_last_block,
+    };
+
+    for (int i = 0; i < sizeof(add_len)/sizeof(add_len[0]); i++) {
+        printf("Test AES-GCM with add length = %d\n", add_len[i]);
+        uint8_t *add = heap_caps_malloc(add_len[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+        TEST_ASSERT(add != NULL || add_len[i] == 0);
+        memset(add, 0x12, add_len[i]);
+
+        cfg.add_buf = add;
+        cfg.add_length = add_len[i];
+        res.expected_tag = expected_tag[i];
+
+        aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
+        aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
+
+        free(add);
+    }
+    free(input);
+}
+
+
+
+TEST_CASE("mbedtls AES GCM performance, start, update, ret", "[aes-gcm]")
+{
+    const unsigned CALL_SZ = 16*3200;
+    mbedtls_gcm_context ctx;
+    float elapsed_usec;
+    unsigned char tag_buf[16];
+    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+    uint8_t iv[16];
+    uint8_t key[16];
+    uint8_t aad[16];
+
+    memset(iv, 0xEE, 16);
+    memset(key, 0x44, 16);
+    memset(aad, 0x76, 16);
+
+    // allocate internal memory
+    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    TEST_ASSERT_NOT_NULL(buf);
+
+    mbedtls_gcm_init(&ctx);
+    mbedtls_gcm_setkey( &ctx, cipher, key, 128);
+
+    ccomp_timer_start();
+
+    memset(buf, 0xAA, CALL_SZ);
+
+    TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv, sizeof(iv), aad, sizeof(aad) ) == 0 );
+    TEST_ASSERT(mbedtls_gcm_update( &ctx, CALL_SZ, buf, buf ) == 0 );
+    TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf, 16 ) == 0 );
+
+    elapsed_usec = ccomp_timer_stop();
+
+    /* Sanity check: make sure the last ciphertext block matches
+       what we expect to see.
+*/
+    const uint8_t expected_last_block[] = {
+        0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
+        0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
+    };
+
+    const uint8_t expected_tag[] = {
+        0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
+        0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
+    };
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
+
+    free(buf);
+
+    // bytes/usec = MB/sec
+    float mb_sec = CALL_SZ / elapsed_usec;
+    printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
+
+#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
+    // Don't put a hard limit on software AES performance
+    TEST_PERFORMANCE_GREATER_THAN(AES_GCM_UPDATE_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
+#endif
+}
+
+
+TEST_CASE("mbedtls AES GCM performance, crypt-and-tag", "[aes-gcm]")
+{
+    const unsigned CALL_SZ = 16*3200;
+    mbedtls_gcm_context ctx;
+    float elapsed_usec;
+    unsigned char tag_buf[16] = {};
+    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
+    uint8_t iv[16];
+    uint8_t key[16];
+    uint8_t aad[16];
+
+    memset(iv, 0xEE, 16);
+    memset(key, 0x44, 16);
+    memset(aad, 0x76, 16);
+
+    // allocate internal memory
+    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    TEST_ASSERT_NOT_NULL(buf);
+
+    mbedtls_gcm_init(&ctx);
+    mbedtls_gcm_setkey( &ctx, cipher, key, 128);
+
+    memset(buf, 0xAA, CALL_SZ);
+
+    ccomp_timer_start();
+    mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
+
+    elapsed_usec = ccomp_timer_stop();
+
+    /* Sanity check: make sure the last ciphertext block matches
+       what we expect to see.
+    */
+
+    const uint8_t expected_last_block[] = {
+        0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
+        0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
+    };
+
+    const uint8_t expected_tag[] = {
+        0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
+        0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
+    };
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
+
+    free(buf);
+
+    // bytes/usec = MB/sec
+    float mb_sec = CALL_SZ / elapsed_usec;
+    printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
+
+#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
+    // Don't put a hard limit on software AES performance
+    TEST_PERFORMANCE_GREATER_THAN(AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
+#endif
+}
+
+#endif //CONFIG_MBEDTLS_HARDWARE_GCM

+ 1 - 73
components/mbedtls/test/test_aes_perf.c

@@ -25,7 +25,7 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
     memset(key, 0x44, 16);
 
     // allocate internal memory
-    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
     TEST_ASSERT_NOT_NULL(buf);
     mbedtls_aes_init(&ctx);
     mbedtls_aes_setkey_enc(&ctx, key, 128);
@@ -67,75 +67,3 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
     TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
 #endif
 }
-
-
-TEST_CASE("mbedtls AES GCM performance", "[aes]")
-{
-    const unsigned CALL_SZ = 32 * 1024;
-    mbedtls_gcm_context ctx;
-    float elapsed_usec;
-    unsigned char tag_buf[16];
-    mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
-    uint8_t iv[16];
-    uint8_t key[16];
-
-    memset(iv, 0xEE, 16);
-    memset(key, 0x44, 16);
-
-    // allocate internal memory
-    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-    TEST_ASSERT_NOT_NULL(buf);
-    uint8_t aad[16];
-    memset(aad, 0x22, 16);
-
-    mbedtls_gcm_init(&ctx);
-    mbedtls_gcm_setkey( &ctx, cipher, key, 128);
-
-    ccomp_timer_start();
-
-    memset(buf, 0xAA, CALL_SZ);
-    mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
-
-    elapsed_usec = ccomp_timer_stop();
-
-    /* Sanity check: make sure the last ciphertext block matches
-       what we expect to see.
-
-       Last block and tag produced via this Python:
-
-        import os, binascii
-        from cryptography.hazmat.primitives.ciphers.aead import AESGCM
-
-        key = b'\x44' * 16
-        iv = b'\xEE' * 16
-        data = b'\xAA' * 100
-        aad = b'\x22 * 16
-
-        aesgcm = AESGCM(key)
-
-        ct = aesgcm.encrypt(iv, data, aad)
-    */
-    const uint8_t expected_last_block[] = {
-        0x7d, 0x3d, 0x16, 0x84, 0xd0, 0xb4, 0x38, 0x30,
-        0xd1, 0x24, 0x6f, 0x7e, 0x9a, 0x9c, 0x81, 0x58,
-    };
-
-    const uint8_t expected_tag[] = {
-        0x7e, 0x16, 0x04, 0x07, 0x4b, 0x7e, 0x6b, 0xf7,
-        0x5d, 0xce, 0x9e, 0x7d, 0x3f, 0x85, 0xc5, 0xa5,
-    };
-
-    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
-    TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
-
-    free(buf);
-
-    // bytes/usec = MB/sec
-    float mb_sec = CALL_SZ / elapsed_usec;
-    printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
-
-#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
-    // Don't put a hard limit on software AES performance
-    TEST_PERFORMANCE_GREATER_THAN(AES_GCM_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
-#endif
-}

+ 19 - 18
components/mbedtls/test/test_esp_crt_bundle.c

@@ -309,35 +309,36 @@ exit:
     return ret;
 }
 
+
 TEST_CASE("custom certificate bundle", "[mbedtls]")
 {
-    esp_crt_validate_res_t validate_res;
+   esp_crt_validate_res_t validate_res;
 
-    test_case_uses_tcpip();
+   test_case_uses_tcpip();
 
-    xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
+   xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
 
-    exit_flag = false;
-    xTaskCreate(server_task, "server task", 8192, &exit_sema, 10, NULL);
+   exit_flag = false;
+   xTaskCreate(server_task, "server task", 8192, &exit_sema, 10, NULL);
 
-    // Wait for the server to start up
-    vTaskDelay(100 / portTICK_PERIOD_MS);
+   // Wait for the server to start up
+   vTaskDelay(100 / portTICK_PERIOD_MS);
 
-    /* Test with default crt bundle that doesnt contain the ca crt */
-    client_task(NULL, &validate_res);
-    TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_FAIL);
+   /* Test with default crt bundle that doesnt contain the ca crt */
+   client_task(NULL, &validate_res);
+   TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_FAIL);
 
-    /* Test with bundle that does contain the CA crt */
-    client_task(server_cert_bundle_start, &validate_res);
-    TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_OK);
+   /* Test with bundle that does contain the CA crt */
+   client_task(server_cert_bundle_start, &validate_res);
+   TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_OK);
 
-    exit_flag = true;
+   exit_flag = true;
 
-    if (!xSemaphoreTake(exit_sema, 10000 / portTICK_PERIOD_MS)) {
-        TEST_FAIL_MESSAGE("exit_sem not released by server task");
-    }
+   if (!xSemaphoreTake(exit_sema, 10000 / portTICK_PERIOD_MS)) {
+       TEST_FAIL_MESSAGE("exit_sem not released by server task");
+   }
 
-    vSemaphoreDelete(exit_sema);
+   vSemaphoreDelete(exit_sema);
 }
 
 TEST_CASE("custom certificate bundle - weak hash", "[mbedtls]")

+ 1 - 1
components/mbedtls/test/test_sha_perf.c

@@ -20,7 +20,7 @@ TEST_CASE("mbedtls SHA performance", "[aes]")
     unsigned char sha256[32];
 
     // allocate internal memory
-    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+    uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
     TEST_ASSERT_NOT_NULL(buf);
     memset(buf, 0x55, CALL_SZ);
 

+ 5 - 0
components/soc/esp32/include/soc/soc_caps.h

@@ -258,6 +258,11 @@
 #define SOC_RSA_MAX_BIT_LEN    (4096)
 
 
+/*-------------------------- AES CAPS -----------------------------------------*/
+#define SOC_AES_SUPPORT_AES_128 (1)
+#define SOC_AES_SUPPORT_AES_192 (1)
+#define SOC_AES_SUPPORT_AES_256 (1)
+
 /* ---------------------------- Compatibility ------------------------------- */
 #define SOC_CAN_SUPPORTED                   SOC_TWAI_SUPPORTED
 #define CAN_BRP_MIN                         SOC_TWAI_BRP_MIN

+ 9 - 0
components/soc/esp32c3/include/soc/soc_caps.h

@@ -44,3 +44,12 @@
 
 /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
 #define SOC_TOUCH_SENSOR_NUM            (0)    /*! No touch sensors on ESP32-C3 */
+
+/*-------------------------- AES CAPS -----------------------------------------*/
+#define SOC_AES_SUPPORT_DMA     (1)
+
+/* Has a centralized DMA, which is shared with all peripherals */
+#define SOC_AES_GENERAL_DMA     (1)
+
+#define SOC_AES_SUPPORT_AES_128 (1)
+#define SOC_AES_SUPPORT_AES_256 (1)

+ 12 - 0
components/soc/esp32s2/include/soc/soc_caps.h

@@ -276,6 +276,18 @@
 #define SOC_RSA_MAX_BIT_LEN    (4096)
 
 
+/*-------------------------- AES CAPS -----------------------------------------*/
+#define SOC_AES_SUPPORT_DMA     (1)
+#define SOC_AES_SUPPORT_GCM     (1)
+
+/* Has "crypto DMA", which is shared with SHA */
+#define SOC_AES_CRYPTO_DMA      (1)
+
+#define SOC_AES_SUPPORT_AES_128 (1)
+#define SOC_AES_SUPPORT_AES_192 (1)
+#define SOC_AES_SUPPORT_AES_256 (1)
+
+
 
 /* ---------------------------- Compatibility ------------------------------- */
 // No contents

+ 5 - 1
components/soc/esp32s3/include/soc/soc.h

@@ -258,10 +258,14 @@
 #define SOC_DIRAM_DRAM_LOW    0x3FC88000
 #define SOC_DIRAM_DRAM_HIGH   0x3FCF0000
 
-// Region of memory accessible via DMA. See esp_ptr_dma_capable().
+// Region of memory accessible via DMA in internal memory. See esp_ptr_dma_capable().
 #define SOC_DMA_LOW  0x3FC88000
 #define SOC_DMA_HIGH 0x3FD00000
 
+// Region of memory accessible via DMA in external memory. See esp_ptr_dma_ext_capable().
+#define SOC_DMA_EXT_LOW     0x3C000000
+#define SOC_DMA_EXT_HIGH    0x3DFFFFFF
+
 // Region of memory that is byte-accessible. See esp_ptr_byte_accessible().
 #define SOC_BYTE_ACCESSIBLE_LOW     0x3FC88000
 #define SOC_BYTE_ACCESSIBLE_HIGH    0x3FD00000

+ 10 - 0
components/soc/esp32s3/include/soc/soc_caps.h

@@ -138,9 +138,19 @@
 #define SOC_RSA_MAX_BIT_LEN    (4096)
 
 
+/*-------------------------- AES CAPS -----------------------------------------*/
+#define SOC_AES_SUPPORT_DMA     (1)
+
+/* Has a centralized DMA, which is shared with all peripherals */
+#define SOC_AES_GENERAL_DMA     (1)
+
+#define SOC_AES_SUPPORT_AES_128 (1)
+#define SOC_AES_SUPPORT_AES_256 (1)
+
 // Attention: These fixed DMA channels are temporarily workaround before we have a centralized DMA controller API to help alloc the channel dynamically
 // Remove them when GDMA driver API is ready
 #define SOC_GDMA_M2M_DMA_CHANNEL  (0)
 #define SOC_GDMA_SPI2_DMA_CHANNEL (1)
 #define SOC_GDMA_SPI3_DMA_CHANNEL (2)
 #define SOC_GDMA_SHA_DMA_CHANNEL  (3)
+#define SOC_GDMA_AES_DMA_CHANNEL  (4)

+ 1 - 1
components/soc/include/soc/soc_memory_layout.h

@@ -148,7 +148,7 @@ inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
 
 inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p)
 {
-#if CONFIG_IDF_TARGET_ESP32S2
+#if CONFIG_IDF_TARGET_ESP32S2  || CONFIG_IDF_TARGET_ESP32S3
     return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
 #else
     return false;