Browse Source

Various Espressif HW crypto, SHA2, AES, MP updates. (#6287)

* various Espressif HW crypto, SHA2, AES, MP updates.

* code review updates & cleanup

* clean trailing whitespace

* cleanup per code review

* removed additional unused WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW

* Code review updates; pack & order WC_ESP32SHA

* clean up TAG text for Espressif ESP_LOG()
gojimmypi 1 year ago
parent
commit
510038022f

+ 3 - 0
IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt

@@ -190,6 +190,8 @@ set(COMPONENT_SRCEXCLUDE
     "${WOLFSSL_ROOT}/src/conf.c"
     "${WOLFSSL_ROOT}/src/misc.c"
     "${WOLFSSL_ROOT}/src/pk.c"
+    "${WOLFSSL_ROOT}/src/ssl_asn1.c" # included by ssl.c
+    "${WOLFSSL_ROOT}/src/ssl_bn.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/ssl_misc.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/x509.c"
     "${WOLFSSL_ROOT}/src/x509_str.c"
@@ -197,6 +199,7 @@ set(COMPONENT_SRCEXCLUDE
     "${WOLFSSL_ROOT}/wolfcrypt/src/misc.c"
     "${EXCLUDE_ASM}"
     )
+set(COMPONENT_PRIV_INCLUDEDIRS ${IDF_PATH}/components/driver/include)
 
 register_component()
 

+ 2 - 0
IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt

@@ -190,6 +190,8 @@ set(COMPONENT_SRCEXCLUDE
     "${WOLFSSL_ROOT}/src/conf.c"
     "${WOLFSSL_ROOT}/src/misc.c"
     "${WOLFSSL_ROOT}/src/pk.c"
+    "${WOLFSSL_ROOT}/src/ssl_asn1.c" # included by ssl.c
+    "${WOLFSSL_ROOT}/src/ssl_bn.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/ssl_misc.c" # included by ssl.c
     "${WOLFSSL_ROOT}/src/x509.c"
     "${WOLFSSL_ROOT}/src/x509_str.c"

+ 2 - 1
IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c

@@ -178,7 +178,8 @@ void app_main(void)
     #elif defined(CONFIG_IDF_TARGET_ESP32S2)
         #error "ESP32WROOM32_CRYPT not yet supported on ESP32-S2"
     #elif defined(CONFIG_IDF_TARGET_ESP32S3)
-        #error "ESP32WROOM32_CRYPT not yet supported on ESP32-S3"
+        /* #error "ESP32WROOM32_CRYPT not yet supported on ESP32-S3" */
+        ESP_LOGI(TAG, "ESP32WROOM32_CRYPT is enabled for  ESP32-S3.");
     #else
         ESP_LOGI(TAG, "ESP32WROOM32_CRYPT is enabled.");
     #endif

+ 42 - 11
wolfcrypt/benchmark/benchmark.c

@@ -66,7 +66,21 @@
 #include <wolfssl/wolfcrypt/wolfmath.h>
 
 #ifdef WOLFSSL_ESPIDF
-    #include <xtensa/hal.h> /* reminder Espressif RISC-V not yet implemented */
+    #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
+        #include "driver/gptimer.h"
+        static gptimer_handle_t esp_gptimer = NULL;
+        static gptimer_config_t esp_timer_config = {
+                            .clk_src = GPTIMER_CLK_SRC_DEFAULT,
+                            .direction = GPTIMER_COUNT_UP,
+                            .resolution_hz = CONFIG_XTAL_FREQ * 1000000,
+                         };
+    #elif defined(CONFIG_IDF_TARGET_ESP32) || \
+          defined(CONFIG_IDF_TARGET_ESP32S2) || \
+          defined(CONFIG_IDF_TARGET_ESP32S3)
+        #include <xtensa/hal.h>
+    #else
+        #error "CONFIG_IDF_TARGET not implemented"
+    #endif
     #include <esp_log.h>
 #endif
 
@@ -1001,13 +1015,18 @@ static const char* bench_desc_words[][15] = {
     ** the Espressif `unsigned xthal_get_ccount()` which is known to overflow
     ** at least once during full benchmark tests.
     */
-    word64 xthal_get_ccount_ex()
+    uint64_t xthal_get_ccount_ex()
     {
         /* reminder: unsigned long long max = 18,446,744,073,709,551,615 */
 
         /* the currently observed clock counter value */
-        word64 thisVal = xthal_get_ccount();
-
+    #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
+        uint64_t thisVal = 0;
+        ESP_ERROR_CHECK(gptimer_get_raw_count(esp_gptimer, &thisVal));
+    #else
+        /* reminder unsupported CONFIG_IDF_TARGET captured above */
+        uint64_t thisVal = xthal_get_ccount();
+    #endif
         /* if the current value is less than the previous value,
         ** we likely overflowed at least once.
         */
@@ -1034,8 +1053,12 @@ static const char* bench_desc_words[][15] = {
         _xthal_get_ccount_ex += (thisVal - _xthal_get_ccount_last);
 
         /* all of this took some time, so reset the "last seen" value */
-        _xthal_get_ccount_last = xthal_get_ccount();
-
+    #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
+        ESP_ERROR_CHECK(gptimer_get_raw_count(esp_gptimer,
+                                              &_xthal_get_ccount_last));
+    #else
+         _xthal_get_ccount_last = xthal_get_ccount();
+    #endif
         return _xthal_get_ccount_ex;
     }
 
@@ -4992,7 +5015,7 @@ exit:
 
     WC_FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT);
 }
-#endif
+#endif /* WOLFSSL_NOSHA512_224 && !FIPS ... */
 
 #if !defined(WOLFSSL_NOSHA512_256) && \
    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
@@ -5086,10 +5109,9 @@ exit:
 
     WC_FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT);
 }
+#endif /* WOLFSSL_NOSHA512_256 && !FIPS ... */
 
-#endif
-
-#endif
+#endif /* WOLFSSL_SHA512 */
 
 
 #ifdef WOLFSSL_SHA3
@@ -7494,8 +7516,9 @@ void bench_eccEncrypt(int curveId)
     if (ret != 0)
         goto exit;
 
-    for (i = 0; i < (int)sizeof(msg); i++)
+    for (i = 0; i < (int)sizeof(msg); i++) {
         msg[i] = (byte)i;
+    }
 
     bench_stats_start(&count, &start);
     do {
@@ -9095,6 +9118,14 @@ static int string_matches(const char* arg, const char* str)
     #ifdef WOLFSSL_ESPIDF
         int argc = construct_argv();
         char** argv = (char**)__argv;
+
+    #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
+        ESP_ERROR_CHECK(gptimer_new_timer(&esp_timer_config, &esp_gptimer));
+        ESP_LOGI(TAG, "Enable ESP32-C3 timer ");
+        ESP_ERROR_CHECK(gptimer_enable(esp_gptimer));
+        ESP_ERROR_CHECK(gptimer_start(esp_gptimer));
+    #endif
+
     #endif
 
     return wolfcrypt_benchmark_main(argc, argv);

+ 185 - 80
wolfcrypt/src/port/Espressif/esp32_aes.c

@@ -35,10 +35,12 @@
 
 #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
     !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
-
+#include "sdkconfig.h" /* programmatically generated from sdkconfig */
 #include <wolfssl/wolfcrypt/aes.h>
 #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+#include <wolfssl/wolfcrypt/error-crypt.h>
 
+/* breadcrumb tag text for ESP_LOG() */
 static const char* TAG = "wolf_hw_aes";
 
 /* mutex */
@@ -67,27 +69,36 @@ static int esp_aes_hw_InUse()
         }
         else {
             ESP_LOGE(TAG, "aes mutex initialization failed.");
-            return -1;
         }
     }
     else {
         /* esp aes has already been initialized */
     }
 
-    /* lock hardware */
-    ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
-
-    if(ret != 0) {
+    if (ret == 0) {
+        /* lock hardware */
+        ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
+    }
+    else {
         ESP_LOGE(TAG, "aes engine lock failed.");
-        return -1;
     }
 
-    /* Enable AES hardware */
-    periph_module_enable(PERIPH_AES_MODULE);
+
+    if (ret == 0) {
+        /* Enable AES hardware */
+        periph_module_enable(PERIPH_AES_MODULE);
+
+        #if CONFIG_IDF_TARGET_ESP32S3
+        /* Select working mode. Can be typical or DMA.
+         * 0 => typical
+         * 1 => DMA */
+        DPORT_REG_WRITE(AES_DMA_ENABLE_REG, 0);
+        #endif
+    }
 
     ESP_LOGV(TAG, "leave esp_aes_hw_InUse");
     return ret;
-}
+} /* esp_aes_hw_InUse */
 
 /*
 *   release hw engine
@@ -102,20 +113,22 @@ static void esp_aes_hw_Leave( void )
     esp_CryptHwMutexUnLock(&aes_mutex);
 
     ESP_LOGV(TAG, "leave esp_aes_hw_Leave");
-}
+} /* esp_aes_hw_Leave */
 
 /*
  * set key to hardware key registers.
+ * return 0 on success; -1 if mode isn't supported.
  */
-static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
+static int esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
 {
+    int ret = 0;
     word32 i;
     word32 mode_ = 0;
 
     ESP_LOGV(TAG, "  enter esp_aes_hw_Set_KeyMode");
 
     /* check mode */
-    if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
+    if (mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
         mode_ = 0;
     }
     else {
@@ -124,47 +137,89 @@ static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
         }
         else {
             ESP_LOGE(TAG, "  >> unexpected error.");
-            return;
+            ret = BAD_FUNC_ARG;
         }
-    }
+    } /* if mode */
 
-    /* update key */
-    for(i=0; i<(ctx->keylen)/sizeof(word32); i++){
-        DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i));
-    }
+    if (ret == 0) {
+
+        /* update key */
+        for (i = 0; i < (ctx->keylen) / sizeof(word32); i++) {
+            DPORT_REG_WRITE(AES_KEY_BASE + (i * 4), *(((word32*)ctx->key) + i));
+        }
+
+        /*
+        ** ESP32: see table 22-1 in ESP32 Technical Reference
+        ** ESP32S3: see table 19-2 in ESP32S3 Technical Reference
+        ** mode     Algorithm             ESP32   ESP32S3
+        **   0       AES-128 Encryption     y        y
+        **   1       AES-192 Encryption     y        n
+        **   2       AES-256 Encryption     y        y
+        **   4       AES-128 Decryption     y        y
+        **   5       AES-192 Decryption     y        n
+        **   6       AES-256 Decryption     y        y
+        */
+        switch(ctx->keylen){
+            case 24: mode_ += 1; break;
+            case 32: mode_ += 2; break;
+            default: break;
+        }
+
+    #if CONFIG_IDF_TARGET_ESP32S3
+        if (mode_ == 1 || mode_ == 5 || mode_ == 7) {
+            ESP_LOGE(TAG, "esp_aes_hw_Set_KeyMode unsupported mode: %i", mode_);
+            ret = BAD_FUNC_ARG;
+        }
+    #endif
 
-    /* mode
-    *   0       AES-128 Encryption
-    *   1       AES-192 Encryption
-    *   2       AES-256 Encryption
-    *   4       AES-128 Decryption
-    *   5       AES-192 Decryption
-    *   6       AES-256 Decryption
-    */
-    switch(ctx->keylen){
-        case 24: mode_ += 1; break;
-        case 32: mode_ += 2; break;
-        default: break;
+        if (ret == 0) {
+            DPORT_REG_WRITE(AES_MODE_REG, mode_);
+        }
+        ESP_LOGV(TAG, "  leave esp_aes_hw_Setkey");
     }
 
-    DPORT_REG_WRITE(AES_MODE_REG, mode_);
-    ESP_LOGV(TAG, "  leave esp_aes_hw_Setkey");
-}
+    return ret;
+} /* esp_aes_hw_Set_KeyMode */
 
 /*
+ * esp_aes_bk
  * Process a one block of AES
+ * in: block of 16 bytes (4 x words32) to process
+ * out: result of processing input bytes.
  */
 static void esp_aes_bk(const byte* in, byte* out)
 {
     const word32 *inwords = (const word32 *)in;
+
 #if ESP_IDF_VERSION_MAJOR >= 4
-    uint32_t *outwords      = (uint32_t *)out;
+    uint32_t *outwords    = (uint32_t *)out;
 #else
     word32 *outwords      = (word32 *)out;
 #endif
 
     ESP_LOGV(TAG, "enter esp_aes_bk");
+#if CONFIG_IDF_TARGET_ESP32S3
+    /* See esp32 - s3 technical reference manual:
+    ** 19.4.3 Operation process using CPU working mode.
+    ** The ESP32-S3 also supports a DMA mode.
+    **
+    ** Copy text for encrypting/decrypting blocks: */
+    DPORT_REG_WRITE(AES_TEXT_IN_BASE, inwords[0]);
+    DPORT_REG_WRITE(AES_TEXT_IN_BASE + 4, inwords[1]);
+    DPORT_REG_WRITE(AES_TEXT_IN_BASE + 8, inwords[2]);
+    DPORT_REG_WRITE(AES_TEXT_IN_BASE + 12, inwords[3]);
+
+    /* start engine */
+    DPORT_REG_WRITE(AES_TRIGGER_REG, 1);
 
+    /* wait until finishing the process */
+    while (DPORT_REG_READ(AES_STATE_REG) != 0) {
+        /* wating for the hardware accelerator to complete operation. */
+    }
+
+    /* read-out blocks */
+    esp_dport_access_read_buffer(outwords, AES_TEXT_OUT_BASE, 4);
+#else
     /* copy text for encrypting/decrypting blocks */
     DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]);
     DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]);
