Jelajahi Sumber

Merge branch 'feature/add_bignum_ll_layer' into 'master'

bignum: added bignum hal and ll layer

Closes IDF-7071

See merge request espressif/esp-idf!22823
Mahavir Jain 2 tahun lalu
induk
melakukan
a8b6a70620
51 mengubah file dengan 2345 tambahan dan 1475 penghapusan
  1. 27 0
      components/esp_hw_support/include/soc/esp32/esp_crypto_lock.h
  2. 1 0
      components/esp_hw_support/port/esp32/CMakeLists.txt
  3. 27 0
      components/esp_hw_support/port/esp32/esp_crypto_lock.c
  4. 5 0
      components/hal/.build-test-rules.yml
  5. 5 0
      components/hal/CMakeLists.txt
  6. 150 0
      components/hal/esp32/include/hal/mpi_ll.h
  7. 153 0
      components/hal/esp32c3/include/hal/mpi_ll.h
  8. 153 0
      components/hal/esp32c6/include/hal/mpi_ll.h
  9. 153 0
      components/hal/esp32h2/include/hal/mpi_ll.h
  10. 151 0
      components/hal/esp32s2/include/hal/mpi_ll.h
  11. 149 0
      components/hal/esp32s3/include/hal/mpi_ll.h
  12. 146 0
      components/hal/include/hal/mpi_hal.h
  13. 19 0
      components/hal/include/hal/mpi_types.h
  14. 126 0
      components/hal/mpi_hal.c
  15. 7 0
      components/hal/test_apps/mpi/CMakeLists.txt
  16. 33 0
      components/hal/test_apps/mpi/README.md
  17. 6 0
      components/hal/test_apps/mpi/main/CMakeLists.txt
  18. 13 0
      components/hal/test_apps/mpi/main/app_main.c
  19. 145 0
      components/hal/test_apps/mpi/main/test_mpi.c
  20. 382 0
      components/hal/test_apps/mpi/main/test_params.h
  21. 16 0
      components/hal/test_apps/mpi/pytest_mpi.py
  22. 2 0
      components/hal/test_apps/mpi/sdkconfig.defaults
  23. 2 3
      components/mbedtls/CMakeLists.txt
  24. 227 0
      components/mbedtls/port/bignum/bignum_alt.c
  25. 26 37
      components/mbedtls/port/bignum/esp_bignum.c
  26. 0 296
      components/mbedtls/port/esp32/bignum.c
  27. 0 229
      components/mbedtls/port/esp32c3/bignum.c
  28. 0 230
      components/mbedtls/port/esp32c6/bignum.c
  29. 0 230
      components/mbedtls/port/esp32h2/bignum.c
  30. 0 224
      components/mbedtls/port/esp32s2/bignum.c
  31. 0 226
      components/mbedtls/port/esp32s3/bignum.c
  32. 4 0
      components/soc/CMakeLists.txt
  33. 8 0
      components/soc/esp32/include/soc/Kconfig.soc_caps.in
  34. 3 0
      components/soc/esp32/include/soc/soc_caps.h
  35. 19 0
      components/soc/esp32/mpi_periph.c
  36. 8 0
      components/soc/esp32c3/include/soc/Kconfig.soc_caps.in
  37. 4 0
      components/soc/esp32c3/include/soc/soc_caps.h
  38. 21 0
      components/soc/esp32c3/mpi_periph.c
  39. 8 0
      components/soc/esp32c6/include/soc/Kconfig.soc_caps.in
  40. 4 0
      components/soc/esp32c6/include/soc/soc_caps.h
  41. 21 0
      components/soc/esp32c6/mpi_periph.c
  42. 8 0
      components/soc/esp32h2/include/soc/Kconfig.soc_caps.in
  43. 4 0
      components/soc/esp32h2/include/soc/soc_caps.h
  44. 21 0
      components/soc/esp32h2/mpi_periph.c
  45. 8 0
      components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
  46. 4 0
      components/soc/esp32s2/include/soc/soc_caps.h
  47. 21 0
      components/soc/esp32s2/mpi_periph.c
  48. 8 0
      components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
  49. 4 0
      components/soc/esp32s3/include/soc/soc_caps.h
  50. 21 0
      components/soc/esp32s3/mpi_periph.c
  51. 22 0
      components/soc/include/soc/mpi_periph.h

+ 27 - 0
components/esp_hw_support/include/soc/esp32/esp_crypto_lock.h

@@ -0,0 +1,27 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Acquire lock for the mpi cryptography peripheral.
+ *
+ */
+void esp_crypto_mpi_lock_acquire(void);
+
+/**
+ * @brief Release lock for the mpi cryptography peripheral.
+ *
+ */
+void esp_crypto_mpi_lock_release(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 0
components/esp_hw_support/port/esp32/CMakeLists.txt

@@ -11,6 +11,7 @@ set(srcs
 
 if(NOT BOOTLOADER_BUILD)
     list(APPEND srcs "cache_sram_mmu.c"
+                     "esp_crypto_lock.c"
                      "sar_periph_ctrl.c")
 endif()
 

+ 27 - 0
components/esp_hw_support/port/esp32/esp_crypto_lock.c

@@ -0,0 +1,27 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/lock.h>
+
+#include "esp_crypto_lock.h"
+
+/* Lock overview:
+MPI/RSA: independent
+*/
+
+/* Lock for the MPI/RSA peripheral */
+
+static _lock_t s_crypto_mpi_lock;
+
+void esp_crypto_mpi_lock_acquire(void)
+{
+    _lock_acquire(&s_crypto_mpi_lock);
+}
+
+void esp_crypto_mpi_lock_release(void)
+{
+    _lock_release(&s_crypto_mpi_lock);
+}

+ 5 - 0
components/hal/.build-test-rules.yml

@@ -7,3 +7,8 @@ components/hal/test_apps/ecc:
     - if: IDF_TARGET == "esp32c2"
       temporary: true
       reason: C2 ECC peripheral has a bug in ECC point verification, if value of K is zero the verification fails
+
+components/hal/test_apps/mpi:
+  disable:
+    - if: SOC_MPI_SUPPORTED != 1
+      reason: Hardware MPI support not available for such targets.

+ 5 - 0
components/hal/CMakeLists.txt

@@ -1,3 +1,4 @@
+
 idf_build_get_property(target IDF_TARGET)
 
 # On Linux, there is currently no HAL, hence this simple component registration
@@ -117,6 +118,10 @@ if(NOT BOOTLOADER_BUILD)
         list(APPEND srcs "ecdsa_hal.c")
     endif()
 
+    if(CONFIG_SOC_MPI_SUPPORTED)
+        list(APPEND srcs "mpi_hal.c")
+    endif()
+
     if(CONFIG_SOC_SHA_SUPPORTED)
         list(APPEND srcs "sha_hal.c")
     endif()

+ 150 - 0
components/hal/esp32/include/hal/mpi_ll.h

@@ -0,0 +1,150 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/dport_reg.h"
+#include "soc/hwcrypto_periph.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Round up number of words to nearest
+   512 bit (16 word) block count.
+*/
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return (words + 0xF) & ~0xF;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return DPORT_REG_READ(RSA_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    DPORT_REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return DPORT_REG_READ(RSA_INTERRUPT_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+
+*/
+
+/* Please see detailed note inside the function body below.
+ * Relevant: IDF-6029
+             https://github.com/espressif/esp-idf/issues/8710
+             https://github.com/espressif/esp-idf/issues/10403
+ */
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (uint32_t i = 0; i < copy_words; i++) {
+        DPORT_REG_WRITE(mem_base + i * 4, p[i]);
+    }
+
+    /* Zero any remaining memory block data */
+    for (uint32_t i = copy_words; i < num_words; i++) {
+        DPORT_REG_WRITE(mem_base + i * 4, 0);
+    }
+#if _INTERNAL_DEBUG_PURPOSE
+    /*
+     * With Xtensa GCC 11.2.0 (from ESP-IDF v5.x), it was observed that above zero initialization
+     * loop gets optimized to `memset` call from the ROM library. This was causing an issue that
+     * specific write (store) operation to the MPI peripheral block was getting lost erroneously.
+     * Following data re-verify loop could catch it during runtime.
+     *
+     * As a workaround, we are using DPORT_WRITE_REG (volatile writes) wrappers to write to
+     * the MPI peripheral.
+     *
+     */
+
+    //for (uint32_t i = copy_words; i < hw_words; i++) { assert(pbase[i] == 0); }
+#endif
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    DPORT_REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    DPORT_REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    assert(n >= num_words);
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    /* Copy data from memory block registers */
+    esp_dport_access_read_buffer(p, mem_base, num_words);
+
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    DPORT_REG_WRITE(RSA_MULT_MODE_REG, length);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 153 - 0
components/hal/esp32c3/include/hal/mpi_ll.h

@@ -0,0 +1,153 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/hwcrypto_periph.h"
+#include "soc/system_reg.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return words;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return REG_READ(RSA_QUERY_INTERRUPT_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+*/
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t* pbase = (uint32_t*) mem_base;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (int i = 0; i < copy_words; i++) {
+        pbase[i] = p[i];
+    }
+
+    /* Zero any remaining memory block data */
+    for (int i = copy_words; i < num_words; i++) {
+        pbase[i] = 0;
+    }
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    REG_WRITE(RSA_M_DASH_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    /* Copy data from memory block registers */
+    const size_t REG_WIDTH = sizeof(uint32_t);
+    for (size_t i = 0; i < num_words; i++) {
+        p[i] = REG_READ(mem_base + (i * REG_WIDTH));
+    }
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    REG_WRITE(RSA_LENGTH_REG, length);
+}
+
+static inline void mpi_ll_disable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+}
+
+static inline void mpi_ll_enable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
+}
+
+static inline void mpi_ll_disable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
+}
+
+static inline void mpi_ll_enable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
+}
+
+static inline void mpi_ll_set_search_position(size_t pos)
+{
+    REG_WRITE(RSA_SEARCH_POS_REG, pos);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 153 - 0
components/hal/esp32c6/include/hal/mpi_ll.h

@@ -0,0 +1,153 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/pcr_reg.h"
+#include "soc/rsa_reg.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return words;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    REG_WRITE(RSA_INT_ENA_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    REG_WRITE(RSA_INT_ENA_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    REG_WRITE(RSA_INT_CLR_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return REG_READ(RSA_QUERY_IDLE_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base' of mpi_param_t 'param'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+*/
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t* pbase = (uint32_t*) mem_base;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (int i = 0; i < copy_words; i++) {
+        pbase[i] = p[i];
+    }
+
+    /* Zero any remaining memory block data */
+    for (int i = copy_words; i < num_words; i++) {
+        pbase[i] = 0;
+    }
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    REG_WRITE(RSA_M_PRIME_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    /* Copy data from memory block registers */
+    const size_t REG_WIDTH = sizeof(uint32_t);
+    for (size_t i = 0; i < num_words; i++) {
+        p[i] = REG_READ(mem_base + (i * REG_WIDTH));
+    }
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    REG_WRITE(RSA_MODE_REG, length);
+}
+
+static inline void mpi_ll_disable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+}
+
+static inline void mpi_ll_enable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
+}
+
+static inline void mpi_ll_disable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
+}
+
+static inline void mpi_ll_enable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
+}
+
+static inline void mpi_ll_set_search_position(size_t pos)
+{
+    REG_WRITE(RSA_SEARCH_POS_REG, pos);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 153 - 0
components/hal/esp32h2/include/hal/mpi_ll.h

@@ -0,0 +1,153 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/pcr_reg.h"
+#include "soc/rsa_reg.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return words;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    REG_WRITE(RSA_INT_ENA_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    REG_WRITE(RSA_INT_ENA_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    REG_WRITE(RSA_INT_CLR_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return REG_READ(RSA_QUERY_IDLE_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+*/
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t* pbase = (uint32_t*) mem_base;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (int i = 0; i < copy_words; i++) {
+        pbase[i] = p[i];
+    }
+
+    /* Zero any remaining memory block data */
+    for (int i = copy_words; i < num_words; i++) {
+        pbase[i] = 0;
+    }
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    REG_WRITE(RSA_M_PRIME_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    /* Copy data from memory block registers */
+    const size_t REG_WIDTH = sizeof(uint32_t);
+    for (size_t i = 0; i < num_words; i++) {
+        p[i] = REG_READ(mem_base + (i * REG_WIDTH));
+    }
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    REG_WRITE(RSA_MODE_REG, length);
+}
+
+static inline void mpi_ll_disable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+}
+
+static inline void mpi_ll_enable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
+}
+
+static inline void mpi_ll_disable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
+}
+
+static inline void mpi_ll_enable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
+}
+
+static inline void mpi_ll_set_search_position(size_t pos)
+{
+    REG_WRITE(RSA_SEARCH_POS_REG, pos);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 151 - 0
components/hal/esp32s2/include/hal/mpi_ll.h

@@ -0,0 +1,151 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/hwcrypto_periph.h"
+#include "soc/dport_reg.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return words;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return REG_READ(RSA_QUERY_INTERRUPT_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+*/
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t* pbase = (uint32_t*) mem_base;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (int i = 0; i < copy_words; i++) {
+        pbase[i] = p[i];
+    }
+
+    /* Zero any remaining memory block data */
+    for (int i = copy_words; i < num_words; i++) {
+        pbase[i] = 0;
+    }
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    REG_WRITE(RSA_M_DASH_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    /* Copy data from memory block registers */
+    esp_dport_access_read_buffer(p, mem_base, num_words);
+
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    REG_WRITE(RSA_LENGTH_REG, length);
+}
+
+static inline void mpi_ll_disable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+}
+
+static inline void mpi_ll_enable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
+}
+
+static inline void mpi_ll_disable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
+}
+
+static inline void mpi_ll_enable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
+}
+
+static inline void mpi_ll_set_search_position(size_t pos)
+{
+    REG_WRITE(RSA_SEARCH_POS_REG, pos);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 149 - 0
components/hal/esp32s3/include/hal/mpi_ll.h

@@ -0,0 +1,149 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#include <stdbool.h>
+#include <string.h>
+#include "hal/assert.h"
+#include "soc/hwcrypto_periph.h"
+#include "soc/dport_reg.h"
+#include "soc/mpi_periph.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline size_t mpi_ll_calculate_hardware_words(size_t words)
+{
+    return words;
+}
+
+static inline void mpi_ll_clear_power_control_bit(void)
+{
+    REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_set_power_control_bit(void)
+{
+    REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+}
+
+static inline void mpi_ll_enable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 1);
+}
+
+static inline void mpi_ll_disable_interrupt(void)
+{
+    REG_WRITE(RSA_INTERRUPT_REG, 0);
+}
+
+static inline void mpi_ll_clear_interrupt(void)
+{
+    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
+}
+
+static inline bool mpi_ll_check_memory_init_complete(void)
+{
+    return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
+}
+
+static inline void mpi_ll_start_op(mpi_op_t op)
+{
+    REG_WRITE(MPI_LL_OPERATIONS[op], 1);
+}
+
+static inline bool mpi_ll_get_int_status(void)
+{
+    return REG_READ(RSA_QUERY_INTERRUPT_REG) == 0;
+}
+
+/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
+
+   If num_words is higher than the number of words (n) in the bignum then
+   these additional words will be zeroed in the memory buffer.
+*/
+static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    uint32_t* pbase = (uint32_t*) mem_base;
+    uint32_t copy_words = MIN(num_words, n);
+
+    /* Copy MPI data to memory block registers */
+    for (int i = 0; i < copy_words; i++) {
+        pbase[i] = p[i];
+    }
+
+    /* Zero any remaining memory block data */
+    for (int i = copy_words; i < num_words; i++) {
+        pbase[i] = 0;
+    }
+}
+
+static inline void mpi_ll_write_m_prime(uint32_t Mprime)
+{
+    REG_WRITE(RSA_M_DASH_REG, Mprime);
+}
+
+static inline void mpi_ll_write_rinv(uint32_t rinv)
+{
+    REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
+}
+
+static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
+    REG_WRITE(mem_base, value);
+}
+
+/* Read MPI bignum (p) back from hardware memory block.
+
+   Reads z_words words from block.
+*/
+static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
+{
+    uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
+    esp_dport_access_read_buffer(p, mem_base, num_words);
+    /* Zero any remaining limbs in the bignum, if the buffer is bigger
+       than num_words */
+    for (size_t i = num_words; i < n; i++) {
+        p[i] = 0;
+    }
+}
+
+static inline void mpi_ll_set_mode(size_t length)
+{
+    REG_WRITE(RSA_LENGTH_REG, length);
+}
+
+static inline void mpi_ll_disable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+}
+
+static inline void mpi_ll_enable_constant_time(void)
+{
+    REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
+}
+
+static inline void mpi_ll_disable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
+}
+
+static inline void mpi_ll_enable_search(void)
+{
+    REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
+}
+
+static inline void mpi_ll_set_search_position(size_t pos)
+{
+    REG_WRITE(RSA_SEARCH_POS_REG, pos);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 146 - 0
components/hal/include/hal/mpi_hal.h

@@ -0,0 +1,146 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*******************************************************************************
+ * NOTICE
+ * The HAL is not public api, don't use in application code.
+ * See readme.md in soc/README.md
+ ******************************************************************************/
+
+#pragma once
+
+#include <stdbool.h>
+#include <sys/param.h>
+#include "hal/mpi_types.h"
+
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Calculate the number of words needed to represent the input word in hardware.
+ *
+ * @param words The number of words to be represented.
+ * @return size_t Number of words required.
+ */
+size_t mpi_hal_calc_hardware_words(size_t words);
+
+/**
+ * @brief Clear the MPI power control bit and intitialise the MPI hardware.
+ *
+ */
+void mpi_hal_enable_hardware_hw_op(void);
+
+/**
+ * @brief Set the MPI power control bit to disable the MPI hardware.
+ *
+ */
+void mpi_hal_disable_hardware_hw_op(void);
+
+/**
+ * @brief Enable/disables MPI operation complete interrupt.
+ *
+ * @param enable true: enable, false: disable.
+ */
+void mpi_hal_interrupt_enable(bool enable);
+
+/**
+ * @brief Clears the MPI operation complete interrupt status.
+ *
+ */
+void mpi_hal_clear_interrupt(void);
+
+/**
+ * @brief Configure RSA length.
+ *
+ * @param num_words Number of words representing the RSA length.
+ */
+void mpi_hal_set_mode(size_t num_words);
+
+/**
+ * @brief Copy the large number (array of words) representation of the parameter 'param' to hardware memory block.
+ *
+ * @param param Type of parameter (enum).
+ * @param offset Offset to copy in the memory from the base address of the parameter.
+ * @param p Pointer to large number (array of words) representation of the parameter.
+ * @param n Number of words needed to represent the large number as an array of words.
+ * @param num_words Maximum hardware words needed.
+ */
+void mpi_hal_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words);
+
+/**
+ * @brief Write a word-sized value to hardware memory block of a parameter.
+ *
+ * @param param Type of parameter (enum).
+ * @param offset Offset to copy in the memory from the base address of the parameter.
+ * @param value Value to be written in the memory.
+ */
+void mpi_hal_write_at_offset(mpi_param_t param, int offset, uint32_t value);
+
+/**
+ * @brief Write the modular multiplicative inverse of M.
+ *
+ * @param Mprime Modular multiplicative inverse of M.
+ */
+void mpi_hal_write_m_prime(uint32_t Mprime);
+
+/**
+ * @brief Write first word of the parametr Rinv.
+ *
+ * @param rinv Value of first word of rinv.
+ */
+void mpi_hal_write_rinv(uint32_t rinv);
+
+#if !CONFIG_IDF_TARGET_ESP32
+/**
+ * @brief Enable/Disable constant time acceleration option.
+ *
+ * @param enable true: enable, false: disable.
+ */
+void mpi_hal_enable_constant_time(bool enable);
+
+/**
+ * @brief Enable/Disable search time acceleration option.
+ *
+ * @param enable
+ */
+void mpi_hal_enable_search(bool enable);
+
+/**
+ * @brief Configures the starting address to start search.
+ *
+ * @param position Address to start search.
+ */
+void mpi_hal_set_search_position(size_t position);
+#endif /* !CONFIG_IDF_TARGET_ESP32 */
+
+/**
+ * @brief Begin an MPI operation.
+ *
+ * @param op Operation type (enum).
+ */
+void mpi_hal_start_op(mpi_op_t op);
+
+/**
+ * @brief  Wait for an MPI operation to complete.
+ *
+ */
+void mpi_hal_wait_op_complete(void);
+
+/**
+ * @brief Wait for an MPI operation to complete and Read result from last MPI operation into parameter Z.
+ *
+ * @param p Pointer to large number (array of words) representation of the parameter.
+ * @param n Number of words needed to represent the large number as an array of words.
+ * @param z_words Calculated number of words of parameter Z.
+ */
+void mpi_hal_read_result_hw_op(uint32_t* p, size_t n, size_t z_words);
+
+#ifdef __cplusplus
+}
+#endif

+ 19 - 0
components/hal/include/hal/mpi_types.h

@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+typedef enum {
+    MPI_MULT = 0x0,             // (X * Y)
+    MPI_MODMULT,                // (X * Y) Mod M
+    MPI_MODEXP,                 // (X ^ Y) Mod M
+} mpi_op_t;
+
+typedef enum {
+    MPI_PARAM_X = 0x0,
+    MPI_PARAM_Y,
+    MPI_PARAM_Z,
+    MPI_PARAM_M,
+} mpi_param_t;

+ 126 - 0
components/hal/mpi_hal.c

@@ -0,0 +1,126 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "hal/mpi_hal.h"
+#include "hal/mpi_ll.h"
+#include "sdkconfig.h"
+
+
+size_t mpi_hal_calc_hardware_words(size_t words)
+{
+    return mpi_ll_calculate_hardware_words(words);
+}
+
+void mpi_hal_enable_hardware_hw_op(void)
+{
+    mpi_ll_clear_power_control_bit();
+    while (mpi_ll_check_memory_init_complete()) {
+    }
+    // Note: from enabling RSA clock to here takes about 1.3us
+
+#if !CONFIG_IDF_TARGET_ESP32
+    mpi_ll_disable_interrupt();
+#endif
+}
+
+void mpi_hal_disable_hardware_hw_op(void)
+{
+    mpi_ll_set_power_control_bit();
+}
+
+void mpi_hal_interrupt_enable(bool enable)
+{
+    if (enable){
+        mpi_ll_enable_interrupt();
+    }
+    else {
+        mpi_ll_disable_interrupt();
+    }
+}
+
+void mpi_hal_clear_interrupt(void)
+{
+    mpi_ll_clear_interrupt();
+}
+
+void mpi_hal_set_mode(size_t num_words)
+{
+    mpi_ll_set_mode(num_words);
+}
+
+void mpi_hal_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
+{
+    mpi_ll_write_to_mem_block(param, offset, p, n, num_words);
+}
+
+void mpi_hal_write_at_offset(mpi_param_t param, int offset, uint32_t value)
+{
+    mpi_ll_write_at_offset(param, offset, value);
+}
+
+void mpi_hal_write_m_prime(uint32_t Mprime)
+{
+    mpi_ll_write_m_prime(Mprime);
+}
+
+void mpi_hal_write_rinv(uint32_t rinv)
+{
+    mpi_ll_write_rinv(rinv);
+}
+
+// Acceleration options
+#if !CONFIG_IDF_TARGET_ESP32
+void mpi_hal_enable_constant_time(bool enable)
+{
+    if (enable){
+        mpi_ll_enable_constant_time();
+    }
+    else {
+        mpi_ll_disable_constant_time();
+    }
+}
+
+void mpi_hal_enable_search(bool enable)
+{
+    if (enable){
+        mpi_ll_enable_search();
+    }
+    else {
+        mpi_ll_disable_search();
+    }
+}
+
+void mpi_hal_set_search_position(size_t position)
+{
+    mpi_ll_set_search_position(position);
+}
+#endif /* !CONFIG_IDF_TARGET_ESP32 */
+
+/* Begin an RSA operation.
+*/
+void mpi_hal_start_op(mpi_op_t op)
+{
+    /* Clear interrupt status */
+    mpi_hal_clear_interrupt();
+    mpi_ll_start_op(op);
+}
+
+/* Wait for an RSA operation to complete.
+*/
+void mpi_hal_wait_op_complete(void)
+{
+    while (mpi_ll_get_int_status())
+    { }
+
+    /* Clear interrupt status */
+    mpi_hal_clear_interrupt();
+}
+
+void mpi_hal_read_result_hw_op(uint32_t* p, size_t n, size_t z_words)
+{
+    /* Wait for an RSA operation to complete. */
+    mpi_hal_wait_op_complete();
+    mpi_ll_read_from_mem_block(p, n, z_words);
+}

+ 7 - 0
components/hal/test_apps/mpi/CMakeLists.txt

@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.16)
+
+set(COMPONENTS main)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+
+project(mpi_test)

+ 33 - 0
components/hal/test_apps/mpi/README.md

@@ -0,0 +1,33 @@
+| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
+
+## MPI peripheral test
+
+This application contains basic test cases for the MPI peripheral without using any OS functionality or higher abstraction layer.
+
+This contains tests for the following features of MPI peripheral:
+
+- MPI Modular Multiplication
+- MPI Multiplication
+- MPI Modular Exponentiation
+
+# Building
+
+```bash
+idf.py set-target <TARGET>
+idf.py build
+```
+
+# Running the app manually
+
+```bash
+idf.py flash monitor
+```
+
+Enter the test that you want to run locally
+
+# Running tests
+
+```bash
+pytest --target <TARGET>
+```

+ 6 - 0
components/hal/test_apps/mpi/main/CMakeLists.txt

@@ -0,0 +1,6 @@
+set(srcs "app_main.c"
+         "test_mpi.c")
+
+idf_component_register(SRCS ${srcs}
+                       REQUIRES unity
+                       WHOLE_ARCHIVE)

+ 13 - 0
components/hal/test_apps/mpi/main/app_main.c

@@ -0,0 +1,13 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+
+void app_main(void)
+{
+    unity_run_menu();
+}

+ 145 - 0
components/hal/test_apps/mpi/main/test_mpi.c

@@ -0,0 +1,145 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include "esp_log.h"
+#include "esp_private/periph_ctrl.h"
+#include "unity.h"
+
+#if CONFIG_IDF_TARGET_ESP32
+#define ESP_MPI_USE_MONT_EXP
+#endif
+
+#include "hal/mpi_hal.h"
+#include "test_params.h"
+
+#define _DEBUG_ 0
+
+
+static void esp_mpi_enable_hardware_hw_op( void )
+{
+    /* Enable RSA hardware */
+    periph_module_enable(PERIPH_RSA_MODULE);
+
+    mpi_hal_enable_hardware_hw_op();
+}
+
+
+static void esp_mpi_disable_hardware_hw_op( void )
+{
+    mpi_hal_disable_hardware_hw_op();
+
+    /* Disable RSA hardware */
+    periph_module_disable(PERIPH_RSA_MODULE);
+}
+
+
+static void mpi_mul_mpi_mod_hw_op(void)
+{
+    esp_mpi_enable_hardware_hw_op();
+    for(int i = 0; i < TEST_CASES_NUM; i++){
+#if CONFIG_IDF_TARGET_ESP32
+        mpi_hal_set_mode((test_cases_num_words[i] / 16) - 1);
+#else
+        mpi_hal_set_mode(test_cases_num_words[i] - 1);
+#endif
+        /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
+        mpi_hal_write_to_mem_block(MPI_PARAM_M, 0, test_cases_M_p[i], test_cases_M_n[i], test_cases_num_words[i]);
+        mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, test_cases_X_p[i], test_cases_X_n[i], test_cases_num_words[i]);
+
+#if !CONFIG_IDF_TARGET_ESP32
+        mpi_hal_write_to_mem_block(MPI_PARAM_Y, 0, test_cases_Y_p[i], test_cases_Y_n[i], test_cases_num_words[i]);
+#endif
+
+        mpi_hal_write_to_mem_block(MPI_PARAM_Z, 0, test_cases_Rinv_p[i], test_cases_Rinv_n[i], test_cases_num_words[i]);
+        mpi_hal_write_m_prime(test_cases_Mprime[i]);
+
+#if CONFIG_IDF_TARGET_ESP32
+        mpi_hal_start_op(MPI_MULT);
+        mpi_hal_wait_op_complete();
+        /* execute second stage */
+        /* Load Y to X input memory block, rerun */
+        mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, test_cases_Y_p[i], test_cases_Y_n[i], test_cases_num_words[i]);
+        mpi_hal_start_op(MPI_MULT);
+#else
+        mpi_hal_start_op(MPI_MODMULT);
+#endif
+        uint32_t* Z_p = (uint32_t*)calloc(test_cases_Z_words[i], sizeof(uint32_t));
+        mpi_hal_read_result_hw_op(Z_p, test_cases_Z_words[i], test_cases_Z_words[i]);
+
+        printf("Test Case %d: ", i+1);
+
+#if _DEBUG_
+        printf("\n");
+        ESP_LOG_BUFFER_HEX("Expected Z:", test_cases_Z_p[i], test_cases_Z_words[i]*4);
+        ESP_LOG_BUFFER_HEX("Got Z:", Z_p, test_cases_Z_words[i]*4);
+#endif
+
+        TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(test_cases_Z_p[i], Z_p, test_cases_Z_words[i], "Result");
+        printf("PASS\n");
+    }
+    esp_mpi_disable_hardware_hw_op();
+}
+
+
+static void mpi_exp_mpi_mod_hw_op(void)
+{
+
+    for (int i = 0; i < EXP_TEST_CASES_NUM; i++) {
+        if (i == 14 || i == 16 || i == 18 || i == 22) // cases when Y == 0 (in Z = X ^ Y mod M) should be handled in the software level
+            continue;
+#ifdef ESP_MPI_USE_MONT_EXP     // CONFIG_IDF_TARGET_ESP32
+        printf("Support for montgomery exponentiation to be added.\n");
+        break;
+#else
+        esp_mpi_enable_hardware_hw_op();
+
+        mpi_hal_set_mode(exp_test_cases_num_words[i] - 1);
+        mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, exp_test_cases_X_p[i], exp_test_cases_X_n[i], exp_test_cases_num_words[i]);
+        mpi_hal_write_to_mem_block(MPI_PARAM_Y, 0, exp_test_cases_Y_p[i], exp_test_cases_Y_n[i], exp_test_cases_num_words[i]);
+        mpi_hal_write_to_mem_block(MPI_PARAM_M, 0, exp_test_cases_M_p[i], exp_test_cases_M_n[i], exp_test_cases_num_words[i]);
+        mpi_hal_write_to_mem_block(MPI_PARAM_Z, 0, exp_test_cases_Rinv_p[i], exp_test_cases_Rinv_n[i], exp_test_cases_num_words[i]);
+
+        mpi_hal_write_m_prime(exp_test_cases_Mprime[i]);
+
+        /* Enable acceleration options */
+        mpi_hal_enable_constant_time(false);
+        mpi_hal_enable_search(true);
+        mpi_hal_set_search_position(exp_test_cases_y_bits[i] - 1);
+
+        /* Execute first stage montgomery multiplication */
+        mpi_hal_start_op(MPI_MODEXP);
+
+        mpi_hal_enable_search(false);
+#endif
+        uint32_t* Z_p = (uint32_t*)calloc(exp_test_cases_m_words[i], sizeof(uint32_t));
+        /* Read back the result */
+        mpi_hal_read_result_hw_op(Z_p, exp_test_cases_m_words[i], exp_test_cases_m_words[i]);
+        esp_mpi_disable_hardware_hw_op();
+
+        printf("Test Case %d: ", i+1);
+
+#if _DEBUG_
+        printf("\n");
+        ESP_LOG_BUFFER_HEX("Expected Z:", test_cases_Z_p[i], test_cases_Z_words[i]*4);
+        ESP_LOG_BUFFER_HEX("Got Z:", Z_p, test_cases_Z_words[i]*4);
+#endif
+
+        TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(exp_test_cases_Z_p[i], Z_p, exp_test_cases_m_words[i], "Result");
+        printf("PASS\n");
+    }
+}
+
+TEST_CASE("Test MPI multiplication", "[mpi][hal]")
+{
+    mpi_mul_mpi_mod_hw_op();
+}
+
+TEST_CASE("Test MPI exponentiation", "[mpi][hal]")
+{
+    mpi_exp_mpi_mod_hw_op();
+}