@@ -175,15 +230,18 @@ static void esp_aes_bk(const byte* in, byte* out)
     DPORT_REG_WRITE(AES_START_REG, 1);
 
     /* wait until finishing the process */
-    while(1) {
-        if(DPORT_REG_READ(AES_IDLE_REG) == 1)
+    while (1) {
+        if (DPORT_REG_READ(AES_IDLE_REG) == 1) {
             break;
+        }
     }
 
     /* read-out blocks */
     esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4);
+#endif
+
     ESP_LOGV(TAG, "leave esp_aes_bk");
-}
+} /* esp_aes_bk */
 
 /*
 * wc_esp32AesEncrypt
@@ -192,20 +250,33 @@ static void esp_aes_bk(const byte* in, byte* out)
 * @param in : a pointer of the input buffer containing plain text to be encrypted
 * @param out: a pointer of the output buffer in which to store the cipher text of
 *             the encrypted message
+* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported.
 */
 int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
 {
+    int ret = 0;
+
     ESP_LOGV(TAG, "enter wc_esp32AesEncrypt");
     /* lock the hw engine */
-    esp_aes_hw_InUse();
+    ret = esp_aes_hw_InUse();
+
+    if (ret == 0) {
+        ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
+        if (ret != 0) {
+            ESP_LOGE(TAG, "wc_esp32AesEncrypt failed during esp_aes_hw_Set_KeyMode");
+        }
+    }
+
     /* load the key into the register */
-    esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
-    /* process a one block of AES */
-    esp_aes_bk(in, out);
+    if (ret == 0) {
+        /* process a one block of AES */
+        esp_aes_bk(in, out);
+    }
+
     /* release hw */
     esp_aes_hw_Leave();
-    return 0;
-}
+    return ret;
+} /* wc_esp32AesEncrypt */
 
 /*
 * wc_esp32AesDecrypt
@@ -214,20 +285,33 @@ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
 * @param in : a pointer of the input buffer containing plain text to be decrypted
 * @param out: a pointer of the output buffer in which to store the cipher text of
 *             the decrypted message
+* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported.
 */
 int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
 {
+    int ret;
+
     ESP_LOGV(TAG, "enter wc_esp32AesDecrypt");
     /* lock the hw engine */
     esp_aes_hw_InUse();
     /* load the key into the register */
-    esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
-    /* process a one block of AES */
-    esp_aes_bk(in, out);
-    /* release hw engine */
-    esp_aes_hw_Leave();
-    return 0;
-}
+    ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
+    if (ret != 0) {
+        ESP_LOGE(TAG, "wc_esp32AesDecrypt failed during esp_aes_hw_Set_KeyMode");
+        /* release hw */
+        esp_aes_hw_Leave();
+        ret = BAD_FUNC_ARG;
+    }
+
+    if (ret == 0) {
+        /* process a one block of AES */
+        esp_aes_bk(in, out);
+        /* release hw engine */
+        esp_aes_hw_Leave();
+    }
+
+    return ret;
+} /* wc_esp32AesDecrypt */
 
 /*
 * wc_esp32AesCbcEncrypt
@@ -239,9 +323,11 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
 *             the encrypted message
 * @param in : a pointer of the input buffer containing plain text to be encrypted
 * @param sz : size of input message
+* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported.
 */
 int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 {
+    int ret;
     int i;
     int offset = 0;
     word32 blocks = (sz / AES_BLOCK_SIZE);
@@ -250,31 +336,40 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 
     ESP_LOGV(TAG, "enter wc_esp32AesCbcEncrypt");
 
-    iv      = (byte*)aes->reg;
+    iv = (byte*)aes->reg;
 
-    esp_aes_hw_InUse();
+    ret = esp_aes_hw_InUse();
 
-    esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
+    if (ret == 0) {
+        ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
+        if (ret != 0) {
+            ESP_LOGE(TAG, "wc_esp32AesCbcEncrypt failed HW Set KeyMode");
+        }
+    } /* if set esp_aes_hw_InUse successful */
 
-    while (blocks--) {
-          XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+    if (ret == 0) {
+        while (blocks--) {
+            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
 
-         /* XOR block with IV for CBC */
-         for (i = 0; i < AES_BLOCK_SIZE; i++)
-             temp_block[i] ^= iv[i];
+            /* XOR block with IV for CBC */
+            for (i = 0; i < AES_BLOCK_SIZE; i++) {
+                temp_block[i] ^= iv[i];
+            }
 
-         esp_aes_bk(temp_block, (out + offset));
+            esp_aes_bk(temp_block, (out + offset));
 
-         offset += AES_BLOCK_SIZE;
+            offset += AES_BLOCK_SIZE;
 
-         /* store IV for next block */
-         XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
-    }
+            /* store IV for next block */
+            XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+        } /* while (blocks--) */
+    } /* if Set Mode successful (ret == 0) */
 
     esp_aes_hw_Leave();
     ESP_LOGV(TAG, "leave wc_esp32AesCbcEncrypt");
     return 0;
-}
+} /* wc_esp32AesCbcEncrypt */
+
 /*
 * wc_esp32AesCbcDecrypt
 * @brief: Encrypts a plain text message from the input buffer, and places the
@@ -285,9 +380,12 @@ int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 *             the decrypted message
 * @param in : a pointer of the input buffer containing plain text to be decrypted
 * @param sz : size of input message
+* @return: 0 on success, BAD_FUNC_ARG if the AES algorithm isn't supported.
 */
 int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 {
+    int ret;
+
     int i;
     int offset = 0;
     word32 blocks = (sz / AES_BLOCK_SIZE);
@@ -296,32 +394,39 @@ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 
     ESP_LOGV(TAG, "enter wc_esp32AesCbcDecrypt");
 
-    iv      = (byte*)aes->reg;
+    iv = (byte*)aes->reg;
 
-    esp_aes_hw_InUse();
+    ret = esp_aes_hw_InUse();
 
-    esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
+    if (ret == 0) {
+        ret = esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
+        if (ret != 0) {
+            ESP_LOGE(TAG, "wc_esp32AesCbcDecrypt failed HW Set KeyMode");
+        }
+    }
 
-    while (blocks--) {
-        XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+    if (ret == 0) {
+        while (blocks--) {
+            XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
 
-        esp_aes_bk((in + offset), (out + offset));
+            esp_aes_bk((in + offset), (out + offset));
 
-        /* XOR block with IV for CBC */
-        for (i = 0; i < AES_BLOCK_SIZE; i++) {
-            (out + offset)[i] ^= iv[i];
-        }
+            /* XOR block with IV for CBC */
+            for (i = 0; i < AES_BLOCK_SIZE; i++) {
+                (out + offset)[i] ^= iv[i];
+            }
 
-        /* store IV for next block */
-        XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
+            /* store IV for next block */
+            XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
 
-        offset += AES_BLOCK_SIZE;
-    }
+            offset += AES_BLOCK_SIZE;
+        } /* while (blocks--) */
+    } /* if Set Mode was successful (ret == 0) */
 
     esp_aes_hw_Leave();
     ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt");
     return 0;
-}
+} /* wc_esp32AesCbcDecrypt */
 
 #endif /* WOLFSSL_ESP32WROOM32_CRYPT */
 #endif /* NO_AES */

+ 347 - 59
wolfcrypt/src/port/Espressif/esp32_mp.c

@@ -48,6 +48,7 @@ static const char* const TAG = "wolfssl_mp";
 #define ESP_HW_RSAMIN_BIT           512
 #define BYTE_TO_WORDS(s)            (((s+3)>>2))           /* (s+(4-1))/ 4    */
 #define BITS_TO_WORDS(s)            (((s+31)>>3)>>2)       /* (s+(32-1))/ 8/ 4*/
+#define BITS_IN_ONE_WORD            32
 
 #define MP_NG   -1
 
@@ -57,7 +58,7 @@ static const char* const TAG = "wolfssl_mp";
 static wolfSSL_Mutex mp_mutex;
 static int espmp_CryptHwMutexInit = 0;
 /*
-* check if the hw is ready before accessing it
+* check if the HW is ready before accessing it
 *
 * When the RSA Accelerator is released from reset, the register RSA_CLEAN_REG
 * reads 0 and an initialization process begins. Hardware initializes the four
@@ -66,27 +67,39 @@ static int espmp_CryptHwMutexInit = 0;
 * after being released from reset, and before writing to any RSA Accelerator
 * memory blocks or registers for the first time.
 */
-static int esp_mp_hw_wait_clean()
+static int esp_mp_hw_wait_clean(void)
 {
+	int ret = MP_OKAY;
     word32 timeout = 0;
 
-    while(!ESP_TIMEOUT(++timeout) &&
-                DPORT_REG_READ(RSA_CLEAN_REG) != 1) {
+#if CONFIG_IDF_TARGET_ESP32S3
+
+    while (!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1)
+    {
+      /*  wait. expected delay 1 to 2 uS  */
+    }
+#else
+  /* RSA_CLEAN_REG is now called RSA_QUERY_CLEAN_REG. hwcrypto_reg.h maintains
+   * RSA_CLEAN_REG for backwards compatibility so this block _might_ be not needed. */
+    while(!ESP_TIMEOUT(++timeout) && DPORT_REG_READ(RSA_CLEAN_REG) != 1) {
         /*  wait. expected delay 1 to 2 uS  */
     }
+#endif
 
     if (ESP_TIMEOUT(timeout)) {
-        ESP_LOGE(TAG, "waiting hw ready is timed out.");
-        return MP_NG;
+        ESP_LOGE(TAG, "esp_mp_hw_wait_clean waiting HW ready timed out.");
+        ret = MP_NG;
     }
-    return MP_OKAY;
+    return ret;
 }
 
 /*
-* lock hw engine.
-* this should be called before using engine.
+* esp_mp_hw_lock()
+*
+* Lock HW engine.
+* This should be called before using engine.
 *
-* returns 0 if the hw lock was initialized and mutex lock
+* Returns 0 if the HW lock was initialized and mutex lock.
 *
 * See Chapter 24:
 *  https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
@@ -116,27 +129,40 @@ static int esp_mp_hw_lock()
         }
         else {
             ESP_LOGE(TAG, "mp mutex initialization failed.");
-            return MP_NG;
         }
     }
     else {
-        /* esp aes has already been initialized */
+        /* ESP AES has already been initialized */
     }
 
-    /* lock hardware */
-    ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY);
+    if (ret == 0) {
+        /* lock hardware */
+        ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY);
+        if (ret != 0) {
+            ESP_LOGE(TAG, "mp engine lock failed.");
+            ret = MP_NG;
+        }
+   }
 
-    if (ret != 0) {
-        ESP_LOGE(TAG, "mp engine lock failed.");
-        return MP_NG;
-    }
+#if CONFIG_IDF_TARGET_ESP32S3
+    /* Activate the RSA accelerator. See 20.3 of ESP32-S3 technical manual.
+     * periph_module_enable doesn't seem to be documented and in private folder
+     * with v5 release. Maybe it will be deprecated? */
+    if (ret == 0) {
+        periph_module_enable(PERIPH_RSA_MODULE);
 
+        /* clear bit to enable hardware operation; (set to disable) */
+        DPORT_REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+    }
+#else
     /* Enable RSA hardware */
-    periph_module_enable(PERIPH_RSA_MODULE);
+    if (ret == 0) {
+        periph_module_enable(PERIPH_RSA_MODULE);
 
-    /* clear bit to enable hardware operation; (set to disable)
-     */
-    DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+        /* clear bit to enable hardware operation; (set to disable) */
+        DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
+    }
+#endif
 
     /* reminder: wait until RSA_CLEAN_REG reads 1
      *  see esp_mp_hw_wait_clean()
@@ -145,17 +171,27 @@ static int esp_mp_hw_lock()
     ESP_LOGV(TAG, "leave esp_mp_hw_lock");
     return ret;
 }
+
 /*
-*   Release hw engine
+*   Release HW engine
 */
 static void esp_mp_hw_unlock( void )
 {
+#if CONFIG_IDF_TARGET_ESP32S3
+    /* Deactivate the RSA accelerator. See 20.3 of ESP32-S3 technical manual.
+     * periph_module_enable doesn't seem to be documented and in private folder
+     * with v5 release. Maybe it will be deprecated? */
+    DPORT_REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
+    periph_module_disable(PERIPH_RSA_MODULE);
+
+#else
     /* set bit to disabled hardware operation; (clear to enable)
      */
     DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
 
     /* Disable RSA hardware */
     periph_module_disable(PERIPH_RSA_MODULE);
+#endif
 
     /* unlock */
     esp_CryptHwMutexUnLock(&mp_mutex);
@@ -189,7 +225,7 @@ static int esp_calc_Mdash(MATH_INT_T *M, word32 k, mp_digit* md)
     return MP_OKAY;
 }
 
-/* start hw process */
+/* start HW process */
 static void process_start(word32 reg)
 {
      /* clear interrupt */
@@ -249,7 +285,8 @@ static void esp_mpint_to_memblock(word32 mem_address, const MATH_INT_T* mp,
         }
     }
 }
-/* return needed hw words.
+
+/* return needed HW words.
  * supported words length
  *  words : {16 ,  32,  48,    64,   80,   96, 112,   128}
  *  bits  : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096}
@@ -294,7 +331,91 @@ static int esp_get_rinv(MATH_INT_T *rinv, MATH_INT_T *M, word32 exp)
 int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z)
 {
     int ret = 0;
+
+#if CONFIG_IDF_TARGET_ESP32S3
+
+    int BitsInX = mp_count_bits(X);
+    int BitsInY = mp_count_bits(Y);
+
+    /* X & Y must be represented by the same number of bits. Must be
+     * enough to represent the larger one. */
+    int MinXYBits = max(BitsInX, BitsInY);
+
+    /* Figure out how many words we need to represent each operand & the result. */
+    int WordsForOperand = bits2words(MinXYBits);
+    int WordsForResult = bits2words(BitsInX + BitsInY);
+
+#ifdef WOLFSSL_SP_INT_NEGATIVE
     int neg;
+    neg = (X->sign == Y->sign) ? MP_ZPOS : MP_NEG;
+#endif
+    /* Make sure we are within capabilities of hardware. */
+    if ( (WordsForOperand * BITS_IN_ONE_WORD) > ESP_HW_MULTI_RSAMAX_BITS ) {
+        ESP_LOGW(TAG, "exceeds max bit length(2048)");
+        return MP_VAL; /*  Error: value is not able to be used. */
+    }
+
+    /* Steps to perform large number multiplication. Calculates Z = X x Y. The number of
+     * bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the
+     * maximum number of bits in the X and Y is 2048.
+     * See 20.3.3 of ESP32-S3 technical manual
+     *  1. Lock the hardware so no-one else uses it and wait until it is ready.
+     *  2. Enable/disable interrupt that signals completion -- we don't use the interrupt.
+     *  3. Write number of words required for result to the RSA_MODE_REG (now called RSA_LENGTH_REG).
+     *     Number of words required for the result is 2 * words for operand - 1
+     *  4. Load X, Y operands to memory blocks. Note the Y value must be written to
+     *     right aligned.
+     *  5. Start the operation by writing 1 to RSA_MULT_START_REG, then wait for it
+     *     to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG).
+     *  6. Read the result out.
+     *  7. Release the hardware lock so others can use it.
+     *  x. Clear the interrupt flag, if you used it (we don't). */
+
+    /* 1. lock HW for use & wait until it is ready. */
+    if ( ((ret = esp_mp_hw_lock()) != MP_OKAY) ||
+         ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) ) {
+        return ret;
+    }
+
+    /* 2. Disable completion interrupt signal; we don't use. */
+    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion.
+
+    /* 3. Write number of words required for result. */
+    if ( (WordsForOperand * BITS_IN_ONE_WORD * 2) > ESP_HW_RSAMAX_BIT) {
+        ESP_LOGW(TAG, "result exceeds max bit length");
+        return MP_VAL; /*  Error: value is not able to be used. */
+    }
+    DPORT_REG_WRITE(RSA_LENGTH_REG, (WordsForOperand * 2 - 1) );
+
+    /* 4. Load X, Y operands. Maximum is 64 words (64*8*4 = 2048 bits) */
+    esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE,
+                          X, BitsInX, WordsForOperand);
+    esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + WordsForOperand * 4,
+                          Y, BitsInY, WordsForOperand);
+
+
+    /* 5. Start operation and wait until it completes. */
+    process_start(RSA_MULT_START_REG);
+    ret = wait_until_done(RSA_QUERY_INTERRUPT_REG);
+    if (MP_OKAY != ret) {
+        return ret;
+    }
+
+    /* 6. read the result form MEM_Z              */
+    esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, WordsForResult);
+
+    /* 7. clear and release HW                    */
+    esp_mp_hw_unlock();
+
+#ifdef WOLFSSL_SP_INT_NEGATIVE
+    Z->sign = (Z->used > 0) ? neg : MP_ZPOS;
+#endif
+
+    return ret;
+    /* end if CONFIG_IDF_TARGET_ESP32S3 */
+
+#else /* not CONFIG_IDF_TARGET_ESP32S3 */
+    /* assumed to be regular Xtensa here */
     word32 Xs;
     word32 Ys;
     word32 Zs;
@@ -302,25 +423,27 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z)
     word32 hwWords_sz;
 
     /* neg check - X*Y becomes negative */
+#ifdef WOLFSSL_SP_INT_NEGATIVE
     neg = mp_isneg(X) != mp_isneg(Y) ? 1 : 0;
+#endif
 
     /* ask bits number */
     Xs = mp_count_bits(X);
     Ys = mp_count_bits(Y);
     Zs = Xs + Ys;
 
-    /* maximum bits and words for writing to hw */
+    /* maximum bits and words for writing to HW */
     maxWords_sz = bits2words(max(Xs, Ys));
     hwWords_sz  = words2hwords(maxWords_sz);
 
     /* sanity check */
     if((hwWords_sz<<5) > ESP_HW_MULTI_RSAMAX_BITS) {
         ESP_LOGW(TAG, "exceeds max bit length(2048)");
-        return -2;
+        return MP_VAL; /*  Error: value is not able to be used. */
     }
 
-    /*Steps to use hw in the following order:
-    * 1. wait until clean hw engine
+    /*Steps to use HW in the following order:
+    * 1. wait until clean HW engine
     * 2. Write(2*N/512bits - 1 + 8) to MULT_MODE_REG
     * 3. Write X and Y to memory blocks
     *    need to write data to each memory block only according to the length
@@ -331,9 +454,9 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z)
     * 6. Write 1 to RSA_INTERRUPT_REG to clear the interrupt.
     * 7. Read the Z from RSA_Z_MEM
     * 8. Write 1 to RSA_INTERUPT_REG to clear the interrupt.
-    * 9. Release the hw engine
+    * 9. Release the HW engine
     */
-    /* lock hw for use */
+    /* lock HW for use */
     if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
         return ret;
     }
@@ -366,14 +489,18 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z)
     /* step.6 read the result form MEM_Z              */
     esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Zs));
 
-    /* step.7 clear and release hw                    */
+    /* step.7 clear and release HW                    */
     esp_mp_hw_unlock();
 
+
+#ifdef WOLFSSL_SP_INT_NEGATIVE
     if (!mp_iszero(Z) && neg) {
         mp_setneg(Z);
     }
+#endif
 
     return ret;
+#endif /* CONFIG_IDF_TARGET_ESP32S3 or not */
 }
 
 /* Z = X * Y (mod M)                                  */
@@ -392,6 +519,12 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
     MATH_INT_T tmpZ;
     mp_digit mp;
 
+    uint32_t Exponent;
+#if CONFIG_IDF_TARGET_ESP32S3
+    uint32_t OperandBits;
+    int WordsForOperand;
+# endif
+
     /* neg check - X*Y becomes negative */
     negcheck = mp_isneg(X) != mp_isneg(Y) ? 1 : 0;
 
@@ -400,27 +533,33 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
     Ys = mp_count_bits(Y);
     Ms = mp_count_bits(M);
 
-    /* maximum bits and words for writing to hw */
+    /* maximum bits and words for writing to HW */
     maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
     zwords      = bits2words(min(Ms, Xs + Ys));
     hwWords_sz  = words2hwords(maxWords_sz);
 
     if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
-        ESP_LOGE(TAG, "exceeds hw maximum bits");
-        return -2;
+        ESP_LOGE(TAG, "exceeds HW maximum bits");
+        return MP_VAL; /*  Error: value is not able to be used. */
     }
     /* calculate r_inv = R^2 mode M
     *    where: R = b^n, and b = 2^32
     *    accordingly R^2 = 2^(n*32*2)
     */
+#if CONFIG_IDF_TARGET_ESP32S3
+    Exponent = maxWords_sz * BITS_IN_ONE_WORD * 2;
+#else
+    Exponent = hwWords_sz << 6;
+#endif
     ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL);
-    if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
+    if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, Exponent)) != MP_OKAY) {
         ESP_LOGE(TAG, "calculate r_inv failed.");
         mp_clear(&tmpZ);
         mp_clear(&r_inv);
         return ret;
     }
-    /* lock hw for use */
+
+    /* lock HW for use */
     if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
         mp_clear(&tmpZ);
         mp_clear(&r_inv);
@@ -431,10 +570,85 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
         ESP_LOGE(TAG, "failed to calculate M dash");
         mp_clear(&tmpZ);
         mp_clear(&r_inv);
-        return -1;
+        return ret;
+    }
+
+#if CONFIG_IDF_TARGET_ESP32S3
+    /* Steps to perform large number modular multiplication. Calculates Z = (X x Y) modulo M.
+     * The number of bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the
+     * maximum number of bits in the X and Y is 2048. We must use the same number of words to represent
+     * the bits in X, Y and M.
+     * See 20.3.3 of ESP32-S3 technical manual
+     *  1. Wait until the hardware is ready.
+     *  2. Enable/disable interrupt that signals completion -- we don't use the interrupt.
+     *  3. Write the number of words required to represent the operands to the
+     *     RSA_MODE_REG (now called RSA_LENGTH_REG).
+     *  4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG).
+     *  5. Load X, Y, M, r' operands to memory blocks.
+     *  6. Start the operation by writing 1 to RSA_MOD_MULT_START_REG, then wait for it
+     *     to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG).
+     *  7. Read the result out.
+     *  8. Release the hardware lock so others can use it.
+     *  x. Clear the interrupt flag, if you used it (we don't). */
+
+    /* 1. Wait until hardware is ready. */
+    if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
+        return ret;
     }
-    /*Steps to use hw in the following order:
-    * 1. wait until clean hw engine
+
+    /* 2. Disable completion interrupt signal; we don't use. */
+    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion.
+
+    /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */
+    OperandBits = max(max(Xs, Ys), Ms);
+    if (OperandBits > ESP_HW_MULTI_RSAMAX_BITS) {
+        ESP_LOGW(TAG, "result exceeds max bit length");
+        return MP_VAL; /*  Error: value is not able to be used. */
+    }
+    WordsForOperand = bits2words(OperandBits);
+    DPORT_REG_WRITE(RSA_LENGTH_REG, WordsForOperand - 1);
+
+    /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */
+    DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
+
+    /* Select acceleration options. */
+    DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
+
+    /* 5. Load X, Y, M, r' operands.
+     * Note RSA_MEM_RB_BLOCK_BASE == RSA_MEM_Z_BLOC_BASE on ESP32s3*/
+    esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_RB_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv), hwWords_sz);
+
+    /* 6. Start operation and wait until it completes. */
+    process_start(RSA_MOD_MULT_START_REG);
+    ret = wait_until_done(RSA_QUERY_INTERRUPT_REG);
+    if (MP_OKAY != ret) {
+        return ret;
+    }
+
+    /* 7. read the result form MEM_Z              */
+    esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords);
+
+    /* 8. clear and release HW                    */
+    esp_mp_hw_unlock();
+
+    if (negcheck) {
+        mp_sub(M, &tmpZ, &tmpZ);
+    }
+
+    mp_copy(&tmpZ, Z);
+    mp_clear(&tmpZ);
+    mp_clear(&r_inv);
+
+    return ret;
+    /* end if CONFIG_IDF_TARGET_ESP32S3 */
+#else
+    /* non-S3 Xtensa */
+
+    /*Steps to use HW in the following order:
+    * 1. wait until clean HW engine
     * 2. Write(N/512bits - 1) to MULT_MODE_REG
     * 3. Write X,M(=G, X, P) to memory blocks
     *    need to write data to each memory block only according to the length
@@ -449,10 +663,10 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
     * 10. Wait for the second operation to be completed. Poll INTERRUPT_REG until it reads 1.
     * 11. Read the Z from RSA_Z_MEM
     * 12. Write 1 to RSA_INTERUPT_REG to clear the interrupt.
-    * 13. Release the hw engine
+    * 13. Release the HW engine
     */
 
-    if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
+    if ( (ret = esp_mp_hw_wait_clean()) != MP_OKAY ) {
         return ret;
     }
     /* step.1                     512 bits => 16 words */
@@ -468,6 +682,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
 
     /* step.3 write M' into memory                   */
     DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
+
     /* step.4 start process                           */
     process_start(RSA_MULT_START_REG);
 
@@ -485,7 +700,7 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
     /* step.12 read the result from MEM_Z             */
     esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, &tmpZ, zwords);
 
-    /* step.13 clear and release hw                   */
+    /* step.13 clear and release HW                   */
     esp_mp_hw_unlock();
 
     /* additional steps                               */
@@ -504,23 +719,25 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z)
     mp_clear(&r_inv);
 
     return ret;
+#endif
 }
 
 /* Large Number Modular Exponentiation
  *
  *    Z = X^Y mod M
  *
- * See Chapter 24:
- *  https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
- *
+ * See:
+ *  ESP32, Chapter 24, https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
+ *  ESP32s3, section 20.3.1, https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf
  * The operation is based on Montgomery multiplication. Aside from the
  * arguments X, Y , and M, two additional ones are needed —r and M′
 .* These arguments are calculated in advance by software.
 .*
 .* The RSA Accelerator supports operand lengths of N ∈ {512, 1024, 1536, 2048,
-.* 2560, 3072, 3584, 4096} bits. The bit length of arguments Z, X, Y , M,
-.* and r can be any one from the N set, but all numbers in a calculation must
-.* be of the same length. The bit length of M′ is always 32.
+.* 2560, 3072, 3584, 4096} bits on the ESP32 and N ∈ [32, 4096] bits on the ESP32s3.
+.* The bit length of arguments Z, X, Y , M, and r can be any one from the N set,
+.* but all numbers in a calculation must be of the same length.
+.* The bit length of M′ is always 32.
 .*
 .* Note some DH references may use: Y = (G ^ X) mod P
  */