+ 382 - 0
components/hal/test_apps/mpi/main/test_params.h

@@ -0,0 +1,382 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#define TEST_CASES_NUM 11
+
+const uint32_t M_p_1[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_1[] = { 0x10 };
+const uint32_t Y_p_1[] = { 0x100 };
+const uint32_t Rinv_p_1[] = { 0x1 };
+const uint32_t Z_p_1[] = { 0x1000 };
+
+const uint32_t M_p_2[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_2[] = { 0x10 };
+const uint32_t Y_p_2[] = { 0x100 };
+const uint32_t Rinv_p_2[] = { 0x1 };
+const uint32_t Z_p_2[] = { 0x1000 };
+
+const uint32_t M_p_3[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_3[] = { 0x10 };
+const uint32_t Y_p_3[] = { 0x100 };
+const uint32_t Rinv_p_3[] = { 0x1 };
+const uint32_t Z_p_3[] = { 0x1000 };
+
+const uint32_t M_p_4[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_4[] = { 0x10 };
+const uint32_t Y_p_4[] = { 0x100 };
+const uint32_t Rinv_p_4[] = { 0x1 };
+const uint32_t Z_p_4[] = { 0x1000 };
+
+const uint32_t M_p_5[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_5[] = { 0x10 };
+const uint32_t Y_p_5[] = { 0x100 };
+const uint32_t Rinv_p_5[] = { 0x1 };
+const uint32_t Z_p_5[] = { 0x1000 };
+
+const uint32_t M_p_6[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_6[] = { 0x10 };
+const uint32_t Y_p_6[] = { 0x100 };
+const uint32_t Rinv_p_6[] = { 0x1 };
+const uint32_t Z_p_6[] = { 0x1000 };
+
+const uint32_t M_p_7[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_7[] = { 0x0, 0xd3101957, 0xecee5346, 0xb54d2f52, 0x442296ec, 0x19cd3ca8, 0x8550f006, 0x41c3f1e1, 0xa488720b, 0xcc4cb107, 0x85fb0e86, 0xcf2ed8f6, 0x4f108e15, 0x60ffaadb, 0x46be39b8, 0x8d3e3bd7, 0x60006fa };
+const uint32_t Y_p_7[] = { 0xbf474ca7 };
+const uint32_t Rinv_p_7[] = { 0x1 };
+const uint32_t Z_p_7[] = { 0x0, 0x67275bc1, 0x404ee63b, 0x2e2c03aa, 0x2e4998f4, 0x20653a31, 0x1dffabd1, 0x6aa51a39, 0xde0e2bad, 0xd7762fc2, 0x88e65fef, 0x2a4e310f, 0x2b9b939a, 0x3051d823, 0x31bc0b75, 0xd3d97e42, 0xcaf58a48, 0x47bb102 };
+
+const uint32_t M_p_8[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_8[] = { 0x80000000, 0xd64787bc, 0x19d05e3d, 0xbd83a839, 0xd2f4a5db, 0x9a770400, 0xaea5e366, 0xafab037d, 0x2f72be37, 0x41e9e9f0, 0xfa4a3585, 0x148ba01f, 0x40d718ca, 0x7be1c5, 0xc033696c, 0x9fdf9e27, 0x5c9d44c0, 0xad60775d, 0xaa67e3aa, 0xe76bd66f, 0x5738985c, 0xdf079b6b, 0x99626884, 0x5361ec05, 0x756ed496, 0xf5e04245, 0xc87d1791, 0xdf9abc30, 0xc44768ea, 0xeaf3bbeb, 0xc01eeb01, 0xc229831e, 0x49493a };
+const uint32_t Y_p_8[] = { 0xb878cc29 };
+const uint32_t Rinv_p_8[] = { 0x1 };
+const uint32_t Z_p_8[] = { 0x80000000, 0x6dfaf330, 0xcc7839bf, 0x29754f1f, 0x6c9121d6, 0xc430620, 0x80e52130, 0x619ccf81, 0x39521993, 0x3f9293c8, 0x165fc8a8, 0x98d8c9d3, 0xa7b1fd46, 0x66d156e7, 0xcb373706, 0x819f0d65, 0xd52d2cbe, 0xb1e5f6e3, 0x78ae1381, 0xc5f8e002, 0x435c6bf7, 0xc912fdbc, 0x7aa2a247, 0xba1e460, 0xd28d4e10, 0x12b0ab73, 0xbff58710, 0x64b6e727, 0x55daff98, 0x66604e0d, 0xf1fe7bda, 0xbda2c86c, 0x13066d5, 0x34cf37 };
+
+const uint32_t M_p_9[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_9[] = { 0xcae9a34d, 0xa031f21e, 0x1e85b5df, 0xe071513a, 0xe81a1521, 0x74ca15f3, 0xdde2beb6, 0x7af1fedf, 0xc8632240, 0x3b9f880f, 0xcf78b817, 0x4cabb724, 0x19816423, 0x7f123142, 0xe07ee72c, 0xddf79c5c, 0x634f9e8c, 0xf7ee8c0c, 0x4a8a9a45, 0x37ae1b48, 0x2d288558, 0xe33fa325, 0x77937f, 0x5091386c, 0xa9d3bfa7, 0x3102f8b4, 0x2bc44d25, 0xfc66ca47, 0x3d25e64e, 0xfdd30308, 0x85468786, 0x24bf61 };
+const uint32_t Y_p_9[] = { 0x10001 };
+const uint32_t Rinv_p_9[] = { 0x1 };
+const uint32_t Z_p_9[] = { 0x6e36a34d, 0x9250bd08, 0xd4655611, 0x31ab6fbf, 0xfd3bf593, 0x8abdfe0d, 0x9c993380, 0x79d1dcc2, 0xeaa39d32, 0xc3af5072, 0x878ff3b6, 0x3d0869d, 0x7da4b0cf, 0xb0544ac3, 0xc7ab663e, 0x7a547cdb, 0x1dc7c84, 0x83faef5c, 0xe4d09234, 0x52f665d2, 0xb280bd06, 0x8664d04d, 0x93f776bf, 0x88fd38e3, 0x697b1038, 0x29b7a288, 0x78e97e28, 0xc6adf60b, 0x2374e2b5, 0xdb402e, 0xccd855a, 0xbf8644a8, 0x24 };
+
+const uint32_t M_p_10[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_10[] = { 0x35893620, 0x6f4b348d, 0x95c4fc96, 0xef12340b, 0xa7dec5d5, 0x56fe1e8e, 0x9486fc80, 0x6f8819d6, 0x467ada31, 0x856a2147, 0x780e9b54, 0xe9da7683, 0x46a906b7, 0x22137235, 0xc417edd0, 0x5d88b669 };
+const uint32_t Y_p_10[] = { 0x6f48ea08, 0xf5a8c50d, 0xc169d74b, 0xa74206ce, 0xeb9f2d2f, 0xbbccba7f, 0xd33605ae, 0xf5a3b2a5, 0xe2bf4411, 0x275aa977, 0xb2f0e2dd, 0xf38d18d2, 0x239eadae, 0xf71896fc, 0x9546432d, 0x9ae7fbc9 };
+const uint32_t Rinv_p_10[] = { 0x1 };
+const uint32_t Z_p_10[] = { 0x30c2f100, 0xadeea408, 0x678bd2f4, 0x99540c47, 0xeba56331, 0x72d75ec6, 0x8fd72c77, 0x3a8b12c3, 0x49eb461a, 0xd332b1ff, 0xcdf59485, 0x4b0a83bb, 0xe4432ee7, 0x74a9bbeb, 0xaf573efb, 0xbc97b670, 0x8c3442f3, 0x8fbf01de, 0xd646884e, 0x76095187, 0x98628219, 0x93746469, 0xf900c0c9, 0x2b2be5a7, 0xa2949bc8, 0x3d832701, 0xc4c9270a, 0xbb7cd629, 0x339aee72, 0x3b5e6aee, 0xeb21810e, 0x38990016 };
+
+const uint32_t M_p_11[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
+const uint32_t X_p_11[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 };
+const uint32_t Y_p_11[] = { 0x1234 };
+const uint32_t Rinv_p_11[] = { 0x1 };
+const uint32_t Z_p_11[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x48d0 };
+
+const uint32_t* test_cases_M_p[TEST_CASES_NUM] = {
+    M_p_1, M_p_2, M_p_3, M_p_4, M_p_5, M_p_6, M_p_7, M_p_8, M_p_9, M_p_10, M_p_11,
+};
+
+const uint32_t* test_cases_X_p[TEST_CASES_NUM] = {
+    X_p_1, X_p_2, X_p_3, X_p_4, X_p_5, X_p_6, X_p_7, X_p_8, X_p_9, X_p_10, X_p_11,
+};
+
+const uint32_t* test_cases_Y_p[TEST_CASES_NUM] = {
+    Y_p_1, Y_p_2, Y_p_3, Y_p_4, Y_p_5, Y_p_6, Y_p_7, Y_p_8, Y_p_9, Y_p_10, Y_p_11,
+};
+
+const uint32_t* test_cases_Rinv_p[TEST_CASES_NUM] = {
+    Rinv_p_1, Rinv_p_2, Rinv_p_3, Rinv_p_4, Rinv_p_5, Rinv_p_6, Rinv_p_7, Rinv_p_8, Rinv_p_9, Rinv_p_10, Rinv_p_11,
+};
+
+const uint32_t* test_cases_Z_p[TEST_CASES_NUM] = {
+    Z_p_1, Z_p_2, Z_p_3, Z_p_4, Z_p_5, Z_p_6, Z_p_7, Z_p_8, Z_p_9, Z_p_10, Z_p_11,
+};
+
+const uint32_t test_cases_Mprime[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+size_t test_cases_M_n[TEST_CASES_NUM] = {
+    16, 32, 48, 64, 80, 96, 32, 96, 48, 64, 96,
+};
+
+size_t test_cases_X_n[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 17, 33, 32, 16, 65,
+};
+
+size_t test_cases_Y_n[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 1,
+};
+
+size_t test_cases_Rinv_n[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+size_t test_cases_Z_n[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 18, 34, 33, 32, 65,
+};
+
+size_t test_cases_Z_words[TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 18, 34, 33, 32, 65,
+};
+
+size_t test_cases_num_words[TEST_CASES_NUM] = {
+    16, 32, 48, 64, 80, 96, 32, 96, 48, 64, 96,
+};
+
+
+
+#define EXP_TEST_CASES_NUM 33
+
+const uint32_t exp_M_p_1[] = { 0xffffffff,};
+const uint32_t exp_X_p_1[] = { 0x1000,};
+const uint32_t exp_Y_p_1[] = { 0x2, };
+const uint32_t exp_Rinv_p_1[] = { 0x1, };
+const uint32_t exp_Z_p_1[] = { 0x1000000, };
+
+const uint32_t exp_M_p_2[] = { 0xfffffff,};
+const uint32_t exp_X_p_2[] = { 0x1234,};
+const uint32_t exp_Y_p_2[] = { 0x2, };
+const uint32_t exp_Rinv_p_2[] = { 0x100, };
+const uint32_t exp_Z_p_2[] = { 0x14b5a90, };
+
+const uint32_t exp_M_p_3[] = { 0xffffffff,};
+const uint32_t exp_X_p_3[] = { 0x1111,};
+const uint32_t exp_Y_p_3[] = { 0x2, };
+const uint32_t exp_Rinv_p_3[] = { 0x1, };
+const uint32_t exp_Z_p_3[] = { 0x1234321, };
+
+const uint32_t exp_M_p_4[] = { 0x3,};
+const uint32_t exp_X_p_4[] = { 0x5,};
+const uint32_t exp_Y_p_4[] = { 0x1, };
+const uint32_t exp_Rinv_p_4[] = { 0x1, };
+const uint32_t exp_Z_p_4[] = { 0x2, };
+
+const uint32_t exp_M_p_5[] = { 0x33,};
+const uint32_t exp_X_p_5[] = { 0x55,};
+const uint32_t exp_Y_p_5[] = { 0x1, };
+const uint32_t exp_Rinv_p_5[] = { 0x1, };
+const uint32_t exp_Z_p_5[] = { 0x22, };
+
+const uint32_t exp_M_p_6[] = { 0x333,};
+const uint32_t exp_X_p_6[] = { 0x555,};
+const uint32_t exp_Y_p_6[] = { 0x1, };
+const uint32_t exp_Rinv_p_6[] = { 0x10, };
+const uint32_t exp_Z_p_6[] = { 0x222, };
+
+const uint32_t exp_M_p_7[] = { 0x3333,};
+const uint32_t exp_X_p_7[] = { 0x5555,};
+const uint32_t exp_Y_p_7[] = { 0x1, };
+const uint32_t exp_Rinv_p_7[] = { 0x1, };
+const uint32_t exp_Z_p_7[] = { 0x2222, };
+
+const uint32_t exp_M_p_8[] = { 0x33,};
+const uint32_t exp_X_p_8[] = { 0x5555,};
+const uint32_t exp_Y_p_8[] = { 0x1, };
+const uint32_t exp_Rinv_p_8[] = { 0x1, };
+const uint32_t exp_Z_p_8[] = { 0x11, };
+
+const uint32_t exp_M_p_9[] = { 0x77,};
+const uint32_t exp_X_p_9[] = { 0x1111,};
+const uint32_t exp_Y_p_9[] = { 0x1, };
+const uint32_t exp_Rinv_p_9[] = { 0x56, };
+const uint32_t exp_Z_p_9[] = { 0x55, };
+
+const uint32_t exp_M_p_10[] = { 0xbb,};
+const uint32_t exp_X_p_10[] = { 0x1111,};
+const uint32_t exp_Y_p_10[] = { 0x2, };
+const uint32_t exp_Rinv_p_10[] = { 0x89, };
+const uint32_t exp_Z_p_10[] = { 0x88, };
+
+const uint32_t exp_M_p_11[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff,};
+const uint32_t exp_X_p_11[] = { 0x2,};
+const uint32_t exp_Y_p_11[] = { 0x128, };
+const uint32_t exp_Rinv_p_11[] = { 0x0, 0x10000, };
+const uint32_t exp_Z_p_11[] = { 0x1000000, 0x0, 0x0, 0x0, 0x0, };
+
+const uint32_t exp_M_p_12[] = { 0xffffffff, 0xffff,};
+const uint32_t exp_X_p_12[] = { 0xdef12345, 0xabc,};
+const uint32_t exp_Y_p_12[] = { 0x1, };
+const uint32_t exp_Rinv_p_12[] = { 0x0, 0x1, };
+const uint32_t exp_Z_p_12[] = { 0xdef12345, 0xabc, };
+
+const uint32_t exp_M_p_13[] = { 0xfffff,};
+const uint32_t exp_X_p_13[] = { 0xabcde,};
+const uint32_t exp_Y_p_13[] = { 0x1, };
+const uint32_t exp_Rinv_p_13[] = { 0x10, };
+const uint32_t exp_Z_p_13[] = { 0xabcde, };
+
+const uint32_t exp_M_p_14[] = { 0x9,};
+const uint32_t exp_X_p_14[] = { 0x2,};
+const uint32_t exp_Y_p_14[] = { 0x2, };
+const uint32_t exp_Rinv_p_14[] = { 0x7, };
+const uint32_t exp_Z_p_14[] = { 0x4, };
+
+const uint32_t exp_M_p_15[] = { 0x9,};
+const uint32_t exp_X_p_15[] = { 0x2,};
+const uint32_t exp_Y_p_15[] = { 0x0, };
+const uint32_t exp_Rinv_p_15[] = { 0x7, };
+const uint32_t exp_Z_p_15[] = { 0x0, };
+
+const uint32_t exp_M_p_16[] = { 0x9,};
+const uint32_t exp_X_p_16[] = { 0x0,};
+const uint32_t exp_Y_p_16[] = { 0x2, };
+const uint32_t exp_Rinv_p_16[] = { 0x7, };
+const uint32_t exp_Z_p_16[] = { 0x0, };
+
+const uint32_t exp_M_p_17[] = { 0x9,};
+const uint32_t exp_X_p_17[] = { 0x0,};
+const uint32_t exp_Y_p_17[] = { 0x0, };
+const uint32_t exp_Rinv_p_17[] = { 0x7, };
+const uint32_t exp_Z_p_17[] = { 0x0, };
+
+const uint32_t exp_M_p_18[] = { 0x9,};
+const uint32_t exp_X_p_18[] = { 0x2,};
+const uint32_t exp_Y_p_18[] = { 0x2, };
+const uint32_t exp_Rinv_p_18[] = { 0x7, };
+const uint32_t exp_Z_p_18[] = { 0x4, };
+
+const uint32_t exp_M_p_19[] = { 0x9,};
+const uint32_t exp_X_p_19[] = { 0x2,};
+const uint32_t exp_Y_p_19[] = { 0x0, };
+const uint32_t exp_Rinv_p_19[] = { 0x7, };
+const uint32_t exp_Z_p_19[] = { 0x0, };
+
+const uint32_t exp_M_p_20[] = { 0x9,};
+const uint32_t exp_X_p_20[] = { 0x2,};
+const uint32_t exp_Y_p_20[] = { 0x7, };
+const uint32_t exp_Rinv_p_20[] = { 0x7, };
+const uint32_t exp_Z_p_20[] = { 0x2, };
+
+const uint32_t exp_M_p_21[] = { 0x9,};
+const uint32_t exp_X_p_21[] = { 0x2,};
+const uint32_t exp_Y_p_21[] = { 0x1, };
+const uint32_t exp_Rinv_p_21[] = { 0x7, };
+const uint32_t exp_Z_p_21[] = { 0x2, };
+
+const uint32_t exp_M_p_22[] = { 0x9,};
+const uint32_t exp_X_p_22[] = { 0x2,};
+const uint32_t exp_Y_p_22[] = { 0x1, };
+const uint32_t exp_Rinv_p_22[] = { 0x7, };
+const uint32_t exp_Z_p_22[] = { 0x2, };
+
+const uint32_t exp_M_p_23[] = { 0x9,};
+const uint32_t exp_X_p_23[] = { 0x2,};
+const uint32_t exp_Y_p_23[] = { 0x0, };
+const uint32_t exp_Rinv_p_23[] = { 0x7, };
+const uint32_t exp_Z_p_23[] = { 0x0, };
+
+const uint32_t exp_M_p_24[] = { 0x7,};
+const uint32_t exp_X_p_24[] = { 0x5,};
+const uint32_t exp_Y_p_24[] = { 0x7, };
+const uint32_t exp_Rinv_p_24[] = { 0x2, };
+const uint32_t exp_Z_p_24[] = { 0x5, };
+
+const uint32_t exp_M_p_25[] = { 0x7,};
+const uint32_t exp_X_p_25[] = { 0x5,};
+const uint32_t exp_Y_p_25[] = { 0x7, };
+const uint32_t exp_Rinv_p_25[] = { 0x2, };
+const uint32_t exp_Z_p_25[] = { 0x5, };
+
+const uint32_t exp_M_p_26[] = { 0x3,};
+const uint32_t exp_X_p_26[] = { 0x5,};
+const uint32_t exp_Y_p_26[] = { 0x7, };
+const uint32_t exp_Rinv_p_26[] = { 0x1, };
+const uint32_t exp_Z_p_26[] = { 0x2, };
+
+const uint32_t exp_M_p_27[] = { 0x23456789, 0x1,};
+const uint32_t exp_X_p_27[] = { 0x23456789, 0x1,};
+const uint32_t exp_Y_p_27[] = { 0x23456789, 0x1, };
+const uint32_t exp_Rinv_p_27[] = { 0x34890700, };
+const uint32_t exp_Z_p_27[] = { 0x0, 0x0, };
+
+const uint32_t exp_M_p_28[] = { 0x23456789, 0x1,};
+const uint32_t exp_X_p_28[] = { 0x23456788, 0x1,};
+const uint32_t exp_Y_p_28[] = { 0x23456788, 0x1, };
+const uint32_t exp_Rinv_p_28[] = { 0x34890700, };
+const uint32_t exp_Z_p_28[] = { 0x1, 0x0, };
+
+const uint32_t exp_M_p_29[] = { 0x23456789, 0x1,};
+const uint32_t exp_X_p_29[] = { 0x2345678a, 0x1,};
+const uint32_t exp_Y_p_29[] = { 0x2345678a, 0x1, };
+const uint32_t exp_Rinv_p_29[] = { 0x34890700, };
+const uint32_t exp_Z_p_29[] = { 0x1, 0x0, };
+
+const uint32_t exp_M_p_30[] = { 0x7,};
+const uint32_t exp_X_p_30[] = { 0x32,};
+const uint32_t exp_Y_p_30[] = { 0x3e9, };
+const uint32_t exp_Rinv_p_30[] = { 0x2, };
+const uint32_t exp_Z_p_30[] = { 0x1, };
+
+const uint32_t exp_M_p_31[] = { 0xd2f86373, 0x7dc0eddd, 0x1a27c06f, 0xbe6e3437, 0xa3fa8342, 0x47be20c9, 0x4532cdf5, 0x728e8766, 0x31e46aa7, 0xdc5e8c72, 0xba39c6b2, 0x29c291b4, 0xab5f5cf4, 0xa90e51bb, 0xfc1e677d, 0x5347c68a, 0xd95f7d6, 0xae98132b, 0x135c643c, 0x2e9e82e9, 0x5a540609, 0x3274e472, 0xb24222d0, 0x9153bd76, 0x1a5c9640, 0xaa94b8bb, 0xeb740f69, 0xc3cdd261, 0x323b9c45, 0x957ff5dd, 0x8419a724, 0xcf5cf5c3,};
+const uint32_t exp_X_p_31[] = { 0x2,};
+const uint32_t exp_Y_p_31[] = { 0xa9e42102, 0x5ab4a0f, 0xc529b673, 0x1684435d, 0x33f2d8fb, 0xdb42b4e7, 0x103e8eb9, 0xbf8de4ed, 0x91537869, 0x11c88a96, 0xcdff05bd, 0x157f8be2, 0xf6c63d3d, 0x36e4ee76, 0xd15c29a7, 0x3e6071e0, 0x3e2b0c1d, 0x54444d19, 0x62699c34, 0xe9ffd47a, 0x1acf4cb1, 0x3617251a, 0x29a256a, 0x884c0e32, 0xcb883a85, 0xcf364770, 0xa5f2da4, 0x32166b1f, 0xda3deaf5, 0xb4fed79a, 0xa82ccab3, 0x471cc5f6, };
+const uint32_t exp_Rinv_p_31[] = { 0x6787f727, 0xc0dc79ce, 0x22066424, 0x4c6a2bf8, 0x5b81cb65, 0x169a350a, 0x47a07b05, 0x2a086619, 0xe5143481, 0xaddd2a07, 0xf3087ad4, 0xb7e7b5cd, 0xeff1c6f6, 0xa35ab988, 0x3cb3c643, 0xd53b3480, 0xcda6a846, 0xd51c411a, 0x840fea4, 0x2b55e639, 0x680557e2, 0x46c77daf, 0x1d110ae6, 0x9cf0f62b, 0x51257507, 0x63d1c63e, 0xdaccc4cf, 0xe3af579d, 0xe58ed7b0, 0x6950d5aa, 0x21471db1, 0x4ca3e886, };
+const uint32_t exp_Z_p_31[] = { 0xe0b8c80b, 0xba541503, 0x26937a8c, 0xd0372fac, 0xc4cb31b4, 0x40d71bbc, 0xefb6ac09, 0x15ad27f9, 0xcee9542a, 0xa247a4a2, 0xf204c903, 0x18728efd, 0x28b5313f, 0x21b6d67f, 0x7efb40c2, 0xf5df3fd7, 0xa49ed483, 0x8024b012, 0xbf355f2a, 0xd19d4b1f, 0xa308f006, 0x20cd0b86, 0x5e9db2bb, 0xf0c89b5c, 0x801c9b5a, 0x277ab525, 0x90ce4180, 0x7df883ab, 0xdad05b20, 0x6cb02835, 0x76a157ec, 0x5fa6cb1f, };
+
+const uint32_t exp_M_p_32[] = { 0xd2f86373, 0x7dc0eddd, 0x1a27c06f, 0xbe6e3437, 0xa3fa8342, 0x47be20c9, 0x4532cdf5, 0x728e8766, 0x31e46aa7, 0xdc5e8c72, 0xba39c6b2, 0x29c291b4, 0xab5f5cf4, 0xa90e51bb, 0xfc1e677d, 0x5347c68a, 0xd95f7d6, 0xae98132b, 0x135c643c, 0x2e9e82e9, 0x5a540609, 0x3274e472, 0xb24222d0, 0x9153bd76, 0x1a5c9640, 0xaa94b8bb, 0xeb740f69, 0xc3cdd261, 0x323b9c45, 0x957ff5dd, 0x8419a724, 0xcf5cf5c3,};
+const uint32_t exp_X_p_32[] = { 0x2,};
+const uint32_t exp_Y_p_32[] = { 0xc0ac270d, 0x6a920e46, 0x8b4cdbf7, 0x96bc5489, 0xdc34fba7, 0xc94c1e56, 0x5eb67c32, 0xa5cb5328, 0x2c08454e, 0x185d67c0, 0x3e0fc930, 0xc1d9a7ce, 0xf73a0e3d, 0x53793857, 0x321e02fe, 0xaee0f18e, 0xb90d3299, 0xc5d34dc6, 0xb22d47a0, 0x9d109034, 0x659ac869, 0xb2a2de08, 0x9f7fc81, 0x229e03b5, 0x3e84ebc3, 0x60838601, 0xc82c0d5c, 0x1d4c659a, 0x8af97f04, 0xda8a3379, 0xc81a8696, 0x31fbcfdd, };
+const uint32_t exp_Rinv_p_32[] = { 0x6787f727, 0xc0dc79ce, 0x22066424, 0x4c6a2bf8, 0x5b81cb65, 0x169a350a, 0x47a07b05, 0x2a086619, 0xe5143481, 0xaddd2a07, 0xf3087ad4, 0xb7e7b5cd, 0xeff1c6f6, 0xa35ab988, 0x3cb3c643, 0xd53b3480, 0xcda6a846, 0xd51c411a, 0x840fea4, 0x2b55e639, 0x680557e2, 0x46c77daf, 0x1d110ae6, 0x9cf0f62b, 0x51257507, 0x63d1c63e, 0xdaccc4cf, 0xe3af579d, 0xe58ed7b0, 0x6950d5aa, 0x21471db1, 0x4ca3e886, };
+const uint32_t exp_Z_p_32[] = { 0x72837fbb, 0xa05c374, 0x63313198, 0xb1279b89, 0xfa1d0aed, 0xeb85c9fe, 0x9d459304, 0x6b756906, 0x4df3a615, 0xe70a90f6, 0xf9354188, 0xf3bc207, 0xa5b817c1, 0xdd4c5b68, 0x222da242, 0x8e683e34, 0xa6674536, 0xfc607769, 0x7a6dd910, 0x36c37489, 0x2ae01e97, 0x87ed74ef, 0xb7528452, 0x242a381f, 0xf886bd3e, 0xb8240556, 0x7ae70a33, 0x9c193652, 0x636c4ab6, 0x11be9d23, 0x1ea9b22b, 0x368a3229, };
+
+const uint32_t exp_M_p_33[] = { 0xd2f86373, 0x7dc0eddd, 0x1a27c06f, 0xbe6e3437, 0xa3fa8342, 0x47be20c9, 0x4532cdf5, 0x728e8766, 0x31e46aa7, 0xdc5e8c72, 0xba39c6b2, 0x29c291b4, 0xab5f5cf4, 0xa90e51bb, 0xfc1e677d, 0x5347c68a, 0xd95f7d6, 0xae98132b, 0x135c643c, 0x2e9e82e9, 0x5a540609, 0x3274e472, 0xb24222d0, 0x9153bd76, 0x1a5c9640, 0xaa94b8bb, 0xeb740f69, 0xc3cdd261, 0x323b9c45, 0x957ff5dd, 0x8419a724, 0xcf5cf5c3,};
+const uint32_t exp_X_p_33[] = { 0xf17d532d, 0x9136fa85, 0x5daf568, 0x36bed5aa, 0x4e2e5ca1, 0x90ca0228, 0x5d795c60, 0x264a452a, 0xe88187b5, 0x400f8fd8, 0x834268f1, 0x876eb7ee, 0x5165b72c, 0x162dd5ba, 0x4034c1f2, 0x6e58383, 0xb26c5b24, 0x7bbe3afb, 0x9722db6b, 0xe6624ae8, 0x1546d7dd, 0xddc0b14f, 0xf10ed6c2, 0x5dcfd1f9, 0x43658bc4, 0x18084e67, 0xf2b57c8a, 0x445d45f1, 0xc1465fff, 0xa7efdf9e, 0x632d9e50, 0xbdad66c8,};
+const uint32_t exp_Y_p_33[] = { 0xa9e42102, 0x5ab4a0f, 0xc529b673, 0x1684435d, 0x33f2d8fb, 0xdb42b4e7, 0x103e8eb9, 0xbf8de4ed, 0x91537869, 0x11c88a96, 0xcdff05bd, 0x157f8be2, 0xf6c63d3d, 0x36e4ee76, 0xd15c29a7, 0x3e6071e0, 0x3e2b0c1d, 0x54444d19, 0x62699c34, 0xe9ffd47a, 0x1acf4cb1, 0x3617251a, 0x29a256a, 0x884c0e32, 0xcb883a85, 0xcf364770, 0xa5f2da4, 0x32166b1f, 0xda3deaf5, 0xb4fed79a, 0xa82ccab3, 0x471cc5f6, };
+const uint32_t exp_Rinv_p_33[] = { 0x6787f727, 0xc0dc79ce, 0x22066424, 0x4c6a2bf8, 0x5b81cb65, 0x169a350a, 0x47a07b05, 0x2a086619, 0xe5143481, 0xaddd2a07, 0xf3087ad4, 0xb7e7b5cd, 0xeff1c6f6, 0xa35ab988, 0x3cb3c643, 0xd53b3480, 0xcda6a846, 0xd51c411a, 0x840fea4, 0x2b55e639, 0x680557e2, 0x46c77daf, 0x1d110ae6, 0x9cf0f62b, 0x51257507, 0x63d1c63e, 0xdaccc4cf, 0xe3af579d, 0xe58ed7b0, 0x6950d5aa, 0x21471db1, 0x4ca3e886, };
+const uint32_t exp_Z_p_33[] = { 0xe0fc973d, 0xf77f5348, 0x3a34dcb9, 0x7c323908, 0xd6c67c28, 0x2844e745, 0x51819313, 0x5495d3fc, 0x5a52558f, 0x7b6f5c96, 0x1d74077e, 0xb987d7b1, 0xe2b04598, 0xe81a5a33, 0xfa3ec8e3, 0x4c28e076, 0x49e971eb, 0xfc954377, 0x81edfd23, 0xf59a8dd4, 0x9186e5e4, 0xf3136a00, 0x9cdba411, 0x1ca4bb10, 0x8a32ca07, 0xf17b5b75, 0x24083905, 0xcbaefcb, 0x284ae12, 0Xc030e665, 0X24600e91, 0X631b2a91 };
+
+const uint32_t* exp_test_cases_M_p[EXP_TEST_CASES_NUM] = {
+    exp_M_p_1, exp_M_p_2, exp_M_p_3, exp_M_p_4, exp_M_p_5, exp_M_p_6, exp_M_p_7, exp_M_p_8, exp_M_p_9, exp_M_p_10, exp_M_p_11, exp_M_p_12, exp_M_p_13, exp_M_p_14, exp_M_p_15, exp_M_p_16, exp_M_p_17, exp_M_p_18, exp_M_p_19, exp_M_p_20, exp_M_p_21, exp_M_p_22, exp_M_p_23, exp_M_p_24, exp_M_p_25, exp_M_p_26, exp_M_p_27, exp_M_p_28, exp_M_p_29, exp_M_p_30, exp_M_p_31, exp_M_p_32, exp_M_p_33,
+};
+
+const uint32_t* exp_test_cases_X_p[EXP_TEST_CASES_NUM] = {
+    exp_X_p_1, exp_X_p_2, exp_X_p_3, exp_X_p_4, exp_X_p_5, exp_X_p_6, exp_X_p_7, exp_X_p_8, exp_X_p_9, exp_X_p_10, exp_X_p_11, exp_X_p_12, exp_X_p_13, exp_X_p_14, exp_X_p_15, exp_X_p_16, exp_X_p_17, exp_X_p_18, exp_X_p_19, exp_X_p_20, exp_X_p_21, exp_X_p_22, exp_X_p_23, exp_X_p_24, exp_X_p_25, exp_X_p_26, exp_X_p_27, exp_X_p_28, exp_X_p_29, exp_X_p_30, exp_X_p_31, exp_X_p_32, exp_X_p_33,
+};
+
+const uint32_t* exp_test_cases_Y_p[EXP_TEST_CASES_NUM] = {
+    exp_Y_p_1, exp_Y_p_2, exp_Y_p_3, exp_Y_p_4, exp_Y_p_5, exp_Y_p_6, exp_Y_p_7, exp_Y_p_8, exp_Y_p_9, exp_Y_p_10, exp_Y_p_11, exp_Y_p_12, exp_Y_p_13, exp_Y_p_14, exp_Y_p_15, exp_Y_p_16, exp_Y_p_17, exp_Y_p_18, exp_Y_p_19, exp_Y_p_20, exp_Y_p_21, exp_Y_p_22, exp_Y_p_23, exp_Y_p_24, exp_Y_p_25, exp_Y_p_26, exp_Y_p_27, exp_Y_p_28, exp_Y_p_29, exp_Y_p_30, exp_Y_p_31, exp_Y_p_32, exp_Y_p_33,
+};
+
+const uint32_t* exp_test_cases_Rinv_p[EXP_TEST_CASES_NUM] = {
+    exp_Rinv_p_1, exp_Rinv_p_2, exp_Rinv_p_3, exp_Rinv_p_4, exp_Rinv_p_5, exp_Rinv_p_6, exp_Rinv_p_7, exp_Rinv_p_8, exp_Rinv_p_9, exp_Rinv_p_10, exp_Rinv_p_11, exp_Rinv_p_12, exp_Rinv_p_13, exp_Rinv_p_14, exp_Rinv_p_15, exp_Rinv_p_16, exp_Rinv_p_17, exp_Rinv_p_18, exp_Rinv_p_19, exp_Rinv_p_20, exp_Rinv_p_21, exp_Rinv_p_22, exp_Rinv_p_23, exp_Rinv_p_24, exp_Rinv_p_25, exp_Rinv_p_26, exp_Rinv_p_27, exp_Rinv_p_28, exp_Rinv_p_29, exp_Rinv_p_30, exp_Rinv_p_31, exp_Rinv_p_32, exp_Rinv_p_33,
+};
+
+const uint32_t* exp_test_cases_Z_p[EXP_TEST_CASES_NUM] = {
+    exp_Z_p_1, exp_Z_p_2, exp_Z_p_3, exp_Z_p_4, exp_Z_p_5, exp_Z_p_6, exp_Z_p_7, exp_Z_p_8, exp_Z_p_9, exp_Z_p_10, exp_Z_p_11, exp_Z_p_12, exp_Z_p_13, exp_Z_p_14, exp_Z_p_15, exp_Z_p_16, exp_Z_p_17, exp_Z_p_18, exp_Z_p_19, exp_Z_p_20, exp_Z_p_21, exp_Z_p_22, exp_Z_p_23, exp_Z_p_24, exp_Z_p_25, exp_Z_p_26, exp_Z_p_27, exp_Z_p_28, exp_Z_p_29, exp_Z_p_30, exp_Z_p_31, exp_Z_p_32, exp_Z_p_33,
+};
+
+const uint32_t exp_test_cases_Mprime[EXP_TEST_CASES_NUM] = {
+    0x1, 0x10000001, 0x1, 0x55555555, 0x5050505, 0x5005005, 0x50005, 0x5050505, 0xb90226b9, 0x5e75bb8d, 0x1, 0x1, 0x100001, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0xc71c71c7, 0x49249249, 0x49249249, 0x55555555, 0x60a2c147, 0x60a2c147, 0x60a2c147, 0x49249249, 0x2b458645, 0x2b458645, 0x2b458645,
+};
+
+size_t exp_test_cases_M_n[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_X_n[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 32,
+};
+
+size_t exp_test_cases_Y_n[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_Rinv_n[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_Z_n[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_num_words[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_m_words[EXP_TEST_CASES_NUM] = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 32, 32, 32,
+};
+
+size_t exp_test_cases_y_bits[EXP_TEST_CASES_NUM] = {
+    2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 9, 1, 1, 2, 0, 2, 0, 2, 0, 3, 1, 1, 0, 3, 3, 3, 33, 33, 33, 10, 1023, 1022, 1023,
+};

+ 16 - 0
components/hal/test_apps/mpi/pytest_mpi.py

@@ -0,0 +1,16 @@
+# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.esp32s2
+@pytest.mark.esp32s3
+@pytest.mark.esp32c3
+@pytest.mark.esp32c6
+@pytest.mark.esp32h2
+@pytest.mark.generic
+def test_bignum(dut: Dut) -> None:
+    dut.run_all_single_board_cases()

+ 2 - 0
components/hal/test_apps/mpi/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_ESP_TASK_WDT_EN=y
+CONFIG_ESP_TASK_WDT_INIT=n

+ 2 - 3
components/mbedtls/CMakeLists.txt

@@ -220,9 +220,8 @@ endif()
 # The other port-specific files don't override internal mbedTLS functions, they just add new functions.
 
 if(CONFIG_MBEDTLS_HARDWARE_MPI)
-    target_sources(mbedcrypto PRIVATE  "${COMPONENT_DIR}/port/esp_bignum.c"
-                                       "${COMPONENT_DIR}/port/${idf_target}/bignum.c"
-    )
+    target_sources(mbedcrypto PRIVATE  "${COMPONENT_DIR}/port/bignum/esp_bignum.c"
+                                       "${COMPONENT_DIR}/port/bignum/bignum_alt.c")
 endif()
 
 if(CONFIG_MBEDTLS_HARDWARE_SHA)

+ 227 - 0
components/mbedtls/port/bignum/bignum_alt.c

@@ -0,0 +1,227 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "esp_crypto_lock.h"
+#include "esp_private/periph_ctrl.h"
+#include "bignum_impl.h"
+#include "mbedtls/bignum.h"
+
+#include "hal/mpi_hal.h"
+
+
+void esp_mpi_enable_hardware_hw_op( void )
+{
+    esp_crypto_mpi_lock_acquire();
+
+    /* Enable RSA hardware */
+    periph_module_enable(PERIPH_RSA_MODULE);
+
+    mpi_hal_enable_hardware_hw_op();
+}
+
+
+void esp_mpi_disable_hardware_hw_op( void )
+{
+    mpi_hal_disable_hardware_hw_op();
+
+    /* Disable RSA hardware */
+    periph_module_disable(PERIPH_RSA_MODULE);
+
+    esp_crypto_mpi_lock_release();
+}
+
+size_t esp_mpi_hardware_words(size_t words)
+{
+    return mpi_hal_calc_hardware_words(words);
+}
+
+
+void esp_mpi_interrupt_enable(bool enable)
+{
+    mpi_hal_interrupt_enable(enable);
+}
+
+
+void esp_mpi_interrupt_clear(void)
+{
+    mpi_hal_clear_interrupt();
+}
+
+
+/* Z = (X * Y) mod M */
+void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
+{
+#if CONFIG_IDF_TARGET_ESP32
+    /* "mode" register loaded with number of 512-bit blocks, minus 1 */
+    mpi_hal_set_mode((num_words / 16) - 1);
+#else
+    mpi_hal_set_mode(num_words - 1);
+#endif
+
+    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
+    mpi_hal_write_to_mem_block(MPI_PARAM_M, 0, M->MBEDTLS_PRIVATE(p), M->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, X->MBEDTLS_PRIVATE(p), X->MBEDTLS_PRIVATE(n), num_words);
+
+#if !CONFIG_IDF_TARGET_ESP32
+    mpi_hal_write_to_mem_block(MPI_PARAM_Y, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+#endif
+
+    mpi_hal_write_to_mem_block(MPI_PARAM_Z, 0, Rinv->MBEDTLS_PRIVATE(p), Rinv->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_m_prime(Mprime);
+
+#if CONFIG_IDF_TARGET_ESP32
+    mpi_hal_start_op(MPI_MULT);
+    mpi_hal_wait_op_complete();
+    /* execute second stage */
+    /* Load Y to X input memory block, rerun */
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_start_op(MPI_MULT);
+#else
+    mpi_hal_start_op(MPI_MODMULT);
+#endif
+
+}
+
+
+/* Z = X * Y */
+void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
+{
+    /* Copy X (right-extended) & Y (left-extended) to memory block */
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, X->MBEDTLS_PRIVATE(p), X->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_Z, num_words * 4, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+    /* NB: as Y is left-exte, we don't zero the bottom words_mult words of Y block.
+       This is OK for now bec zeroing is done by hardware when we do esp_mpi_acquire_hardware().
+    */
+#if CONFIG_IDF_TARGET_ESP32
+    mpi_hal_write_m_prime(0);
+    /* "mode" register loaded with number of 512-bit blocks in result,
+       plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8))
+    */
+    mpi_hal_set_mode(((num_words * 2) / 16) + 7);
+#else
+    mpi_hal_set_mode(num_words * 2 - 1);
+#endif
+
+    mpi_hal_start_op(MPI_MULT);
+}
+
+
+/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod
+   multiplication to calculate an mbedtls_mpi_mult_mpi result where either
+   A or B are >2048 bits so can't use the standard multiplication method.
+
+   Result (number of words, based on A bits + B bits) must still be less than 4096 bits.
+
+   This case is simpler than the general case modulo multiply of
+   esp_mpi_mul_mpi_mod() because we can control the other arguments:
+
+   * Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output
+   * Mprime and Rinv are therefore predictable as follows:
+   isn't actually modulo anything.
+   Mprime 1
+   Rinv 1
+
+   (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
+*/
+
+void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
+{
+     /* M = 2^num_words - 1, so block is entirely FF */
+    for (int i = 0; i < num_words; i++) {
+        mpi_hal_write_at_offset(MPI_PARAM_M, i * 4, UINT32_MAX);
+    }
+
+    /* Mprime = 1 */
+    mpi_hal_write_m_prime(1);
+
+#if CONFIG_IDF_TARGET_ESP32
+    /* "mode" register loaded with number of 512-bit blocks, minus 1 */
+    mpi_hal_set_mode((num_words / 16) - 1);
+#else
+    mpi_hal_set_mode(num_words - 1);
+#endif
+
+    /* Load X & Y */
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, X->MBEDTLS_PRIVATE(p), X->MBEDTLS_PRIVATE(n), num_words);
+#if !CONFIG_IDF_TARGET_ESP32
+    mpi_hal_write_to_mem_block(MPI_PARAM_Y, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+#endif
+    /* Rinv = 1, write first word */
+    mpi_hal_write_rinv(1);
+
+    /* Zero out rest of the Rinv words */
+    for (int i = 1; i < num_words; i++) {
+        mpi_hal_write_at_offset(MPI_PARAM_Z, i * 4, 0);
+    }
+
+#if CONFIG_IDF_TARGET_ESP32
+    mpi_hal_start_op(MPI_MULT);
+    mpi_hal_wait_op_complete();
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_start_op(MPI_MULT);
+#else
+    mpi_hal_start_op(MPI_MODMULT);
+#endif
+}
+
+#ifdef ESP_MPI_USE_MONT_EXP
+int esp_mont_hw_op(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, mbedtls_mpi_uint Mprime, size_t hw_words, bool again)
+{
+    // Note Z may be the same pointer as X or Y
+    int ret = 0;
+
+    // montgomery mult prepare
+    if (again == false) {
+        mpi_hal_write_to_mem_block(MPI_PARAM_M, 0, M->MBEDTLS_PRIVATE(p), M->MBEDTLS_PRIVATE(n), hw_words);
+        mpi_hal_write_m_prime(Mprime);
+        mpi_hal_set_mode((hw_words / 16) - 1);
+    }
+
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, X->MBEDTLS_PRIVATE(p), X->MBEDTLS_PRIVATE(n), hw_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_Z, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), hw_words);
+
+    mpi_hal_start_op(MPI_MULT);
+
+    Z->MBEDTLS_PRIVATE(s) = 1; // The sign of Z will be = M->s (but M->s is always 1)
+    MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, hw_words) );
+
+    /* Read back the result */
+    mpi_hal_read_result_hw_op(Z->MBEDTLS_PRIVATE(p), Z->MBEDTLS_PRIVATE(n), hw_words);
+
+    /* from HAC 14.36 - 3. If Z >= M then Z = Z - M */
+    if (mbedtls_mpi_cmp_mpi(Z, M) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Z, Z, M));
+    }
+cleanup:
+    return ret;
+}
+
+#else
+/* Z = (X ^ Y) mod M
+*/
+void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
+{
+    size_t y_bits = mbedtls_mpi_bitlen(Y);
+    mpi_hal_set_mode(num_words - 1);
+
+    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
+    mpi_hal_write_to_mem_block(MPI_PARAM_X, 0, X->MBEDTLS_PRIVATE(p), X->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_Y, 0, Y->MBEDTLS_PRIVATE(p), Y->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_M, 0, M->MBEDTLS_PRIVATE(p), M->MBEDTLS_PRIVATE(n), num_words);
+    mpi_hal_write_to_mem_block(MPI_PARAM_Z, 0, Rinv->MBEDTLS_PRIVATE(p), Rinv->MBEDTLS_PRIVATE(n), num_words);
+
+    mpi_hal_write_m_prime(Mprime);
+
+    /* Enable acceleration options */
+    mpi_hal_enable_constant_time(false);
+    mpi_hal_enable_search(true);
+    mpi_hal_set_search_position(y_bits - 1);
+
+    /* Execute first stage montgomery multiplication */
+    mpi_hal_start_op(MPI_MODEXP);
+
+    mpi_hal_enable_search(false);
+}
+#endif //ESP_MPI_USE_MONT_EXP

+ 26 - 37
components/mbedtls/port/esp_bignum.c → components/mbedtls/port/bignum/esp_bignum.c

@@ -6,7 +6,7 @@
  *
  * SPDX-License-Identifier: Apache-2.0
  *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
  */
 #include <stdio.h>
 #include <string.h>
@@ -24,17 +24,16 @@
 #include "esp_pm.h"
 #endif
 
+#include "esp_private/periph_ctrl.h"
+
 #include "freertos/FreeRTOS.h"
 #include "freertos/semphr.h"
 
-#include "soc/hwcrypto_periph.h"
-#include "soc/periph_defs.h"
-#include "soc/soc_caps.h"
-
 #include "bignum_impl.h"
 
-#include <mbedtls/bignum.h>
+#include "mbedtls/bignum.h"
 
+#include "hal/mpi_hal.h"
 
 /* Some implementation notes:
  *
@@ -65,7 +64,7 @@ static esp_pm_lock_handle_t s_pm_sleep_lock;
 static IRAM_ATTR void esp_mpi_complete_isr(void *arg)
 {
     BaseType_t higher_woken;
-    esp_mpi_interrupt_clear();
+    mpi_hal_clear_interrupt();
 
     xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
     if (higher_woken) {
@@ -76,8 +75,8 @@ static IRAM_ATTR void esp_mpi_complete_isr(void *arg)
 
 static esp_err_t esp_mpi_isr_initialise(void)
 {
-    esp_mpi_interrupt_clear();
-    esp_mpi_interrupt_enable(true);
+    mpi_hal_clear_interrupt();
+    mpi_hal_interrupt_enable(true);
     if (op_complete_sem == NULL) {
         op_complete_sem = xSemaphoreCreateBinary();
 
@@ -120,7 +119,7 @@ static int esp_mpi_wait_intr(void)
     esp_pm_lock_release(s_pm_sleep_lock);
 #endif  // CONFIG_PM_ENABLE
 
-    esp_mpi_interrupt_enable(false);
+    mpi_hal_interrupt_enable(false);
 
     return 0;
 }
@@ -208,8 +207,6 @@ cleanup:
 
 
 
-
-
 /* Z = (X * Y) mod M
 
    Not an mbedTLS function
@@ -226,7 +223,7 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
     size_t y_words = bits_to_words(y_bits);
     size_t m_words = bits_to_words(m_bits);
     size_t z_words = bits_to_words(z_bits);
-    size_t hw_words = esp_mpi_hardware_words(MAX(x_words, MAX(y_words, m_words))); /* longest operand */
+    size_t hw_words = mpi_hal_calc_hardware_words(MAX(x_words, MAX(y_words, m_words))); /* longest operand */
     mbedtls_mpi Rinv;
     mbedtls_mpi_uint Mprime;
 
@@ -241,7 +238,8 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
 
     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Z, z_words));
 
-    esp_mpi_read_result_hw_op(Z, z_words);
+    /* Read back the result */
+    mpi_hal_read_result_hw_op(Z->MBEDTLS_PRIVATE(p), Z->MBEDTLS_PRIVATE(n), z_words);
     Z->MBEDTLS_PRIVATE(s) = X->MBEDTLS_PRIVATE(s) * Y->MBEDTLS_PRIVATE(s);
 
 cleanup:
@@ -274,6 +272,7 @@ static size_t mbedtls_mpi_msb( const mbedtls_mpi *X )
     return 0;
 }
 
+
 /*
  * Montgomery exponentiation: Z = X ^ Y mod M  (HAC 14.94)
  */
@@ -335,6 +334,7 @@ cleanup2:
 
 #endif //USE_MONT_EXPONENATIATION
 
+
 /*
  * Z = X ^ Y mod M
  *
@@ -358,7 +358,7 @@ static int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_
     /* "all numbers must be the same length", so choose longest number
        as cardinal length of operation...
     */
-    size_t num_words = esp_mpi_hardware_words(MAX(m_words, MAX(x_words, y_words)));
+    size_t num_words = mpi_hal_calc_hardware_words(MAX(m_words, MAX(x_words, y_words)));
 
     if (num_words * 32 > SOC_RSA_MAX_BIT_LEN) {
         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
@@ -420,7 +420,9 @@ static int esp_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_
     }
 #endif //CONFIG_MBEDTLS_MPI_USE_INTERRUPT
 
-    esp_mpi_read_result_hw_op(Z, m_words);
+    /* Read back the result */
+    mpi_hal_read_result_hw_op(Z->MBEDTLS_PRIVATE(p), Z->MBEDTLS_PRIVATE(n), m_words);
+
     esp_mpi_disable_hardware_hw_op();
 #endif
 
@@ -479,7 +481,7 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
     size_t x_words = bits_to_words(x_bits);
     size_t y_words = bits_to_words(y_bits);
     size_t z_words = bits_to_words(x_bits + y_bits);
-    size_t hw_words = esp_mpi_hardware_words(MAX(x_words, y_words)); // length of one operand in hardware
+    size_t hw_words = mpi_hal_calc_hardware_words(MAX(x_words, y_words)); // length of one operand in hardware
 
     /* Short-circuit eval if either argument is 0 or 1.
 
@@ -534,7 +536,9 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
     esp_mpi_enable_hardware_hw_op();
 
     esp_mpi_mul_mpi_hw_op(X, Y, hw_words);
-    esp_mpi_read_result_hw_op(Z, z_words);
+
+    /* Read back the result */
+    mpi_hal_read_result_hw_op(Z->MBEDTLS_PRIVATE(p), Z->MBEDTLS_PRIVATE(n), z_words);
 
     esp_mpi_disable_hardware_hw_op();
 
@@ -612,34 +616,19 @@ cleanup:
     return ret;
 }
 
-/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod
-   multiplication to calculate an mbedtls_mpi_mult_mpi result where either
-   A or B are >2048 bits so can't use the standard multiplication method.
-
-   Result (number of words, based on A bits + B bits) must still be less than 4096 bits.
-
-   This case is simpler than the general case modulo multiply of
-   esp_mpi_mul_mpi_mod() because we can control the other arguments:
-
-   * Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output
-   * Mprime and Rinv are therefore predictable as follows:
-   isn't actually modulo anything.
-   Mprime 1
-   Rinv 1
-
-   (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
-*/
 
 static int mpi_mult_mpi_failover_mod_mult( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words)
 {
     int ret;
-    size_t hw_words = esp_mpi_hardware_words(z_words);
+    size_t hw_words = mpi_hal_calc_hardware_words(z_words);
 
     esp_mpi_enable_hardware_hw_op();
 
     esp_mpi_mult_mpi_failover_mod_mult_hw_op(X, Y, hw_words );
     MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, hw_words) );
-    esp_mpi_read_result_hw_op(Z, hw_words);
+
+    /* Read back the result */
+    mpi_hal_read_result_hw_op(Z->MBEDTLS_PRIVATE(p), Z->MBEDTLS_PRIVATE(n), hw_words);
 
     Z->MBEDTLS_PRIVATE(s) = X->MBEDTLS_PRIVATE(s) * Y->MBEDTLS_PRIVATE(s);
     /*

+ 0 - 296
components/mbedtls/port/esp32/bignum.c

@@ -1,296 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
- */
-#include "soc/hwcrypto_periph.h"
-#include "soc/dport_reg.h"
-#include "esp_private/periph_ctrl.h"
-#include <mbedtls/bignum.h>
-#include "bignum_impl.h"
-#include <sys/param.h>
-#include <sys/lock.h>
-
-static _lock_t mpi_lock;
-
-/* Round up number of words to nearest
-   512 bit (16 word) block count.
-*/
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return (words + 0xF) & ~0xF;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    /* newlib locks lazy initialize on ESP-IDF */
-    _lock_acquire(&mpi_lock);
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-    DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
-
-    while (DPORT_REG_READ(RSA_CLEAN_REG) != 1)
-    { }
-    // Note: from enabling RSA clock to here takes about 1.3us
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    _lock_release(&mpi_lock);
-}
-
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    DPORT_REG_WRITE(RSA_INTERRUPT_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If hw_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-
-*/
-
-/* Please see detailed note inside the function body below.
- * Relevant: IDF-6029
-             https://github.com/espressif/esp-idf/issues/8710
-             https://github.com/espressif/esp-idf/issues/10403
- */
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t hw_words)
-{
-    uint32_t copy_words = MIN(hw_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (uint32_t i = 0; i < copy_words; i++) {
-        DPORT_REG_WRITE(mem_base + i * 4, mpi->MBEDTLS_PRIVATE(p[i]));
-    }
-
-    /* Zero any remaining memory block data */
-    for (uint32_t i = copy_words; i < hw_words; i++) {
-        DPORT_REG_WRITE(mem_base + i * 4, 0);
-    }
-
-#if _INTERNAL_DEBUG_PURPOSE
-    /*
-     * With Xtensa GCC 11.2.0 (from ESP-IDF v5.x), it was observed that above zero initialization
-     * loop gets optimized to `memset` call from the ROM library. This was causing an issue that
-     * specific write (store) operation to the MPI peripheral block was getting lost erroneously.
-     * Following data re-verify loop could catch it during runtime.
-     *
-     * As a workaround, we are using DPORT_WRITE_REG (volatile writes) wrappers to write to
-     * the MPI peripheral.
-     *
-     */
-
-    //for (uint32_t i = copy_words; i < hw_words; i++) { assert(pbase[i] == 0); }
-#endif
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-
-   Bignum 'x' should already be grown to at least num_words by caller (can be done while
-   calculation is in progress, to save some cycles)
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, size_t num_words)
-{
-    assert(x->MBEDTLS_PRIVATE(n) >= num_words);
-
-    /* Copy data from memory block registers */
-    esp_dport_access_read_buffer(x->MBEDTLS_PRIVATE(p), mem_base, num_words);
-
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p[i]) = 0;
-    }
-}
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    DPORT_REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (DPORT_REG_READ(RSA_INTERRUPT_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
-}
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
-}
-
-/* Z = (X * Y) mod M */
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t hw_words)
-{
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words);
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, hw_words);
-    DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime);
-
-    /* "mode" register loaded with number of 512-bit blocks, minus 1 */
-    DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_MULT_START_REG);
-
-    wait_op_complete();
-
-    /* execute second stage */
-    /* Load Y to X input memory block, rerun */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, hw_words);
-
-    start_op(RSA_MULT_START_REG);
-}
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t hw_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
-    mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + hw_words * 4, Y, hw_words);
-    /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
-       This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-
-    DPORT_REG_WRITE(RSA_M_DASH_REG, 0);
-
-    /* "mode" register loaded with number of 512-bit blocks in result,
-       plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8))
-    */
-    DPORT_REG_WRITE(RSA_MULT_MODE_REG, ((hw_words * 2) / 16) + 7);
-
-    start_op(RSA_MULT_START_REG);
-
-}
-
-
-int esp_mont_hw_op(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M,
-                   mbedtls_mpi_uint Mprime,
-                   size_t hw_words,
-                   bool again)
-{
-    // Note Z may be the same pointer as X or Y
-    int ret = 0;
-
-    // montgomery mult prepare
-    if (again == false) {
-        mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, hw_words);
-        DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
-        DPORT_REG_WRITE(RSA_MULT_MODE_REG, hw_words / 16 - 1);
-    }
-
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Y, hw_words);
-
-    start_op(RSA_MULT_START_REG);
-    Z->MBEDTLS_PRIVATE(s) = 1; // The sign of Z will be = M->s (but M->s is always 1)
-    MBEDTLS_MPI_CHK( mbedtls_mpi_grow(Z, hw_words) );
-
-    wait_op_complete();
-
-    /* Read back the result */
-    mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, hw_words);
-
-
-    /* from HAC 14.36 - 3. If Z >= M then Z = Z - M */
-    if (mbedtls_mpi_cmp_mpi(Z, M) >= 0) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Z, Z, M));
-    }
-cleanup:
-    return ret;
-}
-
-
-
-/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod
-   multiplication to calculate an mbedtls_mpi_mult_mpi result where either
-   A or B are >2048 bits so can't use the standard multiplication method.
-
-   Result (z_words, based on A bits + B bits) must still be less than 4096 bits.
-
-   This case is simpler than the general case modulo multiply of
-   esp_mpi_mul_mpi_mod() because we can control the other arguments:
-
-   * Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output
-   isn't actually modulo anything.
-   * Mprime and Rinv are therefore predictable as follows:
-   Mprime = 1
-   Rinv = 1
-
-   (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
-*/
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    size_t hw_words = num_words;
-
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (size_t i = 0; i < hw_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
-    }
-    /* Mprime = 1 */
-    DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
-
-    /* "mode" register loaded with number of 512-bit blocks, minus 1 */
-    DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hw_words / 16) - 1);
-
-    /* Load X */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, hw_words);
-
-    /* Rinv = 1, write first word */
-    DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
-
-    /* Zero out rest of the Rinv words */
-    for (size_t i = 1; i < hw_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
-    }
-
-    start_op(RSA_MULT_START_REG);
-
-    wait_op_complete();
-
-    /* finish the modular multiplication */
-    /* Load Y to X input memory block, rerun */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, hw_words);
-
-    start_op(RSA_MULT_START_REG);
-
-}