@@ -536,41 +753,111 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, word32 Ys, MATH_INT_T* M, MATH_
     MATH_INT_T r_inv;
     mp_digit mp;
 
+#if CONFIG_IDF_TARGET_ESP32S3
+    uint32_t OperandBits;
+    uint32_t WordsForOperand;
+#endif
+
     /* ask bits number */
     Xs = mp_count_bits(X);
     Ms = mp_count_bits(M);
-    /* maximum bits and words for writing to hw */
+    /* maximum bits and words for writing to HW */
     maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
     hwWords_sz  = words2hwords(maxWords_sz);
 
     if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
-        ESP_LOGE(TAG, "exceeds hw maximum bits");
-        return -2;
+        ESP_LOGE(TAG, "exceeds HW maximum bits");
+        return MP_VAL; /*  Error: value is not able to be used. */
     }
     /* calculate r_inv = R^2 mode M
     *    where: R = b^n, and b = 2^32
     *    accordingly R^2 = 2^(n*32*2)
     */
     ret = mp_init(&r_inv);
-    if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
+    if ( (ret == 0) &&
+         ((ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) ) {
         ESP_LOGE(TAG, "calculate r_inv failed.");
         mp_clear(&r_inv);
         return ret;
     }
-    /* lock and init the hw                           */
-    if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
+    /* lock and init the HW                           */
+    if ( (ret = esp_mp_hw_lock()) != MP_OKAY ) {
         mp_clear(&r_inv);
         return ret;
     }
     /* calc M' */
     /* if Pm is odd, uses mp_montgomery_setup() */
-    if ((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
+    if ( (ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY ) {
         ESP_LOGE(TAG, "failed to calculate M dash");
         mp_clear(&r_inv);
-        return -1;
+        return ret;
+    }
+
+#if CONFIG_IDF_TARGET_ESP32S3
+    /* Steps to perform large number modular exponentiation. Calculates Z = (X ^ Y) modulo M.
+     * The number of bits in the operands (X, Y) is N. N can be 32x, where x = {1,2,3,...64}, so the
+     * maximum number of bits in the X and Y is 2048.
+     * See 20.3.3 of ESP32-S3 technical manual
+     *  1. Wait until the hardware is ready.
+     *  2. Enable/disable interrupt that signals completion -- we don't use the interrupt.
+     *  3. Write (N_bits/32 - 1) to the RSA_MODE_REG (now called RSA_LENGTH_REG).
+     *     Here N_bits is the maximum number of bits in X, Y and M.
+     *  4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG).
+     *  5. Load X, Y, M, r' operands to memory blocks.
+     *  6. Start the operation by writing 1 to RSA_MODEXP_START_REG, then wait for it
+     *     to complete by monitoring RSA_IDLE_REG (which is now called RSA_QUERY_INTERRUPT_REG).
+     *  7. Read the result out.
+     *  8. Release the hardware lock so others can use it.
+     *  x. Clear the interrupt flag, if you used it (we don't). */
+
+    /* 1. Wait until hardware is ready. */
+    if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
+        return ret;
+    }
+
+    /* 2. Disable completion interrupt signal; we don't use. */
+    DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0); // 0 => no interrupt; 1 => interrupt on completion.
+
+    /* 3. Write (N_result_bits/32 - 1) to the RSA_MODE_REG. */
+    OperandBits = max(max(Xs, Ys), Ms);
+    if (OperandBits > ESP_HW_MULTI_RSAMAX_BITS) {
+        ESP_LOGW(TAG, "result exceeds max bit length");
+        return MP_VAL; /*  Error: value is not able to be used. */
     }
+    WordsForOperand = bits2words(OperandBits);
+    DPORT_REG_WRITE(RSA_LENGTH_REG, WordsForOperand - 1);
 
-    /*Steps to use hw in the following order:
+    /* 4. Write M' value into RSA_M_PRIME_REG (now called RSA_M_DASH_REG) */
+    DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
+
+    /* 5. Load X, Y, M, r' operands. */
+    esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
+    esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv,
+                          mp_count_bits(&r_inv), hwWords_sz);
+
+    /* 6. Start operation and wait until it completes. */
+    process_start(RSA_MODEXP_START_REG);
+    ret = wait_until_done(RSA_QUERY_INTERRUPT_REG);
+    if (MP_OKAY != ret) {
+        return ret;
+    }
+
+    /* 7. read the result form MEM_Z              */
+    esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms));
+
+    /* 8. clear and release HW                    */
+    esp_mp_hw_unlock();
+
+    mp_clear(&r_inv);
+
+    return ret;
+    /* end if CONFIG_IDF_TARGET_ESP32S3 */
+#else
+    /* non-ESP32S3 Xtensa (regular ESP32) */
+
+    /* Steps to use HW in the following order:
     * 1. Write(N/512bits - 1) to MODEXP_MODE_REG
     * 2. Write X, Y, M and r_inv to memory blocks
     *    need to write data to each memory block only according to the length
@@ -605,12 +892,13 @@ int esp_mp_exptmod(MATH_INT_T* X, MATH_INT_T* Y, word32 Ys, MATH_INT_T* M, MATH_
     wait_until_done(RSA_INTERRUPT_REG);
     /* step.6 read a result form memory               */
     esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Ms));
-    /* step.7 clear and release hw                    */
+    /* step.7 clear and release HW                    */
     esp_mp_hw_unlock();
 
     mp_clear(&r_inv);
 
     return ret;
+#endif
 }
 
 #endif /* WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) &&

File diff suppressed because it is too large
+ 752 - 138
wolfcrypt/src/port/Espressif/esp32_sha.c


+ 242 - 10
wolfcrypt/src/port/Espressif/esp32_util.c

@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  */
 #include <wolfssl/wolfcrypt/settings.h>
+#include <wolfssl/version.h>
 
 #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
   (!defined(NO_AES)        || !defined(NO_SHA) || !defined(NO_SHA256) ||\
@@ -27,6 +28,8 @@
 #include <wolfssl/wolfcrypt/wc_port.h>
 #include <wolfssl/wolfcrypt/error-crypt.h>
 #include <wolfssl/wolfcrypt/logging.h>
+
+
 /*
  * initialize our mutex used to lock hardware access
  *
@@ -79,25 +82,254 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) {
 #endif
 }
 
+/*
+** Version / Platform info.
+**
+** This could evolve into a wolfSSL-wide feature. For now, here only. See:
+** https://github.com/wolfSSL/wolfssl/pull/6149
+*/
+#if defined(WOLFSSL_ESPIDF)
+    #include <esp_log.h>
+    #include "sdkconfig.h"
+    const char* TAG = "Version Info";
+    #define WOLFSSL_VERSION_PRINTF(...) ESP_LOGI(TAG, __VA_ARGS__)
+#else
+    #include <stdio.h>
+    #define WOLFSSL_VERSION_PRINTF(...) { printf(__VA_ARGS__); printf("\n"); }
+#endif
+
+/*
+*******************************************************************************
+** Specific Platforms
+*******************************************************************************
+*/
+
+/*
+** Specific platforms: Espressif
+*/
+#if defined(WOLFSSL_ESPIDF)
+static int ShowExtendedSystemInfo_platform_espressif()
+{
+#if defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ)
+    WOLFSSL_VERSION_PRINTF("CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ: %u MHz",
+                           CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
+#endif
+
+#if CONFIG_IDF_TARGET_ESP32
+
+    WOLFSSL_VERSION_PRINTF("Xthal_have_ccount: %u",
+                           Xthal_have_ccount);
+
+    /* this is the legacy stack size */
+#if defined(CONFIG_MAIN_TASK_STACK_SIZE)
+    WOLFSSL_VERSION_PRINTF("CONFIG_MAIN_TASK_STACK_SIZE: %d",
+                           CONFIG_MAIN_TASK_STACK_SIZE);
+#endif
+
+    /* this is the modern stack size */
+#if defined(CONFIG_ESP_MAIN_TASK_STACK_SIZE)
+    WOLFSSL_VERSION_PRINTF("CONFIG_ESP_MAIN_TASK_STACK_SIZE: %d",
+                           CONFIG_ESP_MAIN_TASK_STACK_SIZE);
+#endif
+
+#if defined(CONFIG_TIMER_TASK_STACK_SIZE)
+    WOLFSSL_VERSION_PRINTF("CONFIG_TIMER_TASK_STACK_SIZE: %d",
+                           CONFIG_TIMER_TASK_STACK_SIZE);
+#endif
+
+#if defined(CONFIG_TIMER_TASK_STACK_DEPTH)
+    WOLFSSL_VERSION_PRINTF("CONFIG_TIMER_TASK_STACK_DEPTH: %d",
+                           CONFIG_TIMER_TASK_STACK_DEPTH);
+#endif
+
+#if defined(SINGLE_THREADED)
+    /* see also HAVE_STACK_SIZE_VERBOSE */
+    char thisHWM = 0;
+    WOLFSSL_VERSION_PRINTF("Stack HWM: %x", (size_t) &thisHWM);
+#else
+    WOLFSSL_VERSION_PRINTF("Stack HWM: %d",
+                           uxTaskGetStackHighWaterMark(NULL));
+#endif
+
+#elif CONFIG_IDF_TARGET_ESP32S2
+    WOLFSSL_VERSION_PRINTF("Xthal_have_ccount = %u",
+                           Xthal_have_ccount);
+#elif CONFIG_IDF_TARGET_ESP32C6
+    /* not supported at this time */
+#elif CONFIG_IDF_TARGET_ESP32C3
+    /* not supported at this time */
+#elif CONFIG_IDF_TARGET_ESP32S3
+    WOLFSSL_VERSION_PRINTF("Xthal_have_ccount = %u",
+                           Xthal_have_ccount);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    /* not supported at this time */
+#elif CONFIG_IDF_TARGET_ESP32C2
+    /* not supported at this time */
+#else
+    /* not supported at this time */
+#endif
+
+    /* check to see if we are using hardware encryption */
+#if defined(NO_ESP32WROOM32_CRYPT)
+    WOLFSSL_VERSION_PRINTF("NO_ESP32WROOM32_CRYPT defined! "
+                           "HW acceleration DISABLED.");
+#else
+    /* first show what platform hardware acceleration is enabled
+    ** (some new platforms may not be supported yet) */
+#if defined(CONFIG_IDF_TARGET_ESP32)
+    WOLFSSL_VERSION_PRINTF("ESP32WROOM32_CRYPT is enabled for ESP32.");
+#elif defined(CONFIG_IDF_TARGET_ESP32S2)
+    WOLFSSL_VERSION_PRINTF("ESP32WROOM32_CRYPT is enabled for ESP32-S2.");
+#elif defined(CONFIG_IDF_TARGET_ESP32S3)
+    WOLFSSL_VERSION_PRINTF("ESP32WROOM32_CRYPT is enabled for ESP32-S3.");
+#else
+#error "ESP32WROOM32_CRYPT not yet supported on this IDF TARGET"
+#endif
+
+    /* Even though enabled, some specifics may be disabled */
+#if defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH is defined!"
+                           "(disabled HW SHA).");
+#endif
+
+#if defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+    WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32WROOM32_CRYPT_AES is defined!"
+                           "(disabled HW AES).");
+#endif
+
+#if defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI)
+    WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI defined!"
+                           "(disabled HW RSA)");
+#endif
+#endif
+
+    return 0;
+}
+#endif
+
+/*
+*******************************************************************************
+** All Platforms
+*******************************************************************************
+*/
+
+/*
+** All platforms: git details
+*/
+static int ShowExtendedSystemInfo_git()
+{
+#if defined(HAVE_WC_INTROSPECTION) && !defined(ALLOW_BINARY_MISMATCH_INTROSPECTION)
+#pragma message("WARNING: both HAVE_VERSION_EXTENDED_INFO and " \
+                "HAVE_WC_INTROSPECTION are enabled. Some extended " \
+                "information details will not be available.")
+
+    WOLFSSL_VERSION_PRINTF("HAVE_WC_INTROSPECTION enabled. "
+                           "Some extended system details not available.");
+#else
+    /* Display some interesting git values that may change,
+    ** but not desired for introspection which requires object code to be
+    ** maximally bitwise-invariant.
+    */
+#if defined(LIBWOLFSSL_VERSION_GIT_ORIGIN)
+        /* git config --get remote.origin.url */
+    WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_ORIGIN = %s",
+                           LIBWOLFSSL_VERSION_GIT_ORIGIN);
 #endif
 
-#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
+#if defined(LIBWOLFSSL_VERSION_GIT_BRANCH)
+    /* git rev-parse --abbrev-ref HEAD */
+    WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_BRANCH = %s",
+                           LIBWOLFSSL_VERSION_GIT_BRANCH);
+#endif
 
-#include "esp_timer.h"
-#include "esp_log.h"
+#if defined(LIBWOLFSSL_VERSION_GIT_HASH)
+    WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_HASH = %s",
+                           LIBWOLFSSL_VERSION_GIT_HASH);
+#endif
 