+ 0 - 229
components/mbedtls/port/esp32c3/bignum.c

@@ -1,229 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 C3 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
- */
-#include <string.h>
-#include <sys/param.h>
-#include "soc/hwcrypto_periph.h"
-#include "esp_private/periph_ctrl.h"
-#include "mbedtls/bignum.h"
-#include "bignum_impl.h"
-#include "soc/system_reg.h"
-#include "soc/periph_defs.h"
-#include "esp_crypto_lock.h"
-
-
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return words;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    esp_crypto_mpi_lock_acquire();
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-
-    REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
-
-    while (REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
-    }
-    // Note: from enabling RSA clock to here takes about 1.3us
-
-    REG_WRITE(RSA_INTERRUPT_REG, 0);
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    esp_crypto_mpi_lock_release();
-}
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    REG_WRITE(RSA_INTERRUPT_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If num_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-*/
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
-{
-    uint32_t *pbase = (uint32_t *)mem_base;
-    uint32_t copy_words = MIN(num_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (int i = 0; i < copy_words; i++) {
-        pbase[i] = mpi->MBEDTLS_PRIVATE(p)[i];
-    }
-
-    /* Zero any remaining memory block data */
-    for (int i = copy_words; i < num_words; i++) {
-        pbase[i] = 0;
-    }
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
-{
-
-    /* Copy data from memory block registers */
-    const size_t REG_WIDTH = sizeof(uint32_t);
-    for (size_t i = 0; i < num_words; i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = REG_READ(mem_base + (i * REG_WIDTH));
-    }
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = 0;
-    }
-}
-
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (REG_READ(RSA_QUERY_INTERRUPT_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
-}
-
-
-/* Z = (X * Y) mod M
-
-   Not an mbedTLS function
-*/
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    start_op(RSA_MOD_MULT_START_REG);
-}
-
-/* Z = (X ^ Y) mod M
-*/
-void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    size_t y_bits = mbedtls_mpi_bitlen(Y);
-
-    REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    /* Enable acceleration options */
-    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
-    REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_MODEXP_START_REG);
-
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
-}
-
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + num_words * 4, Y, num_words);
-    /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
-       This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-    REG_WRITE(RSA_LENGTH_REG, (num_words * 2 - 1));
-    start_op(RSA_MULT_START_REG);
-}
-
-
-
-/**
- * @brief Special-case of (X * Y), where we use hardware montgomery mod
-   multiplication to calculate result where either A or B are >2048 bits so
-   can't use the standard multiplication method.
- *
- */
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (int i = 0; i < num_words; i++) {
-        REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
-    }
-
-    /* Mprime = 1 */
-    REG_WRITE(RSA_M_DASH_REG, 1);
-    REG_WRITE(RSA_LENGTH_REG, num_words - 1);
-
-    /* Load X & Y */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-
-    /* Rinv = 1, write first word */
-    REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
-
-    /* Zero out rest of the Rinv words */
-    for (int i = 1; i < num_words; i++) {
-        REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
-    }
-
-    start_op(RSA_MOD_MULT_START_REG);
-}

+ 0 - 230
components/mbedtls/port/esp32c6/bignum.c

@@ -1,230 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 C6 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
- */
-#include <string.h>
-#include <sys/param.h>
-#include "soc/hwcrypto_periph.h"
-#include "esp_private/periph_ctrl.h"
-#include "mbedtls/bignum.h"
-#include "bignum_impl.h"
-#include "soc/pcr_reg.h"
-#include "soc/periph_defs.h"
-#include "soc/system_reg.h"
-#include "esp_crypto_lock.h"
-
-
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return words;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    esp_crypto_mpi_lock_acquire();
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-
-    REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
-
-    while (REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
-    }
-    // Note: from enabling RSA clock to here takes about 1.3us
-
-    REG_WRITE(RSA_INT_ENA_REG, 0);
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    esp_crypto_mpi_lock_release();
-}
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    REG_WRITE(RSA_INT_ENA_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If num_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-*/
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
-{
-    uint32_t *pbase = (uint32_t *)mem_base;
-    uint32_t copy_words = MIN(num_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (int i = 0; i < copy_words; i++) {
-        pbase[i] = mpi->MBEDTLS_PRIVATE(p)[i];
-    }
-
-    /* Zero any remaining memory block data */
-    for (int i = copy_words; i < num_words; i++) {
-        pbase[i] = 0;
-    }
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
-{
-
-    /* Copy data from memory block registers */
-    const size_t REG_WIDTH = sizeof(uint32_t);
-    for (size_t i = 0; i < num_words; i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = REG_READ(mem_base + (i * REG_WIDTH));
-    }
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = 0;
-    }
-}
-
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (REG_READ(RSA_QUERY_IDLE_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-}
-
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_Z_MEM, z_words);
-}
-
-
-/* Z = (X * Y) mod M
-
-   Not an mbedTLS function
-*/
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    REG_WRITE(RSA_MODE_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_X_MEM, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM, Y, num_words);
-    mpi_to_mem_block(RSA_M_MEM, M, num_words);
-    mpi_to_mem_block(RSA_Z_MEM, Rinv, num_words);
-    REG_WRITE(RSA_M_PRIME_REG, Mprime);
-
-    start_op(RSA_SET_START_MODMULT_REG);
-}
-
-/* Z = (X ^ Y) mod M
-*/
-void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    size_t y_bits = mbedtls_mpi_bitlen(Y);
-
-    REG_WRITE(RSA_MODE_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_X_MEM, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM, Y, num_words);
-    mpi_to_mem_block(RSA_M_MEM, M, num_words);
-    mpi_to_mem_block(RSA_Z_MEM, Rinv, num_words);
-    REG_WRITE(RSA_M_PRIME_REG, Mprime);
-
-    /* Enable acceleration options */
-    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
-    REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_SET_START_MODEXP_REG);
-
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
-}
-
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_X_MEM, X, num_words);
-    mpi_to_mem_block(RSA_Z_MEM + num_words * 4, Y, num_words);
-    /* NB: as Y is left-exte, we don't zero the bottom words_mult words of Y block.
-       This is OK for now bec zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-    REG_WRITE(RSA_MODE_REG, (num_words * 2 - 1));
-    start_op(RSA_SET_START_MULT_REG);
-}
-
-
-
-/**
- * @brief Special-case of (X * Y), where we use hardware montgomery mod
-   multiplication to calculate result where either A or B are >2048 bits so
-   can't use the standard multiplication method.
- *
- */
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (int i = 0; i < num_words; i++) {
-        REG_WRITE(RSA_M_MEM + i * 4, UINT32_MAX);
-    }
-
-    /* Mprime = 1 */
-    REG_WRITE(RSA_M_PRIME_REG, 1);
-    REG_WRITE(RSA_MODE_REG, num_words - 1);
-
-    /* Load X & Y */
-    mpi_to_mem_block(RSA_X_MEM, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM, Y, num_words);
-
-    /* Rinv = 1, write first word */
-    REG_WRITE(RSA_Z_MEM, 1);
-
-    /* Zero out rest of the Rinv words */
-    for (int i = 1; i < num_words; i++) {
-        REG_WRITE(RSA_Z_MEM + i * 4, 0);
-    }
-
-    start_op(RSA_SET_START_MODMULT_REG);
-}