-static uint64_t startTime = 0;
+#if defined(LIBWOLFSSL_VERSION_GIT_SHORT_HASH )
+    WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_SHORT_HASH = %s",
+                           LIBWOLFSSL_VERSION_GIT_SHORT_HASH);
+#endif
 
+#if defined(LIBWOLFSSL_VERSION_GIT_HASH_DATE)
+    WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_GIT_HASH_DATE = %s",
+                           LIBWOLFSSL_VERSION_GIT_HASH_DATE);
+#endif
 
-void wc_esp32TimerStart()
+#endif /* else not HAVE_WC_INTROSPECTION */
+    return 0;
+}
+
+/*
+** All platforms: thread details
+*/
+static int ShowExtendedSystemInfo_thread()
 {
-    startTime = esp_timer_get_time();
+    /* all platforms: stack high water mark check */
+#if defined(SINGLE_THREADED)
+    WOLFSSL_VERSION_PRINTF("SINGLE_THREADED");
+#else
+    WOLFSSL_VERSION_PRINTF("NOT SINGLE_THREADED");
+#endif
+    return 0;
 }
 
-uint64_t  wc_esp32elapsedTime()
+/*
+** All Platforms: platform details
+*/
+static int ShowExtendedSystemInfo_platform()
 {
-    /* return elapsed time since wc_esp32AesTimeStart() is called in us */
-    return esp_timer_get_time() - startTime;
+#if defined(WOLFSSL_ESPIDF)
+#if defined(CONFIG_IDF_TARGET)
+    WOLFSSL_VERSION_PRINTF("CONFIG_IDF_TARGET = %s",
+                           CONFIG_IDF_TARGET);
+    ShowExtendedSystemInfo_platform_espressif();
+#endif
+#endif
+    return 0;
+}
+
+/*
+*******************************************************************************
+** The public ShowExtendedSystemInfo()
+*******************************************************************************
+*/
+
+int ShowExtendedSystemInfo(void)
+    {
+        WOLFSSL_VERSION_PRINTF("Extended Version and Platform Information.");
+
+#if defined(LIBWOLFSSL_VERSION_STRING)
+        WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_STRING = %s",
+                               LIBWOLFSSL_VERSION_STRING);
+#endif
+
+#if defined(LIBWOLFSSL_VERSION_HEX)
+        WOLFSSL_VERSION_PRINTF("LIBWOLFSSL_VERSION_HEX = %x",
+                               LIBWOLFSSL_VERSION_HEX);
+#endif
+
+#if defined(WOLFSSL_MULTI_INSTALL_WARNING)
+        /* CMake may have detected undesired multiple installs, so give warning. */
+        WOLFSSL_VERSION_PRINTF("");
+        WOLFSSL_VERSION_PRINTF("WARNING: Multiple wolfSSL installs found.");
+        WOLFSSL_VERSION_PRINTF("Check ESP-IDF and local project [components] directory.");
+        WOLFSSL_VERSION_PRINTF("");
+#endif
+
+        ShowExtendedSystemInfo_git(); /* may be limited during active introspection */
+        ShowExtendedSystemInfo_platform();
+        ShowExtendedSystemInfo_thread();
+        return 0;
+    }
+
+
+
+int esp_ShowExtendedSystemInfo()
+{
+    return ShowExtendedSystemInfo();
 }
 
-#endif /*WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */
+#endif
+

+ 137 - 73
wolfcrypt/src/sha.c

@@ -26,6 +26,14 @@
 
 #include <wolfssl/wolfcrypt/settings.h>
 
+#ifdef DEBUG_WOLFSSL_VERBOSE
+    #if defined(WOLFSSL_ESPIDF)
+        #include <esp_log.h>
+    #else
+        #include <wolfssl/wolfcrypt/logging.h>
+    #endif
+#endif
+
 #if !defined(NO_SHA)
 
 #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
@@ -50,6 +58,29 @@
 #include <wolfssl/wolfcrypt/port/caam/wolfcaam_fsl_nxp.h>
 #endif
 
+#undef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    /* define a single keyword for simplicity & readability
+     *
+     * by default the HW acceleration is on for ESP32-WROOM32
+     * but individual components can be turned off.
+     */
+    #define WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+    #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+
+    /* Although we have hardware acceleration,
+    ** we may need to fall back to software */
+    #define USE_SHA_SOFTWARE_IMPL
+    static const char* TAG = "wc_sha";
+#elif defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW)
+    /* The ESP32C3 is different; HW crypto here. Not yet implemented.
+    ** We'll be using software for RISC-V at this time */
+    static const char* TAG = "wc_sha-c3";
+#else
+    #undef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+#endif
+
 /* fips wrapper calls, user can call direct */
 #if defined(HAVE_FIPS) && \
     (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
@@ -290,13 +321,11 @@
     !defined(WOLFSSL_QNX_CAAM)
     /* wolfcrypt/src/port/caam/caam_sha.c */
 
-#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-     !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-
-    #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
-
-    #define USE_SHA_SOFTWARE_IMPL
+#elif defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW) || \
+      defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW)
 
+    /* This function initializes SHA.
+    ** This is automatically called by wc_ShaHash */
     static int InitSha(wc_Sha* sha)
     {
         int ret = 0;
@@ -311,19 +340,10 @@
         sha->loLen   = 0;
         sha->hiLen   = 0;
 
-        /* always start firstblock = 1 when using hw engine */
-        sha->ctx.isfirstblock = 1;
-        sha->ctx.sha_type = SHA1;
-        if(sha->ctx.mode == ESP32_SHA_HW){
-            sha->ctx.lockDepth = 0;
-            /* release hw engine */
-            esp_sha_hw_unlock(&(sha->ctx));
-        }
-        /* always set mode as INIT
-        *  whether using HW or SW is determined at first call of update()
-        */
-        sha->ctx.mode = ESP32_SHA_INIT;
-        sha->ctx.lockDepth = 0;
+        /* HW needs to be carefully initialized, taking into account soft copy.
+        ** If already in use; copy may revert to SW as needed. */
+        ret = esp_sha_init(&(sha->ctx), WC_HASH_TYPE_SHA);
+
         return ret;
     }
 
@@ -526,15 +546,20 @@ static WC_INLINE void AddLength(wc_Sha* sha, word32 len)
 
         return 0;
     }
-#endif /* !USE_CUSTOM_SHA_TRANSFORM */
+#endif /* XTRANSFORM when USE_SHA_SOFTWARE_IMPL is enabled */
 
 
+/*
+** wolfCrypt InitSha256 external wrapper.
+**
+** we'll assume this is ALWAYS for a new, uninitialized sha256
+*/
 int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
 {
     int ret = 0;
-
-    if (sha == NULL)
+    if (sha == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     sha->heap = heap;
 #ifdef WOLF_CRYPTO_CB
@@ -542,28 +567,32 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
     sha->devCtx = NULL;
 #endif
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+#ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+    if (sha->ctx.mode != ESP32_SHA_INIT) {
+        /* it may be interesting to see old values during debugging */
+        ESP_LOGV(TAG, "Set ctx mode from prior value: %d", sha->ctx.mode);
+    }
+    /* We know this is a fresh, uninitialized item, so set to INIT */
     sha->ctx.mode = ESP32_SHA_INIT;
-    sha->ctx.isfirstblock = 1;
-    sha->ctx.lockDepth = 0; /* keep track of how many times lock is called */
 #endif
+
     ret = InitSha(sha);
-    if (ret != 0)
+    if (ret != 0) {
         return ret;
+    }
 
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
     ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA,
                                                             sha->heap, devId);
 #else
     (void)devId;
-#endif /* WOLFSSL_ASYNC_CRYPT */
+# endif /* WOLFSSL_ASYNC_CRYPT */
 #ifdef WOLFSSL_IMXRT1170_CAAM
    ret = wc_CAAM_HashInit(&sha->hndl, &sha->ctx, WC_HASH_TYPE_SHA);
 #endif
 
     return ret;
-}
+} /* wc_InitSha_ex */
 
 /* do block size increments/updates */
 int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
@@ -599,8 +628,9 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
 #endif /* WOLFSSL_ASYNC_CRYPT */
 
     /* check that internal buffLen is valid */
-    if (sha->buffLen >= WC_SHA_BLOCK_SIZE)
+    if (sha->buffLen >= WC_SHA_BLOCK_SIZE) {
         return BUFFER_E;
+    }
 
     /* add length for final */
     AddLength(sha, len);
@@ -621,26 +651,32 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
             ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
         #endif
 
-        #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-            !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+        #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
             if (sha->ctx.mode == ESP32_SHA_INIT) {
+                ESP_LOGV(TAG, "wc_ShaUpdate try hardware");
                 esp_sha_try_hw_lock(&sha->ctx);
             }
             if (sha->ctx.mode == ESP32_SHA_SW) {
+                ESP_LOGI(TAG, "wc_ShaUpdate process software");
                 ret = XTRANSFORM(sha, (const byte*)local);
             }
             else {
+                ESP_LOGV(TAG, "wc_ShaUpdate process hardware");
                 esp_sha_process(sha, (const byte*)local);
             }
+        #elif defined (WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW)
+            ESP_LOGI(TAG, "wc_ShaUpdate not implemented for ESP32C3");
+            ret = XTRANSFORM(sha, (const byte*)local);
         #else
             ret = XTRANSFORM(sha, (const byte*)local);
         #endif
-            if (ret != 0)
+            if (ret != 0) {
                 return ret;
+            }
 
-            sha->buffLen = 0;
-        }
-    }
+            sha->buffLen = 0; /* Nothing left to do, so set to zero. */
+        } /* (sha->buffLen == WC_SHA_BLOCK_SIZE) */
+    } /* (sha->buffLen > 0)  Process any remainder from previous operation. */
 
     /* process blocks */
 #ifdef XTRANSFORM_LEN
@@ -676,8 +712,7 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
         ByteReverseWords(local32, local32, WC_SHA_BLOCK_SIZE);
     #endif
 
-    #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
         if (sha->ctx.mode == ESP32_SHA_INIT){
             esp_sha_try_hw_lock(&sha->ctx);
         }
@@ -722,6 +757,10 @@ int wc_ShaFinalRaw(wc_Sha* sha, byte* hash)
     return 0;
 }
 
+/*
+** Finalizes hashing of data. Result is placed into hash.
+** Resets state of sha struct.
+*/
 int wc_ShaFinal(wc_Sha* sha, byte* hash)
 {
     int ret;
@@ -749,6 +788,13 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
     }
 #endif /* WOLFSSL_ASYNC_CRYPT */
 
+    /* we'll add a 0x80 byte at the end,
+    ** so make sure we have appropriate buffer length. */
+    if (sha->buffLen > WC_SHA_BLOCK_SIZE - 1) {
+        /* exit with error code if there's a bad buffer size in buffLen */
+        return BAD_STATE_E;
+    } /* buffLen check */
+
     local[sha->buffLen++] = 0x80;  /* add 1 */
 
     /* pad with zeros */
@@ -760,11 +806,13 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
         ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE);
     #endif
 
-    #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-        !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        /* For a fresh sha.ctx, try to use hardware acceleration */
         if (sha->ctx.mode == ESP32_SHA_INIT) {
             esp_sha_try_hw_lock(&sha->ctx);
         }
+
+        /* if HW was busy, we may need to fall back to SW. */
         if (sha->ctx.mode == ESP32_SHA_SW) {
             ret = XTRANSFORM(sha, (const byte*)local);
         }
@@ -772,13 +820,19 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
             ret = esp_sha_process(sha, (const byte*)local);
         }
     #else
+        /*
+        ** The #if defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW) also falls
+        ** though here to SW, as it's not yet implemented for HW.
+        */
         ret = XTRANSFORM(sha, (const byte*)local);
     #endif
-        if (ret != 0)
+        if (ret != 0) {
             return ret;
+        }
 
         sha->buffLen = 0;
-    }
+    } /*  (sha->buffLen > WC_SHA_PAD_SIZE) */
+
     XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen);
 
 #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA)
@@ -801,8 +855,7 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
                      2 * sizeof(word32));
 #endif
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
     if (sha->ctx.mode == ESP32_SHA_INIT) {
         esp_sha_try_hw_lock(&sha->ctx);
     }
@@ -812,6 +865,10 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
     else {
         ret = esp_sha_digest_process(sha, 1);
     }
+/*
+** The #if defined(WOLFSSL_USE_ESP32C3_CRYPT_HASH_HW) also falls
+** though here to SW, as it's not yet implemented for HW.
+*/
 #else
     ret = XTRANSFORM(sha, (const byte*)local);
 #endif
@@ -822,7 +879,7 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
 
     XMEMCPY(hash, (byte *)&sha->digest[0], WC_SHA_DIGEST_SIZE);
 
-    (void)InitSha(sha); /* reset state */
+    ret = InitSha(sha); /* reset state */
 
     return ret;
 }
@@ -844,12 +901,15 @@ int wc_ShaTransform(wc_Sha* sha, const unsigned char* data)
 
 #endif /* USE_SHA_SOFTWARE_IMPL */
 
-
+/*
+** This function initializes SHA. This is automatically called by wc_ShaHash.
+*/
 int wc_InitSha(wc_Sha* sha)
 {
     return wc_InitSha_ex(sha, NULL, INVALID_DEVID);
 }
 
+
 #if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)
 
 void wc_ShaFree(wc_Sha* sha)