+ 0 - 230
components/mbedtls/port/esp32h2/bignum.c

@@ -1,230 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 H2 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
- */
-#include <string.h>
-#include <sys/param.h>
-#include "soc/hwcrypto_periph.h"
-#include "esp_private/periph_ctrl.h"
-#include "mbedtls/bignum.h"
-#include "bignum_impl.h"
-#include "soc/pcr_reg.h"
-#include "soc/periph_defs.h"
-#include "soc/system_reg.h"
-#include "esp_crypto_lock.h"
-
-
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return words;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    esp_crypto_mpi_lock_acquire();
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-
-    REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
-
-    while (REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
-    }
-    // Note: from enabling RSA clock to here takes about 1.3us
-
-    REG_WRITE(RSA_INT_ENA_REG, 0);
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    esp_crypto_mpi_lock_release();
-}
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    REG_WRITE(RSA_INT_ENA_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If num_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-*/
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
-{
-    uint32_t *pbase = (uint32_t *)mem_base;
-    uint32_t copy_words = MIN(num_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (int i = 0; i < copy_words; i++) {
-        pbase[i] = mpi->MBEDTLS_PRIVATE(p)[i];
-    }
-
-    /* Zero any remaining memory block data */
-    for (int i = copy_words; i < num_words; i++) {
-        pbase[i] = 0;
-    }
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
-{
-
-    /* Copy data from memory block registers */
-    const size_t REG_WIDTH = sizeof(uint32_t);
-    for (size_t i = 0; i < num_words; i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = REG_READ(mem_base + (i * REG_WIDTH));
-    }
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = 0;
-    }
-}
-
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (REG_READ(RSA_QUERY_IDLE_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    REG_WRITE(RSA_INT_CLR_REG, 1);
-}
-
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_Z_MEM_REG, z_words);
-}
-
-
-/* Z = (X * Y) mod M
-
-   Not an mbedTLS function
-*/
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    REG_WRITE(RSA_MODE_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_X_MEM_REG, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM_REG, Y, num_words);
-    mpi_to_mem_block(RSA_M_MEM_REG, M, num_words);
-    mpi_to_mem_block(RSA_Z_MEM_REG, Rinv, num_words);
-    REG_WRITE(RSA_M_PRIME_REG, Mprime);
-
-    start_op(RSA_SET_START_MODMULT_REG);
-}
-
-/* Z = (X ^ Y) mod M
-*/
-void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    size_t y_bits = mbedtls_mpi_bitlen(Y);
-
-    REG_WRITE(RSA_MODE_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_X_MEM_REG, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM_REG, Y, num_words);
-    mpi_to_mem_block(RSA_M_MEM_REG, M, num_words);
-    mpi_to_mem_block(RSA_Z_MEM_REG, Rinv, num_words);
-    REG_WRITE(RSA_M_PRIME_REG, Mprime);
-
-    /* Enable acceleration options */
-    REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
-    REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_SET_START_MODEXP_REG);
-
-    REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
-}
-
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_X_MEM_REG, X, num_words);
-    mpi_to_mem_block(RSA_Z_MEM_REG + num_words * 4, Y, num_words);
-    /* NB: as Y is left-exte, we don't zero the bottom words_mult words of Y block.
-       This is OK for now bec zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-    REG_WRITE(RSA_MODE_REG, (num_words * 2 - 1));
-    start_op(RSA_SET_START_MULT_REG);
-}
-
-
-
-/**
- * @brief Special-case of (X * Y), where we use hardware montgomery mod
-   multiplication to calculate result where either A or B are >2048 bits so
-   can't use the standard multiplication method.
- *
- */
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (int i = 0; i < num_words; i++) {
-        REG_WRITE(RSA_M_MEM_REG + i * 4, UINT32_MAX);
-    }
-
-    /* Mprime = 1 */
-    REG_WRITE(RSA_M_PRIME_REG, 1);
-    REG_WRITE(RSA_MODE_REG, num_words - 1);
-
-    /* Load X & Y */
-    mpi_to_mem_block(RSA_X_MEM_REG, X, num_words);
-    mpi_to_mem_block(RSA_Y_MEM_REG, Y, num_words);
-
-    /* Rinv = 1, write first word */
-    REG_WRITE(RSA_Z_MEM_REG, 1);
-
-    /* Zero out rest of the Rinv words */
-    for (int i = 1; i < num_words; i++) {
-        REG_WRITE(RSA_Z_MEM_REG + i * 4, 0);
-    }
-
-    start_op(RSA_SET_START_MODMULT_REG);
-}

+ 0 - 224
components/mbedtls/port/esp32s2/bignum.c

@@ -1,224 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 S2 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
- */
-#include "soc/hwcrypto_periph.h"
-#include "esp_private/periph_ctrl.h"
-#include <mbedtls/bignum.h>
-#include "bignum_impl.h"
-#include "soc/dport_reg.h"
-#include "soc/periph_defs.h"
-#include <sys/param.h>
-#include "esp_crypto_lock.h"
-
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return words;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    esp_crypto_mpi_lock_acquire();
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-
-    DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD);
-
-    while (DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
-    }
-    // Note: from enabling RSA clock to here takes about 1.3us
-
-    REG_WRITE(RSA_INTERRUPT_REG, 0);
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    esp_crypto_mpi_lock_release();
-}
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    REG_WRITE(RSA_INTERRUPT_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If num_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-*/
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
-{
-    uint32_t *pbase = (uint32_t *)mem_base;
-    uint32_t copy_words = MIN(num_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (uint32_t i = 0; i < copy_words; i++) {
-        pbase[i] = mpi->MBEDTLS_PRIVATE(p)[i];
-    }
-
-    /* Zero any remaining memory block data */
-    for (uint32_t i = copy_words; i < num_words; i++) {
-        pbase[i] = 0;
-    }
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
-{
-
-    /* Copy data from memory block registers */
-    esp_dport_access_read_buffer(x->MBEDTLS_PRIVATE(p), mem_base, num_words);
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = 0;
-    }
-}
-
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    DPORT_REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
-}
-
-
-/* Z = (X * Y) mod M
-
-   Not an mbedTLS function
-*/
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    start_op(RSA_MOD_MULT_START_REG);
-}
-
-/* Z = (X ^ Y) mod M
-*/
-void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    size_t y_bits = mbedtls_mpi_bitlen(Y);
-
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    /* Enable acceleration options */
-    DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
-    DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
-    DPORT_REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_MODEXP_START_REG);
-
-    DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
-}
-
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + num_words * 4, Y, num_words);
-    /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
-       This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words * 2 - 1));
-    start_op(RSA_MULT_START_REG);
-}
-
-
-
-/**
- * @brief Special-case of (X * Y), where we use hardware montgomery mod
-   multiplication to calculate result where either A or B are >2048 bits so
-   can't use the standard multiplication method.
- *
- */
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (size_t i = 0; i < num_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
-    }
-
-    /* Mprime = 1 */
-    DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
-    DPORT_REG_WRITE(RSA_LENGTH_REG, num_words - 1);
-
-    /* Load X & Y */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-
-    /* Rinv = 1, write first word */
-    DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
-
-     /* Zero out rest of the Rinv words */
-    for (size_t i = 1; i < num_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
-    }
-
-    start_op(RSA_MOD_MULT_START_REG);
-}