@@ -882,7 +942,7 @@ void wc_ShaFree(wc_Sha* sha)
 
 #endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */
 #endif /* !WOLFSSL_TI_HASH */
-#endif /* HAVE_FIPS */
+#endif /* !HAVE_FIPS ... */
 
 #if !defined(WOLFSSL_TI_HASH) && !defined(WOLFSSL_IMXRT_DCP)
 
@@ -891,36 +951,38 @@ void wc_ShaFree(wc_Sha* sha)
 #if !defined(WOLFSSL_RENESAS_RX64_HASH)
 
 #if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)
+
+/* wc_ShaGetHash get hash value */
 int wc_ShaGetHash(wc_Sha* sha, byte* hash)
 {
     int ret;
-    wc_Sha tmpSha;
+#ifdef WOLFSSL_SMALL_STACK
+    wc_Sha* tmpSha;
+#else
+    wc_Sha  tmpSha[1];
+#endif
 
-    if (sha == NULL || hash == NULL)
+    if (sha == NULL || hash == NULL) {
         return BAD_FUNC_ARG;
-
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    if(sha->ctx.mode == ESP32_SHA_INIT){
-        esp_sha_try_hw_lock(&sha->ctx);
     }
-    if (sha->ctx.mode != ESP32_SHA_SW) {
-        /* TODO check SW/HW logic */
-        esp_sha_digest_process(sha, 0);
+
+#ifdef WOLFSSL_SMALL_STACK
+    tmpSha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL,
+        DYNAMIC_TYPE_TMP_BUFFER);
+    if (tmpSha == NULL) {
+        return MEMORY_E;
     }
 #endif
 
-    ret = wc_ShaCopy(sha, &tmpSha);
+    ret = wc_ShaCopy(sha, tmpSha);
     if (ret == 0) {
-        /* if HW failed, use SW */
-        ret = wc_ShaFinal(&tmpSha, hash);
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-        sha->ctx.mode = ESP32_SHA_SW;
-#endif
+        ret = wc_ShaFinal(tmpSha, hash);
+    }
 
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmpSha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
 
-    }
     return ret;
 }
 
@@ -941,27 +1003,29 @@ int wc_ShaCopy(wc_Sha* src, wc_Sha* dst)
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA)
     ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
 #endif
+
 #ifdef WOLFSSL_PIC32MZ_HASH
     ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
 #endif
+
 #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
     ret = se050_hash_copy(&src->se050Ctx, &dst->se050Ctx);
 #endif
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-     dst->ctx.mode = src->ctx.mode;
-     dst->ctx.isfirstblock = src->ctx.isfirstblock;
-     dst->ctx.sha_type = src->ctx.sha_type;
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    esp_sha_ctx_copy(src, dst);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
-     dst->flags |= WC_HASH_FLAG_ISCOPY;
+    dst->flags |= WC_HASH_FLAG_ISCOPY;
 #endif
     return ret;
 }
 #endif /* WOLFSSL_RENESAS_RX64_HASH */
-#endif /* defined(WOLFSSL_RENESAS_TSIP_CRYPT) ... */
-#endif /* !WOLFSSL_TI_HASH && !WOLFSSL_IMXRT_DCP */
 #endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */
+#endif /* !defined(WOLFSSL_RENESAS_TSIP_CRYPT) ||
+          defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH) */
+#endif /* !defined(WOLFSSL_TI_HASH) && !defined(WOLFSSL_IMXRT_DCP) */
 
 #ifdef WOLFSSL_HASH_FLAGS
 int wc_ShaSetFlags(wc_Sha* sha, word32 flags)

+ 99 - 64
wolfcrypt/src/sha256.c

@@ -103,6 +103,14 @@ on the specific device platform.
     #undef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
 #endif
 
+#ifdef WOLFSSL_ESPIDF
+    /* Define the ESP_LOGx(TAG, "" value for output messages here.
+    **
+    ** Beware of possible conflict in test.c (that one now named TEST_TAG)
+    */
+    static const char* TAG = "wc_sha256";
+#endif
+
 /* fips wrapper calls, user can call direct */
 #if defined(HAVE_FIPS) && \
     (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
@@ -731,16 +739,16 @@ static int InitSha256(wc_Sha256* sha256)
     #define NEED_SOFT_SHA256
 
     /*
-     * soft SHA needs initialization digest, but HW does not.
-     */
+    ** soft SHA needs initialization digest, but HW does not.
+    */
     static int InitSha256(wc_Sha256* sha256)
     {
         int ret = 0; /* zero = success */
 
-        if (sha256 == NULL)
+        if (sha256 == NULL) {
             return BAD_FUNC_ARG;
+        }
 
-        XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
         sha256->digest[0] = 0x6A09E667L;
         sha256->digest[1] = 0xBB67AE85L;
         sha256->digest[2] = 0x3C6EF372L;
@@ -754,41 +762,33 @@ static int InitSha256(wc_Sha256* sha256)
         sha256->loLen   = 0;
         sha256->hiLen   = 0;
 
-        /* always start firstblock = 1 when using hw engine */
-        sha256->ctx.isfirstblock = 1;
-        sha256->ctx.sha_type = SHA2_256;
-        if(sha256->ctx.mode == ESP32_SHA_HW) {
-            /* release hw */
-            esp_sha_hw_unlock(&(sha256->ctx));
-        }
-
-        /* always set mode as INIT
-        *  whether using HW or SW is determined at first call of update()
-        */
-        sha256->ctx.mode = ESP32_SHA_INIT;
+        ret = esp_sha_init(&(sha256->ctx), WC_HASH_TYPE_SHA256);
 
         return ret;
     }
 
     /*
-     * wolfCrypt InitSha256 external wrapper
-     */
+    ** wolfCrypt InitSha256 external wrapper.
+    **
+    ** we'll assume this is ALWAYS for a new, uninitialized sha256
+    */
     int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
     {
-        int ret = 0; /* zero = success */
-
-        if (sha256 == NULL)
+        (void)devId;
+        if (sha256 == NULL) {
             return BAD_FUNC_ARG;
+        }
 
-        XMEMSET(sha256, 0, sizeof(wc_Sha256));
+    #ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+        /* We know this is a fresh, uninitialized item, so set to INIT */
+        if (sha256->ctx.mode != ESP32_SHA_INIT) {
+            ESP_LOGV(TAG, "Set ctx mode from prior value: "
+                               "%d", sha256->ctx.mode);
+        }
         sha256->ctx.mode = ESP32_SHA_INIT;
-        sha256->ctx.isfirstblock = 1;
-        sha256->ctx.lockDepth = 0; /* we'll keep track of our own lock depth */
-        (void)devId;
-
-        ret = InitSha256(sha256);
+    #endif
 
-        return ret;
+        return InitSha256(sha256);
     }
 
 #elif defined(WOLFSSL_RENESAS_TSIP_CRYPT) && \
@@ -1100,15 +1100,17 @@ static int InitSha256(wc_Sha256* sha256)
             #endif
 
             #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
-                if (sha256->ctx.mode == ESP32_SHA_INIT ||
-                    sha256->ctx.mode == ESP32_SHA_FAIL_NEED_UNROLL) {
+                if (sha256->ctx.mode == ESP32_SHA_INIT) {
+                    ESP_LOGV(TAG, "Sha256Update try hardware");
                     esp_sha_try_hw_lock(&sha256->ctx);
                 }
 
                 if (sha256->ctx.mode == ESP32_SHA_SW) {
+                    ESP_LOGV(TAG, "Sha256Update process software");
                     ret = XTRANSFORM(sha256, (const byte*)local);
                 }
                 else {
+                    ESP_LOGV(TAG, "Sha256Update process hardware");
                     esp_sha256_process(sha256, (const byte*)local);
                 }
             #else
@@ -1183,15 +1185,18 @@ static int InitSha256(wc_Sha256* sha256)
 
             #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
                 if (sha256->ctx.mode == ESP32_SHA_INIT){
+                    ESP_LOGV(TAG, "Sha256Update try hardware loop");
                     esp_sha_try_hw_lock(&sha256->ctx);
                 }
                 if (sha256->ctx.mode == ESP32_SHA_SW) {
+                    ESP_LOGV(TAG, "Sha256Update process software loop");
                     ret = XTRANSFORM(sha256, (const byte*)local32);
                 }
                 else {
+                    ESP_LOGV(TAG, "Sha256Update process hardware");
                     esp_sha256_process(sha256, (const byte*)local32);
                 }
-#else
+            #else
                 ret = XTRANSFORM(sha256, (const byte*)local32);
             #endif
 
@@ -1255,6 +1260,13 @@ static int InitSha256(wc_Sha256* sha256)
             return BAD_FUNC_ARG;
         }
 
+        /* we'll add a 0x80 byte at the end,
+        ** so make sure we have appropriate buffer length. */
+        if (sha256->buffLen > WC_SHA256_BLOCK_SIZE - 1) {
+            /* exit with error code if there's a bad buffer size in buffLen */
+            return BAD_STATE_E;
+        } /* buffLen check */
+
         local = (byte*)sha256->buffer;
         local[sha256->buffLen++] = 0x80; /* add 1 */
 
@@ -1400,8 +1412,9 @@ static int InitSha256(wc_Sha256* sha256)
     #endif /* WOLFSSL_ASYNC_CRYPT */
 
         ret = Sha256Final(sha256);
-        if (ret != 0)
+        if (ret != 0) {
             return ret;
+        }
 
     #if defined(LITTLE_ENDIAN_ORDER)
         ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE);
@@ -1572,6 +1585,10 @@ static int InitSha256(wc_Sha256* sha256)
         sha224->used = 0;
     #endif
 
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        /* not to be confused with HAS512_224 */
+        sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */
+    #endif
 
         return ret;
     }
@@ -1591,9 +1608,20 @@ static int InitSha256(wc_Sha256* sha256)
         sha224->W = NULL;
     #endif
 
+    #ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+        /* We know this is a fresh, uninitialized item, so set to INIT */
+        if (sha224->ctx.mode != ESP32_SHA_SW) {
+            ESP_LOGV(TAG, "Set sha224 ctx mode init to ESP32_SHA_SW. "
+                          "Prior value: %d", sha224->ctx.mode);
+        }
+        /* no sha224 HW support is available, set to SW */
+        sha224->ctx.mode = ESP32_SHA_SW;
+    #endif
+
         ret = InitSha224(sha224);
-        if (ret != 0)
+        if (ret != 0) {
             return ret;
+        }
 
     #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
         ret = wolfAsync_DevCtxInit(&sha224->asyncDev,
@@ -1604,6 +1632,16 @@ static int InitSha256(wc_Sha256* sha256)
 #ifdef WOLFSSL_IMXRT1170_CAAM
      ret = wc_CAAM_HashInit(&sha224->hndl, &sha224->ctx, WC_HASH_TYPE_SHA224);
 #endif
+
+    #ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+        if (sha224->ctx.mode != ESP32_SHA_INIT) {
+            ESP_LOGV("SHA224", "Set ctx mode from prior value: "
+                               "%d", sha224->ctx.mode);
+        }
+        /* We know this is a fresh, uninitialized item, so set to INIT */
+        sha224->ctx.mode = ESP32_SHA_INIT;
+    #endif
+
         return ret;
     }
 
@@ -1623,6 +1661,10 @@ static int InitSha256(wc_Sha256* sha256)
         }
     #endif /* WOLFSSL_ASYNC_CRYPT */
 
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */
+    #endif
+
         ret = Sha256Update((wc_Sha256*)sha224, data, len);
 
         return ret;
@@ -1645,6 +1687,10 @@ static int InitSha256(wc_Sha256* sha256)
         }
     #endif /* WOLFSSL_ASYNC_CRYPT */
 
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */
+    #endif
+
         ret = Sha256Final((wc_Sha256*)sha224);
         if (ret != 0)
             return ret;
@@ -1785,11 +1831,11 @@ void wc_Sha256Free(wc_Sha256* sha256)
          * the unexpected. by the time free is called, the hardware
          * should have already been released (lockDepth = 0)
          */
-        InitSha256(sha256); /* unlock mutex, set mode to ESP32_SHA_INIT */
-        ESP_LOGV("sha256", "Alert: hardware unlock needed in wc_Sha256Free.");
+        (void)InitSha256(sha256); /* unlock mutex, set mode to ESP32_SHA_INIT */
+        ESP_LOGV(TAG, "Alert: hardware unlock needed in wc_Sha256Free.");
     }
     else {
-        ESP_LOGV("sha256", "Hardware unlock not needed in wc_Sha256Free.");
+        ESP_LOGV(TAG, "Hardware unlock not needed in wc_Sha256Free.");
     }
 #endif
 }
@@ -1865,12 +1911,14 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz)
 
     int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
     {
-        int ret = 0;
+        int ret = 0; /* assume success unless proven otherwise */
 
-        if (src == NULL || dst == NULL)
+        if (src == NULL || dst == NULL) {
             return BAD_FUNC_ARG;
+        }
 
         XMEMCPY(dst, src, sizeof(wc_Sha224));
+
     #ifdef WOLFSSL_SMALL_STACK_CACHE
         dst->W = NULL;
     #endif
@@ -1883,9 +1931,15 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz)
     #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
         ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
     #endif
+
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        ret = esp_sha224_ctx_copy(src, dst);
+    #endif
+
     #ifdef WOLFSSL_HASH_FLAGS
         dst->flags |= WC_HASH_FLAG_ISCOPY;
     #endif