+ 0 - 226
components/mbedtls/port/esp32s3/bignum.c

@@ -1,226 +0,0 @@
-/*
- * Multi-precision integer library
- * ESP32 S3 hardware accelerated parts based on mbedTLS implementation
- *
- * SPDX-FileCopyrightText: The Mbed TLS Contributors
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
- */
-#include "soc/hwcrypto_periph.h"
-#include "esp_private/periph_ctrl.h"
-#include <mbedtls/bignum.h>
-#include "bignum_impl.h"
-#include "soc/dport_reg.h"
-#include "soc/system_reg.h"
-#include "soc/periph_defs.h"
-#include <sys/param.h>
-#include "esp_crypto_lock.h"
-
-size_t esp_mpi_hardware_words(size_t words)
-{
-    return words;
-}
-
-void esp_mpi_enable_hardware_hw_op( void )
-{
-    esp_crypto_mpi_lock_acquire();
-
-    /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
-
-    REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
-
-    while (DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
-    }
-    // Note: from enabling RSA clock to here takes about 1.3us
-
-    REG_WRITE(RSA_INTERRUPT_REG, 0);
-
-}
-
-void esp_mpi_disable_hardware_hw_op( void )
-{
-    REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
-
-    /* Disable RSA hardware */
-    periph_module_disable(PERIPH_RSA_MODULE);
-
-    esp_crypto_mpi_lock_release();
-}
-
-void esp_mpi_interrupt_enable( bool enable )
-{
-    REG_WRITE(RSA_INTERRUPT_REG, enable);
-}
-
-void esp_mpi_interrupt_clear( void )
-{
-    REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
-
-   If num_words is higher than the number of words in the bignum then
-   these additional words will be zeroed in the memory buffer.
-*/
-static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
-{
-    uint32_t *pbase = (uint32_t *)mem_base;
-    uint32_t copy_words = MIN(num_words, mpi->MBEDTLS_PRIVATE(n));
-
-    /* Copy MPI data to memory block registers */
-    for (uint32_t i = 0; i < copy_words; i++) {
-        pbase[i] = mpi->MBEDTLS_PRIVATE(p)[i];
-    }
-
-    /* Zero any remaining memory block data */
-    for (uint32_t i = copy_words; i < num_words; i++) {
-        pbase[i] = 0;
-    }
-}
-
-/* Read mbedTLS MPI bignum back from hardware memory block.
-
-   Reads num_words words from block.
-*/
-static inline void mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
-{
-
-    /* Copy data from memory block registers */
-    esp_dport_access_read_buffer(x->MBEDTLS_PRIVATE(p), mem_base, num_words);
-    /* Zero any remaining limbs in the bignum, if the buffer is bigger
-       than num_words */
-    for (size_t i = num_words; i < x->MBEDTLS_PRIVATE(n); i++) {
-        x->MBEDTLS_PRIVATE(p)[i] = 0;
-    }
-}
-
-
-
-/* Begin an RSA operation. op_reg specifies which 'START' register
-   to write to.
-*/
-static inline void start_op(uint32_t op_reg)
-{
-    /* Clear interrupt status */
-    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-
-    /* Note: above REG_WRITE includes a memw, so we know any writes
-       to the memory blocks are also complete. */
-
-    DPORT_REG_WRITE(op_reg, 1);
-}
-
-/* Wait for an RSA operation to complete.
-*/
-static inline void wait_op_complete(void)
-{
-    while (DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG) != 1)
-    { }
-
-    /* clear the interrupt */
-    DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
-}
-
-
-/* Read result from last MPI operation */
-void esp_mpi_read_result_hw_op(mbedtls_mpi *Z, size_t z_words)
-{
-    wait_op_complete();
-    mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words);
-}
-
-
-/* Z = (X * Y) mod M
-
-   Not an mbedTLS function
-*/
-void esp_mpi_mul_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    start_op(RSA_MOD_MULT_START_REG);
-}
-
-/* Z = (X ^ Y) mod M
-*/
-void esp_mpi_exp_mpi_mod_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, const mbedtls_mpi *Rinv, mbedtls_mpi_uint Mprime, size_t num_words)
-{
-    size_t y_bits = mbedtls_mpi_bitlen(Y);
-
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
-
-    /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-    mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
-    mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
-    DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
-
-    /* Enable acceleration options */
-    DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
-    DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
-    DPORT_REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1);
-
-    /* Execute first stage montgomery multiplication */
-    start_op(RSA_MODEXP_START_REG);
-
-    DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
-}
-
-
-/* Z = X * Y */
-void esp_mpi_mul_mpi_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* Copy X (right-extended) & Y (left-extended) to memory block */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + num_words * 4, Y, num_words);
-    /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
-       This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
-    */
-    DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words * 2 - 1));
-    start_op(RSA_MULT_START_REG);
-}
-
-
-
-/**
- * @brief Special-case of (X * Y), where we use hardware montgomery mod
-   multiplication to calculate result where either A or B are >2048 bits so
-   can't use the standard multiplication method.
- *
- */
-void esp_mpi_mult_mpi_failover_mod_mult_hw_op(const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
-{
-    /* M = 2^num_words - 1, so block is entirely FF */
-    for (size_t i = 0; i < num_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
-    }
-
-    /* Mprime = 1 */
-    DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
-    DPORT_REG_WRITE(RSA_LENGTH_REG, num_words - 1);
-
-    /* Load X & Y */
-    mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
-    mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
-
-    /* Rinv = 1, write first word */
-    DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
-
-    /* Zero out rest of the Rinv words */
-    for (size_t i = 1; i < num_words; i++) {
-        DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
-    }
-
-    start_op(RSA_MOD_MULT_START_REG);
-}

+ 4 - 0
components/soc/CMakeLists.txt

@@ -83,6 +83,10 @@ if(CONFIG_SOC_MCPWM_SUPPORTED)
     list(APPEND srcs "${target}/mcpwm_periph.c")
 endif()
 
+if(CONFIG_SOC_MPI_SUPPORTED)
+    list(APPEND srcs "${target}/mpi_periph.c")
+endif()
+
 if(CONFIG_SOC_SDMMC_HOST_SUPPORTED)
     list(APPEND srcs "${target}/sdmmc_periph.c")
 endif()

+ 8 - 0
components/soc/esp32/include/soc/Kconfig.soc_caps.in

@@ -691,6 +691,14 @@ config SOC_SHA_SUPPORT_SHA512
     bool
     default y
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    bool
+    default y
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 4096

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

@@ -340,6 +340,9 @@
 #define SOC_SHA_SUPPORT_SHA384          (1)
 #define SOC_SHA_SUPPORT_SHA512          (1)
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (1)
 
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (4096)

+ 19 - 0
components/soc/esp32/mpi_periph.c

@@ -0,0 +1,19 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/hwcrypto_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[SOC_MPI_MEM_BLOCKS_NUM] = {
+    RSA_MEM_X_BLOCK_BASE,
+    RSA_MEM_Y_BLOCK_BASE,
+    RSA_MEM_Z_BLOCK_BASE,
+    RSA_MEM_M_BLOCK_BASE,
+};
+
+const uint32_t MPI_LL_OPERATIONS[SOC_MPI_OPERATIONS_NUM] = {
+    RSA_MULT_START_REG,
+};

+ 8 - 0
components/soc/esp32c3/include/soc/Kconfig.soc_caps.in

@@ -535,6 +535,14 @@ config SOC_RTCIO_PIN_COUNT
     int
     default 0
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    int
+    default 3
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 3072

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

@@ -242,6 +242,10 @@
  * for hold, wake & 32kHz crystal functions - via rtc_cntl_reg */
 #define SOC_RTCIO_PIN_COUNT    (0U)
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (3)
+
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (3072)
 

+ 21 - 0
components/soc/esp32c3/mpi_periph.c

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/hwcrypto_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[4] = {
+    RSA_MEM_X_BLOCK_BASE,
+    RSA_MEM_Y_BLOCK_BASE,
+    RSA_MEM_Z_BLOCK_BASE,
+    RSA_MEM_M_BLOCK_BASE,
+};
+
+const uint32_t MPI_LL_OPERATIONS[3] = {
+    RSA_MULT_START_REG,
+    RSA_MOD_MULT_START_REG,
+    RSA_MODEXP_START_REG,
+};

+ 8 - 0
components/soc/esp32c6/include/soc/Kconfig.soc_caps.in

@@ -731,6 +731,14 @@ config SOC_PARLIO_TX_RX_SHARE_INTERRUPT
     bool
     default y
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    int
+    default 3
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 3072

+ 4 - 0
components/soc/esp32c6/include/soc/soc_caps.h

@@ -300,6 +300,10 @@
 #define SOC_PARLIO_RX_UNIT_MAX_DATA_WIDTH    16  /*!< Number of data lines of the RX unit */
 #define SOC_PARLIO_TX_RX_SHARE_INTERRUPT     1   /*!< TX and RX unit share the same interrupt source number */
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (3)
+
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (3072)
 

+ 21 - 0
components/soc/esp32c6/mpi_periph.c

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/rsa_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[4] = {
+    RSA_X_MEM,
+    RSA_Y_MEM,
+    RSA_Z_MEM,
+    RSA_M_MEM,
+};
+
+const uint32_t MPI_LL_OPERATIONS[3] = {
+    RSA_SET_START_MULT_REG,
+    RSA_SET_START_MODMULT_REG,
+    RSA_SET_START_MODEXP_REG,
+};

+ 8 - 0
components/soc/esp32h2/include/soc/Kconfig.soc_caps.in

@@ -731,6 +731,14 @@ config SOC_RTCIO_PIN_COUNT
     int
     default 0
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    int
+    default 3
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 3072

+ 4 - 0
components/soc/esp32h2/include/soc/soc_caps.h

@@ -311,6 +311,10 @@
  * for hold, wake & 32kHz crystal functions - via LP_AON registers */
 #define SOC_RTCIO_PIN_COUNT    (0U)
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (3)
+
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (3072)
 

+ 21 - 0
components/soc/esp32h2/mpi_periph.c

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/rsa_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[4] = {
+    RSA_X_MEM_REG,
+    RSA_Y_MEM_REG,
+    RSA_Z_MEM_REG,
+    RSA_M_MEM_REG,
+};
+
+const uint32_t MPI_LL_OPERATIONS[3] = {
+    RSA_SET_START_MULT_REG,
+    RSA_SET_START_MODMULT_REG,
+    RSA_SET_START_MODEXP_REG,
+};

+ 8 - 0
components/soc/esp32s2/include/soc/Kconfig.soc_caps.in

@@ -831,6 +831,14 @@ config SOC_SHA_SUPPORT_SHA512_T
     bool
     default y
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    int
+    default 3
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 4096

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

@@ -361,6 +361,10 @@
 #define SOC_SHA_SUPPORT_SHA512_T        (1)
 
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (3)
+
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (4096)
 

+ 21 - 0
components/soc/esp32s2/mpi_periph.c

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/hwcrypto_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[4] = {
+    RSA_MEM_X_BLOCK_BASE,
+    RSA_MEM_Y_BLOCK_BASE,
+    RSA_MEM_Z_BLOCK_BASE,
+    RSA_MEM_M_BLOCK_BASE,
+};
+
+const uint32_t MPI_LL_OPERATIONS[3] = {
+    RSA_MULT_START_REG,
+    RSA_MOD_MULT_START_REG,
+    RSA_MODEXP_START_REG,
+};

+ 8 - 0
components/soc/esp32s3/include/soc/Kconfig.soc_caps.in

@@ -967,6 +967,14 @@ config SOC_SHA_SUPPORT_SHA512_T
     bool
     default y
 
+config SOC_MPI_MEM_BLOCKS_NUM
+    int
+    default 4
+
+config SOC_MPI_OPERATIONS_NUM
+    int
+    default 3
+
 config SOC_RSA_MAX_BIT_LEN
     int
     default 4096

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

@@ -390,6 +390,10 @@
 #define SOC_SHA_SUPPORT_SHA512_T        (1)
 
 
+/*--------------------------- MPI CAPS ---------------------------------------*/
+#define SOC_MPI_MEM_BLOCKS_NUM (4)
+#define SOC_MPI_OPERATIONS_NUM (3)
+
 /*--------------------------- RSA CAPS ---------------------------------------*/
 #define SOC_RSA_MAX_BIT_LEN    (4096)
 

+ 21 - 0
components/soc/esp32s3/mpi_periph.c

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "soc/hwcrypto_reg.h"
+#include "soc/mpi_periph.h"
+
+const uint32_t MPI_LL_BLOCK_BASES[4] = {
+    RSA_MEM_X_BLOCK_BASE,
+    RSA_MEM_Y_BLOCK_BASE,
+    RSA_MEM_Z_BLOCK_BASE,
+    RSA_MEM_M_BLOCK_BASE,
+};
+
+const uint32_t MPI_LL_OPERATIONS[3] = {
+    RSA_MULT_START_REG,
+    RSA_MOD_MULT_START_REG,
+    RSA_MODEXP_START_REG,
+};

+ 22 - 0
components/soc/include/soc/mpi_periph.h

@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include "soc/soc_caps.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern const uint32_t MPI_LL_BLOCK_BASES[SOC_MPI_MEM_BLOCKS_NUM];
+extern const uint32_t MPI_LL_OPERATIONS[SOC_MPI_OPERATIONS_NUM];
+
+#ifdef __cplusplus
+}
+#endif