+
     #if defined(WOLFSSL_HASH_KEEP)
         if (src->msg != NULL) {
             dst->msg = (byte*)XMALLOC(src->len, dst->heap,
@@ -1972,32 +2026,13 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
     }
 #endif
 
-#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
-    /* ESP32 hardware can only handle only 1 active hardware hashing
-     * at a time. If the mutex lock is acquired the first time then
-     * that Sha256 instance has exclusive access to hardware. The
-     * final or free needs to release the mutex. Operations that
-     * do not get the lock fallback to software based Sha256 */
-
-    if (sha256->ctx.mode == ESP32_SHA_INIT) {
-        esp_sha_try_hw_lock(&sha256->ctx);
-    }
-    if (sha256->ctx.mode == ESP32_SHA_HW) {
-        esp_sha256_digest_process(sha256, 0);
-    }
-#endif
-
     ret = wc_Sha256Copy(sha256, tmpSha256);
     if (ret == 0) {
         ret = wc_Sha256Final(tmpSha256, hash);
-
-    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
-        sha256->ctx.mode = ESP32_SHA_SW;
-    #endif
-
-        wc_Sha256Free(tmpSha256);
+        wc_Sha256Free(tmpSha256); /* TODO move outside brackets? */
     }
 
+
 #ifdef WOLFSSL_SMALL_STACK
     XFREE(tmpSha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 #endif
@@ -2008,8 +2043,9 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
 {
     int ret = 0;
 
-    if (src == NULL || dst == NULL)
+    if (src == NULL || dst == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     XMEMCPY(dst, src, sizeof(wc_Sha256));
 
@@ -2029,20 +2065,19 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
     ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
 #endif
+
 #ifdef WOLFSSL_PIC32MZ_HASH
     ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
 #endif
 
 #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
-    dst->ctx.mode         = src->ctx.mode;
-    dst->ctx.isfirstblock = src->ctx.isfirstblock;
-    dst->ctx.sha_type     = src->ctx.sha_type;
-    dst->ctx.lockDepth    = src->ctx.lockDepth;
+    esp_sha256_ctx_copy(src, dst);
 #endif
 
 #ifdef WOLFSSL_HASH_FLAGS
      dst->flags |= WC_HASH_FLAG_ISCOPY;
 #endif
+
 #if defined(WOLFSSL_HASH_KEEP)
     if (src->msg != NULL) {
         dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);

+ 144 - 114
wolfcrypt/src/sha512.c

@@ -28,6 +28,21 @@
 
 #if (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_PSOC6_CRYPTO)
 
+/* determine if we are using Espressif SHA hardware acceleration */
+#undef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+    /* define a single keyword for simplicity & readability
+     *
+     * by default the HW acceleration is on for ESP32-WROOM32
+     * but individual components can be turned off.
+     */
+    #define WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+    static const char* TAG = "wc_sha_512";
+#else
+    #undef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+#endif
+
 #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
     #define FIPS_NO_WRAPPERS
@@ -279,21 +294,13 @@ static int InitSha512(wc_Sha512* sha512)
     sha512->loLen   = 0;
     sha512->hiLen   = 0;
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
 
-    sha512->ctx.sha_type = SHA2_512;
-     /* always start firstblock = 1 when using hw engine */
-    sha512->ctx.isfirstblock = 1;
-    if(sha512->ctx.mode == ESP32_SHA_HW) {
-        /* release hw */
-        esp_sha_hw_unlock(&(sha512->ctx));
-    }
-    /* always set mode as INIT
-    *  whether using HW or SW is determined at first call of update()
-    */
-    sha512->ctx.mode = ESP32_SHA_INIT;
+    /* HW needs to be carefully initialized, taking into account soft copy.
+    ** If already in use; copy may revert to SW as needed. */
+    esp_sha_init(&(sha512->ctx), WC_HASH_TYPE_SHA512);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
     sha512->flags = 0;
 #endif
@@ -327,21 +334,15 @@ static int InitSha512_224(wc_Sha512* sha512)
     sha512->loLen   = 0;
     sha512->hiLen   = 0;
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-
-    sha512->ctx.sha_type = SHA2_512;
-     /* always start firstblock = 1 when using hw engine */
-    sha512->ctx.isfirstblock = 1;
-    if(sha512->ctx.mode == ESP32_SHA_HW) {
-        /* release hw */
-        esp_sha_hw_unlock(&(sha512->ctx));
-    }
-    /* always set mode as INIT
-    *  whether using HW or SW is determined at first call of update()
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    /* HW needs to be carefully initialized, taking into account soft copy.
+    ** If already in use; copy may revert to SW as needed.
+    **
+    ** Note for original ESP32, there's no HW for SHA512/224
     */
-    sha512->ctx.mode = ESP32_SHA_INIT;
+    esp_sha_init(&(sha512->ctx), WC_HASH_TYPE_SHA512_224);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
     sha512->flags = 0;
 #endif
@@ -375,21 +376,15 @@ static int InitSha512_256(wc_Sha512* sha512)
     sha512->loLen   = 0;
     sha512->hiLen   = 0;
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-
-    sha512->ctx.sha_type = SHA2_512;
-     /* always start firstblock = 1 when using hw engine */
-    sha512->ctx.isfirstblock = 1;
-    if(sha512->ctx.mode == ESP32_SHA_HW) {
-        /* release hw */
-        esp_sha_hw_unlock(&(sha512->ctx));
-    }
-    /* always set mode as INIT
-    *  whether using HW or SW is determined at first call of update()
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    /* HW needs to be carefully initialized, taking into account soft copy.
+    ** If already in use; copy may revert to SW as needed.
+    **
+    ** Note for original ESP32, there's no HW for SHA512/2256.
     */
-    sha512->ctx.mode = ESP32_SHA_INIT;
+    esp_sha_init(&(sha512->ctx), WC_HASH_TYPE_SHA512_256);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
     sha512->flags = 0;
 #endif
@@ -578,8 +573,10 @@ static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId,
 {
    int ret = 0;
 
-    if (sha512 == NULL)
+    if (sha512 == NULL) {
         return BAD_FUNC_ARG;
+    }
+
 
     sha512->heap = heap;
 #ifdef WOLFSSL_SMALL_STACK_CACHE
@@ -590,6 +587,7 @@ static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId,
     sha512->devCtx = NULL;
 #endif
 
+    /* call the initialization function pointed to by initfp */
     ret = initfp(sha512);
     if (ret != 0)
         return ret;
@@ -614,10 +612,19 @@ static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId,
      ret = wc_CAAM_HashInit(&sha512->hndl, &sha512->ctx, WC_HASH_TYPE_SHA512);
 #endif
     return ret;
-}
+} /* InitSha512_Family */
 
 int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
 {
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    if (sha512->ctx.mode != ESP32_SHA_INIT) {
+        ESP_LOGV(TAG, "Set ctx mode from prior value: "
+                      "%d", sha512->ctx.mode);
+    }
+    /* We know this is a fresh, uninitialized item, so set to INIT */
+    sha512->ctx.mode = ESP32_SHA_INIT;
+#endif
+
     return InitSha512_Family(sha512, heap, devId, InitSha512);
 }
 
@@ -625,6 +632,10 @@ int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
 int wc_InitSha512_224_ex(wc_Sha512* sha512, void* heap, int devId)
 {
+#ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+    /* No SHA512/224 HW support is available, set to SW. */
+    sha512->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */
+#endif
     return InitSha512_Family(sha512, heap, devId, InitSha512_224);
 }
 #endif /* !WOLFSSL_NOSHA512_224 ... */
@@ -633,6 +644,10 @@ int wc_InitSha512_224_ex(wc_Sha512* sha512, void* heap, int devId)
    (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
 int wc_InitSha512_256_ex(wc_Sha512* sha512, void* heap, int devId)
 {
+#ifdef WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
+    /* No SHA512/256 HW support is available on ESP32, set to SW. */
+    sha512->ctx.mode = ESP32_SHA_SW;
+#endif
     return InitSha512_Family(sha512, heap, devId, InitSha512_256);
 }
 #endif /* !WOLFSSL_NOSHA512_256 ... */
@@ -836,6 +851,8 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le
             }
             ret = esp_sha512_process(sha512);
             if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+                ByteReverseWords64(sha512->buffer, sha512->buffer,
+                                                         WC_SHA512_BLOCK_SIZE);
                 ret = Transform_Sha512(sha512);
             }
     #endif
@@ -903,14 +920,18 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le
             if(sha512->ctx.mode == ESP32_SHA_INIT) {
                 esp_sha_try_hw_lock(&sha512->ctx);
             }
-            ret = esp_sha512_process(sha512);
-            if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+            if (sha512->ctx.mode == ESP32_SHA_SW) {
+                ByteReverseWords64(sha512->buffer, sha512->buffer,
+                                                          WC_SHA512_BLOCK_SIZE);
                 ret = Transform_Sha512(sha512);
             }
+            else {
+                ret = esp_sha512_process(sha512);
+            }
     #endif
             if (ret != 0)
                 break;
-        }
+        } /* while (len >= WC_SHA512_BLOCK_SIZE) */
     }
 #endif
 
@@ -962,8 +983,8 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
 
 static WC_INLINE int Sha512Final(wc_Sha512* sha512)
 {
-    byte* local;
     int ret;
+    byte* local;
 
     if (sha512 == NULL) {
         return BAD_FUNC_ARG;
@@ -971,6 +992,12 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
 
     local = (byte*)sha512->buffer;
 
+    /* we'll add a 0x80 byte at the end,
+    ** so make sure we have appropriate buffer length. */
+    if (sha512->buffLen > WC_SHA512_BLOCK_SIZE - 1) {
+        return BAD_STATE_E;
+    } /* buffLen check */
+
     local[sha512->buffLen++] = 0x80;  /* add 1 */
 
     /* pad with zeros */
@@ -990,24 +1017,29 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
                                                          WC_SHA512_BLOCK_SIZE);
        #endif
         }
+
 #endif /* LITTLE_ENDIAN_ORDER */
-#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
-     defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-        ret = Transform_Sha512(sha512);
-#else
-       if(sha512->ctx.mode == ESP32_SHA_INIT) {
+    #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+        if (sha512->ctx.mode == ESP32_SHA_INIT) {
             esp_sha_try_hw_lock(&sha512->ctx);
-       }
-        ret = esp_sha512_process(sha512);
-        if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){
+        }
+        if (sha512->ctx.mode == ESP32_SHA_SW) {
+            ByteReverseWords64(sha512->buffer,sha512->buffer,
+                                                         WC_SHA512_BLOCK_SIZE);
             ret = Transform_Sha512(sha512);
         }
-#endif
+        else {
+            ret = esp_sha512_process(sha512);
+        }
+    #else
+        ret = Transform_Sha512(sha512);
+    #endif
         if (ret != 0)
             return ret;
 
         sha512->buffLen = 0;
-    }
+    } /* (sha512->buffLen > WC_SHA512_PAD_SIZE) pad with zeros */
+
     XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen);
 
     /* put lengths in bits */
@@ -1041,18 +1073,28 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
                            &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]),
                            WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE);
 #endif
+
 #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \
     defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
     ret = Transform_Sha512(sha512);
 #else
     if(sha512->ctx.mode == ESP32_SHA_INIT) {
+        /* typically for tiny block: first = last */
         esp_sha_try_hw_lock(&sha512->ctx);
     }
-    ret = esp_sha512_digest_process(sha512, 1);
-    if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW) {
+    if (sha512->ctx.mode == ESP32_SHA_SW) {
+        ByteReverseWords64(sha512->buffer,
+                           sha512->buffer,
+                           WC_SHA512_BLOCK_SIZE);
+        sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen;
+        sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen;
         ret = Transform_Sha512(sha512);
     }
+    else {
+        ret = esp_sha512_digest_process(sha512, 1);
+    }
 #endif
+
     if (ret != 0)
         return ret;
 
@@ -1179,6 +1221,7 @@ void wc_Sha512Free(wc_Sha512* sha512)
     wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512);
 #endif /* WOLFSSL_ASYNC_CRYPT */
 }
+
 #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_KCAPI_HASH)
 /* Apply SHA512 transformation to the data                */
 /* @param sha  a pointer to wc_Sha512 structure           */
@@ -1302,24 +1345,16 @@ static int InitSha384(wc_Sha384* sha384)
     sha384->loLen   = 0;
     sha384->hiLen   = 0;
 
-#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    sha384->ctx.sha_type = SHA2_384;
-     /* always start firstblock = 1 when using hw engine */
-    sha384->ctx.isfirstblock = 1;
-    if(sha384->ctx.mode == ESP32_SHA_HW) {
-        /* release hw */
-        esp_sha_hw_unlock(&(sha384->ctx));
-    }
-    /* always set mode as INIT
-    *  whether using HW or SW is determined at first call of update()
-    */
-    sha384->ctx.mode = ESP32_SHA_INIT;
-
+#if  defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    /* HW needs to be carefully initialized, taking into account soft copy.
+    ** If already in use; copy may revert to SW as needed. */
+    esp_sha_init(&(sha384->ctx), WC_HASH_TYPE_SHA384);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
     sha384->flags = 0;
 #endif
+
 #ifdef WOLFSSL_HASH_KEEP
     sha384->msg  = NULL;
     sha384->len  = 0;
@@ -1426,10 +1461,19 @@ int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
     sha384->devId = devId;
     sha384->devCtx = NULL;
 #endif
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    if (sha384->ctx.mode != ESP32_SHA_INIT) {
+        ESP_LOGV(TAG, "Set ctx mode from prior value: "
+                           "%d", sha384->ctx.mode);
+    }
+    /* We know this is a fresh, uninitialized item, so set to INIT */
+    sha384->ctx.mode = ESP32_SHA_INIT;
+#endif
 
     ret = InitSha384(sha384);
-    if (ret != 0)
+    if (ret != 0) {
         return ret;
+    }
 
 #if defined(USE_INTEL_SPEEDUP) && \
     (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
@@ -1525,24 +1569,10 @@ static int Sha512_Family_GetHash(wc_Sha512* sha512, byte* hash,
     }
 #endif
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    if (sha512->ctx.mode == ESP32_SHA_INIT) {
-        esp_sha_try_hw_lock(&sha512->ctx);
-    }
-    if (sha512->ctx.mode != ESP32_SHA_SW) {
-       esp_sha512_digest_process(sha512, 0);
-    }
-#endif
-
+    /* copy this sha512 into tmpSha */
     ret = wc_Sha512Copy(sha512, tmpSha512);
     if (ret == 0) {
         ret = finalfp(tmpSha512, hash);
-
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-        sha512->ctx.mode = ESP32_SHA_SW;;
-#endif
         wc_Sha512Free(tmpSha512);
     }
 
@@ -1562,8 +1592,9 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
 {
     int ret = 0;
 
-    if (src == NULL || dst == NULL)
+    if (src == NULL || dst == NULL) {
         return BAD_FUNC_ARG;
+    }
 
     XMEMCPY(dst, src, sizeof(wc_Sha512));
 #ifdef WOLFSSL_SMALL_STACK_CACHE
@@ -1578,15 +1609,17 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst)
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512)
     ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
 #endif
-#if  defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    dst->ctx.mode = src->ctx.mode;
-    dst->ctx.isfirstblock = src->ctx.isfirstblock;
-    dst->ctx.sha_type = src->ctx.sha_type;
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    if (ret == 0) {
+        ret = esp_sha512_ctx_copy(src, dst);
+    }
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
      dst->flags |= WC_HASH_FLAG_ISCOPY;
 #endif
+
 #if defined(WOLFSSL_HASH_KEEP)
     if (src->msg != NULL) {
         dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1626,6 +1659,7 @@ int wc_InitSha512_224(wc_Sha512* sha)
 {
     return wc_InitSha512_224_ex(sha, NULL, INVALID_DEVID);
 }
+
 int wc_Sha512_224Update(wc_Sha512* sha, const byte* data, word32 len)
 {
     return wc_Sha512Update(sha, data, len);
@@ -1640,16 +1674,19 @@ int wc_Sha512_224FinalRaw(wc_Sha512* sha, byte* hash)
 {
     return Sha512FinalRaw(sha, hash, WC_SHA512_224_DIGEST_SIZE);
 }
+
 int wc_Sha512_224Final(wc_Sha512* sha512, byte* hash)
 {
     return Sha512_Family_Final(sha512, hash, WC_SHA512_224_DIGEST_SIZE,
                                InitSha512_224);
 }
-#endif
+#endif /* else none of the above: WOLFSSL_KCAPI_HASH, WOLFSSL_SE050 */
+
 void wc_Sha512_224Free(wc_Sha512* sha)
 {
     wc_Sha512Free(sha);
 }
+
 #if defined(WOLFSSL_KCAPI_HASH)
     /* functions defined in wolfcrypt/src/port/kcapi/kcapi_hash.c */
 #elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
@@ -1660,11 +1697,12 @@ int wc_Sha512_224GetHash(wc_Sha512* sha512, byte* hash)
 {
     return Sha512_Family_GetHash(sha512, hash, wc_Sha512_224Final);
 }
+
 int wc_Sha512_224Copy(wc_Sha512* src, wc_Sha512* dst)
 {
     return wc_Sha512Copy(src, dst);
 }
-#endif
+#endif /* else none of the above: WOLFSSL_KCAPI_HASH, WOLFSSL_SE050 */
 
 #ifdef WOLFSSL_HASH_FLAGS
 int wc_Sha512_224SetFlags(wc_Sha512* sha, word32 flags)
@@ -1694,6 +1732,7 @@ int wc_InitSha512_256(wc_Sha512* sha)
 {
     return wc_InitSha512_256_ex(sha, NULL, INVALID_DEVID);
 }
+
 int wc_Sha512_256Update(wc_Sha512* sha, const byte* data, word32 len)
 {
     return wc_Sha512Update(sha, data, len);
@@ -1707,16 +1746,19 @@ int wc_Sha512_256FinalRaw(wc_Sha512* sha, byte* hash)
 {
     return Sha512FinalRaw(sha, hash, WC_SHA512_256_DIGEST_SIZE);
 }
+
 int wc_Sha512_256Final(wc_Sha512* sha512, byte* hash)
 {
     return Sha512_Family_Final(sha512, hash, WC_SHA512_256_DIGEST_SIZE,
                                InitSha512_256);
 }
 #endif
+
 void wc_Sha512_256Free(wc_Sha512* sha)
 {
     wc_Sha512Free(sha);
 }
+
 #if defined(WOLFSSL_KCAPI_HASH)
     /* functions defined in wolfcrypt/src/port/kcapi/kcapi_hash.c */
 
@@ -1782,23 +1824,10 @@ int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash)
     }
 #endif
 
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    if (sha384->ctx.mode == ESP32_SHA_INIT) {
-        esp_sha_try_hw_lock(&sha384->ctx);
-    }
-    if (sha384->ctx.mode != ESP32_SHA_SW) {
-        esp_sha512_digest_process(sha384, 0);
-    }
-#endif
+    /* copy this sha384 into tmpSha */
     ret = wc_Sha384Copy(sha384, tmpSha384);
     if (ret == 0) {
         ret = wc_Sha384Final(tmpSha384, hash);
-
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-        sha384->ctx.mode = ESP32_SHA_SW;
-#endif
         wc_Sha384Free(tmpSha384);
     }
 
@@ -1818,6 +1847,7 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
     }
 
     XMEMCPY(dst, src, sizeof(wc_Sha384));
+
 #ifdef WOLFSSL_SMALL_STACK_CACHE
     dst->W = NULL;
 #endif
@@ -1830,15 +1860,15 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst)
 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384)
     ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
 #endif
-#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
-   !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
-    dst->ctx.mode = src->ctx.mode;
-    dst->ctx.isfirstblock = src->ctx.isfirstblock;
-    dst->ctx.sha_type = src->ctx.sha_type;
+
+#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
+    esp_sha384_ctx_copy(src, dst);
 #endif
+
 #ifdef WOLFSSL_HASH_FLAGS
      dst->flags |= WC_HASH_FLAG_ISCOPY;
 #endif
+
 #if defined(WOLFSSL_HASH_KEEP)
     if (src->msg != NULL) {
         dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);

+ 73 - 44
wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h

@@ -28,7 +28,6 @@
 #include "esp_idf_version.h"
 #include "esp_types.h"
 #include "esp_log.h"
-#include "esp_random.h"
 
 #ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
     #undef LOG_LOCAL_LEVEL
@@ -39,31 +38,45 @@
 #endif
 
 #include <freertos/FreeRTOS.h>
-#include "soc/dport_reg.h"
-#include "soc/hwcrypto_reg.h"
+#if defined(CONFIG_IDF_TARGET_ESP32C3)
+    /* no includes for ESP32C3 at this time (no HW implemented yet) */
+#elif defined(CONFIG_IDF_TARGET_ESP32S3)
+    #include "soc/dport_reg.h"
+    #include "soc/hwcrypto_reg.h"
+    #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
+        #include "esp_private/periph_ctrl.h"
+    #else
+        #include "driver/periph_ctrl.h"
+    #endif
+#else
+    #include "soc/dport_reg.h"
+    #include "soc/hwcrypto_reg.h"
 
-#if ESP_IDF_VERSION_MAJOR < 5
-    #include "soc/cpu.h"
-#endif
+    #if ESP_IDF_VERSION_MAJOR < 5
+        #include "soc/cpu.h"
+    #endif
 
-#if ESP_IDF_VERSION_MAJOR >= 5
-    #include "esp_private/periph_ctrl.h"
-#else
-    #include "driver/periph_ctrl.h"
-#endif
+    #if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
+        #include "esp_private/periph_ctrl.h"
+    #else
+        #include "driver/periph_ctrl.h"
+    #endif
+
+    #if ESP_IDF_VERSION_MAJOR >= 4
+        #include <esp32/rom/ets_sys.h>
+    #else
+        #include <rom/ets_sys.h>
+    #endif
 
-#if ESP_IDF_VERSION_MAJOR >= 4
-    #include <esp32/rom/ets_sys.h>
-#elif defined(CONFIG_IDF_TARGET_ESP32S3)
-    #include <esp32s3/rom/ets_sys.h>
-#else
-    #include <rom/ets_sys.h>
 #endif
 
+
 #ifdef __cplusplus
     extern "C" {
 #endif
 
+int esp_ShowExtendedSystemInfo(void);
+
 int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex);
 int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBloxkTime);
 int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
@@ -72,8 +85,6 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
 
     #if ESP_IDF_VERSION_MAJOR >= 4
         #include "esp32/rom/aes.h"
-    #elif defined(CONFIG_IDF_TARGET_ESP32S3)
-        #include "esp32s3/rom/aes.h"
     #else
         #include "rom/aes.h"
     #endif
@@ -95,14 +106,15 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
 
 #ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
 
-    void wc_esp32TimerStart();
-    uint64_t  wc_esp32elapsedTime();
+    void wc_esp32TimerStart(void);
+    uint64_t  wc_esp32elapsedTime(void);
 
 #endif /* WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */
 
-#if (!defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || \
-      defined(WOLFSSL_SHA512)) && \
-    !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
+#if !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) &&     \
+   (!defined(NO_SHA) || !defined(NO_SHA256) ||          \
+     defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) \
+   )
 
     /* RAW hash function APIs are not implemented with esp32 hardware acceleration*/
     #define WOLFSSL_NO_HASH_RAW
@@ -118,50 +130,67 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
 
     #undef SHA_CTX
 
-    typedef enum {
-        ESP32_SHA_INIT = 0,
-        ESP32_SHA_HW = 1,
-        ESP32_SHA_SW = 2,
+    typedef enum
+    {
+        ESP32_SHA_INIT             = 0,
+        ESP32_SHA_HW               = 1,
+        ESP32_SHA_SW               = 2,
+        ESP32_SHA_HW_COPY          = 3,
         ESP32_SHA_FAIL_NEED_UNROLL = -1
     } ESP32_MODE;
 
-    typedef struct {
-        byte isfirstblock;
-
-        ESP32_MODE mode; /* typically 0 init, 1 HW, 2 SW */
+    typedef struct
+    {
+        /* pointer to object the initialized HW; to track copies */
+        void* initializer;
+
+        /* an ESP32_MODE value; typically:
+        **   0 init,
+        **   1 HW,
+        **   2 SW     */
+        ESP32_MODE mode;
+
+        /* see esp_rom/include/esp32/rom/sha.h
+        **
+        **  the Espressif type: SHA1, SHA256, etc.
+        */
+        enum SHA_TYPE sha_type;
 
         /* we'll keep track of our own locks.
-         * actual enable/disable only occurs for ref_counts[periph] == 0 */
-        int lockDepth; /* see ref_counts[periph] in periph_ctrl.c */
-
-        /* ESP32S3 defines SHA_TYPE to enum, all other ESP32s define it to
-           typedef enum. */
-    #if defined(CONFIG_IDF_TARGET_ESP32S3)
-        SHA_TYPE sha_type;
-    #else
-        enum SHA_TYPE sha_type;
-    #endif
+        ** actual enable/disable only occurs for ref_counts[periph] == 0
+        **
+        **  see ref_counts[periph] in periph_ctrl.c */
+        byte lockDepth:7;   /* 7 bits for a small number, pack with below. */
+
+        /* 0 (false) this is NOT first block.
+        ** 1 (true ) this is first block.  */
+        byte isfirstblock:1; /* 1 bit only for true / false */
     } WC_ESP32SHA;
 
+    int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type);
+    int esp_sha_init_ctx(WC_ESP32SHA* ctx);
     int esp_sha_try_hw_lock(WC_ESP32SHA* ctx);
     int esp_sha_hw_unlock(WC_ESP32SHA* ctx);
 
     struct wc_Sha;
+    int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst);
     int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess);
     int esp_sha_process(struct wc_Sha* sha, const byte* data);
 
     #ifndef NO_SHA256
         struct wc_Sha256;
+        int esp_sha224_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst);
+        int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst);
         int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess);
         int esp_sha256_process(struct wc_Sha256* sha, const byte* data);
         int esp32_Transform_Sha256_demo(struct wc_Sha256* sha256, const byte* data);
-
-
     #endif
 
     /* TODO do we really call esp_sha512_process for WOLFSSL_SHA384 ? */
     #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
         struct wc_Sha512;
+        int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst);
+        int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst);
         int esp_sha512_process(struct wc_Sha512* sha);
         int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc);
     #endif

Some files were not shown because too many files changed in this diff