diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt index 2423b802c1..eff3591838 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_benchmark/components/wolfssl/CMakeLists.txt +++ b/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() diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt index 2423b802c1..a916facabd 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/components/wolfssl/CMakeLists.txt +++ b/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" diff --git a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c b/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c index 01538f72e3..5adb75300f 100644 --- a/IDE/Espressif/ESP-IDF/examples/wolfssl_test/main/main.c +++ b/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 diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 68949cbdaa..1c9e1df21a 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -66,7 +66,21 @@ #include #ifdef WOLFSSL_ESPIDF - #include /* 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 + #else + #error "CONFIG_IDF_TARGET not implemented" + #endif #include #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 @@ void bench_sha512_224(int useDeviceID) 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 @@ void bench_sha512_256(int useDeviceID) 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); diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c index 0603f169e5..09105a5110 100644 --- a/wolfcrypt/src/port/Espressif/esp32_aes.c +++ b/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 #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" +#include +/* 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 */ diff --git a/wolfcrypt/src/port/Espressif/esp32_mp.c b/wolfcrypt/src/port/Espressif/esp32_mp.c index 1717a415b0..7e57eff4ca 100644 --- a/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/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) && diff --git a/wolfcrypt/src/port/Espressif/esp32_sha.c b/wolfcrypt/src/port/Espressif/esp32_sha.c index 257a715287..3f5535ba35 100644 --- a/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -60,108 +60,569 @@ static const char* TAG = "wolf_hw_sha"; #define WC_SHA_DIGEST_SIZE 20 #endif -/* mutex */ +/* RTOS mutex or just InUse variable */ #if defined(SINGLE_THREADED) static int InUse = 0; #else - static wolfSSL_Mutex sha_mutex; - static int espsha_CryptHwMutexInit = 0; + static wolfSSL_Mutex sha_mutex = NULL; #if defined(DEBUG_WOLFSSL) + /* Only when debugging, we'll keep tracking of block numbers. */ static int this_block_num = 0; #endif #endif -/* - * determine the digest size, depending on SHA type. - * - * See FIPS PUB 180-4, Instruction Section 1. - * - * - enum SHA_TYPE { - SHA1 = 0, - SHA2_256, - SHA2_384, - SHA2_512, - SHA_INVALID = -1, - }; +/* esp_sha_init +** +** ctx: any wolfSSL ctx from any hash algo +** hash_type: the specific wolfSSL enum for hash type +** +** Initializes ctx based on chipset capabilities and current state. +** Active HW states, such as from during a copy operation, are demoted to SW. +** For hash_type not available in HW, set SW mode. +** +** See esp_sha_init_ctx(ctx) */ -static word32 wc_esp_sha_digest_size(enum SHA_TYPE type) +int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) { - ESP_LOGV(TAG, " esp_sha_digest_size"); + int ret = 0; - switch(type){ - #ifndef NO_SHA - case SHA1: /* typically 20 bytes */ - return WC_SHA_DIGEST_SIZE; - #endif +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) + switch (hash_type) { /* check each wolfSSL hash type WC_[n] */ + case WC_HASH_TYPE_SHA: + ctx->sha_type = SHA1; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; - #ifndef NO_SHA256 - case SHA2_256: /* typically 32 bytes */ - return WC_SHA256_DIGEST_SIZE; - #endif + case WC_HASH_TYPE_SHA256: + ctx->sha_type = SHA2_256; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; - #ifdef WOLFSSL_SHA384 - case SHA2_384: - return WC_SHA384_DIGEST_SIZE; - #endif + #ifdef CONFIG_IDF_TARGET_ESP32S3 + case WC_HASH_TYPE_SHA384: + /* TODO is SHA384 really not supported on -S3? */ + ctx->mode = ESP32_SHA_SW; + ctx->sha_type = SHA2_384; /* Espressif type, but we won't use HW */ + break; + #else + case WC_HASH_TYPE_SHA384: + ctx->sha_type = SHA2_384; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; + #endif - #ifdef WOLFSSL_SHA512 - case SHA2_512: /* typically 64 bytes */ - return WC_SHA512_DIGEST_SIZE; - #endif + case WC_HASH_TYPE_SHA512: + ctx->sha_type = SHA2_512; /* assign Espressif SHA HW type */ + ret = esp_sha_init_ctx(ctx); + break; + + #ifndef WOLFSSL_NOSHA512_224 + case WC_HASH_TYPE_SHA512_224: + /* Don't call init, always SW as there's no HW. */ + ctx->mode = ESP32_SHA_SW; + ctx->sha_type = SHA2_512; /* Espressif type, but we won't use HW */ + break; + #endif + + #ifndef WOLFSSL_NOSHA512_256 + case WC_HASH_TYPE_SHA512_256: + /* Don't call init, always SW as there's no HW. */ + ctx->mode = ESP32_SHA_SW; + ctx->sha_type = SHA2_512; /* Espressif type, but we won't use HW */ + break; + #endif default: - ESP_LOGE(TAG, "Bad sha type"); - return WC_SHA_DIGEST_SIZE; + ret = esp_sha_init_ctx(ctx); + ESP_LOGW(TAG, "Unexpected hash_type in esp_sha_init"); + break; } - /* we never get here, as all the above switches should have a return */ +#else + /* other chipsets will be implemented here */ +#endif /* defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) */ + + return ret; } +/* we'll call a separate init as there's only 1 HW acceleration */ +int esp_sha_init_ctx(WC_ESP32SHA* ctx) +{ + if (ctx->initializer == NULL) { + ESP_LOGV(TAG, "regular init of blank WC_ESP32SHA ctx"); + + /* we'll keep track of who initialized this */ + ctx->initializer = ctx; /* save our address in the initializer */ + ctx->mode = ESP32_SHA_INIT; + } + else { + /* things may be more interesting when previously initialized */ + if (ctx->initializer == ctx) { + /* We're likely re-using an existing object previously initialized. + ** There's of course a non-zero probability that garbage data is + ** the same pointer value, but that's highly unlikely; We'd need + ** to discard, then re-init to same memory location for a matching + ** initializer. */ + ESP_LOGV(TAG, "re-using existing WC_ESP32SHA ctx"); + + /* we should never have an unexpected mode in a known ctx */ + switch (ctx->mode) { + case ESP32_SHA_INIT: + case ESP32_SHA_SW: + /* nothing interesting here */ + break; + + case ESP32_SHA_HW: + /* This will be dealt with below: likely demote to SW */ + break; + + case ESP32_SHA_HW_COPY: + /* This is an interesting mode, caller gave HW mode hint */ + ESP_LOGI(TAG, "ALERT: ESP32_SHA_HW_COPY?"); + break; + + default: + /* This should almost occur. We'd need to have an + ** uninitialized ctx that just happens to include the + ** breadcrumb initializer with the same address. */ + ESP_LOGW(TAG, "ALERT: unexpected WC_ESP32SHA ctx mode: " + "%d. ", ctx->mode); + ctx->mode = ESP32_SHA_INIT; + break; + } + /* We don't need to do anything here, + ** this section for diagnostics only. + ** May need to unlock HW, below. */ + } /* ctx->initializer == ctx */ + else { + /* We may end up here with either dirty memory + ** or copied SHA ctx. + ** + ** Any copy function should have already set mode = ESP32_SHA_INIT. + ** + ** In either case, initialize: */ + ctx->initializer = ctx; /* set a new address */ + + /* Always set to ESP32_SHA_INIT, but give debug info as to why: */ + switch (ctx->mode) { + case ESP32_SHA_INIT: + /* if we are already in init mode, nothing to do. */ + break; + + case ESP32_SHA_SW: + /* this should rarely, if ever occur */ + ESP_LOGW(TAG, "ALERT: unexpected SW WC_ESP32SHA ctx mode. " + "Copied? Revert to ESP32_SHA_INIT."); + ctx->mode = ESP32_SHA_INIT; + break; + + case ESP32_SHA_HW: + /* this should rarely, if ever occur. */ + ESP_LOGW(TAG, "ALERT: unexpected HW WC_ESP32SHA ctx mode. " + "Copied?"); + ctx->mode = ESP32_SHA_INIT; + break; + + case ESP32_SHA_HW_COPY: + /* This is an interesting but acceptable situation: + ** an anticipated active HW copy that will demote to SW. */ + ESP_LOGV(TAG, "HW WC_ESP32SHA ctx mode = ESP32_SHA_HW_COPY."); + break; + + default: + /* this will frequently occur during new init */ + ESP_LOGV(TAG, "ALERT: unexpected WC_ESP32SHA ctx mode. " + "Uninitialized?"); + ctx->mode = ESP32_SHA_INIT; + break; + } /* switch */ + } /* ctx->initializer != ctx */ + } /* ctx->initializer != NULL */ + + /* + ** After possibly changing the mode (above) handle current mode: + */ + switch (ctx->mode) { + case ESP32_SHA_INIT: + /* Likely a fresh, new SHA, as desired. */ + ESP_LOGV(TAG, "Normal ESP32_SHA_INIT"); + break; + + case ESP32_SHA_HW: + /* We're already in hardware mode, so release. */ + /* Interesting, but normal. */ + ESP_LOGV(TAG, ">> HW unlock."); + + /* During init is the ONLY TIME we call unlock. + ** If there's a problem, likely some undesired operation + ** outside of wolfSSL. + */ + esp_sha_hw_unlock(ctx); + ctx->mode = ESP32_SHA_INIT; + break; + + case ESP32_SHA_HW_COPY: + /* When we init during a known active HW copy, revert to SW. */ + ESP_LOGV(TAG, "Planned revert to SW during copy."); + ctx->mode = ESP32_SHA_SW; + break; + + case ESP32_SHA_SW: + /* This is an interesting situation: likely a call when + ** another SHA in progress, but copied. */ + ESP_LOGV(TAG, ">> SW Set to init."); + ctx->mode = ESP32_SHA_INIT; + break; + + case ESP32_SHA_FAIL_NEED_UNROLL: + /* Oh, how did we get here? likely uninitialized SHA memory. + ** User code logic may need attention. */ + ESP_LOGW(TAG, "ALERT: \nESP32_SHA_FAIL_NEED_UNROLL\n"); + ctx->mode = ESP32_SHA_INIT; + break; + + default: + /* Most likely corrupted memory. */ + ESP_LOGW(TAG, "ALERT: \nunexpected mode value: " + "%d \n", ctx->mode); + ctx->mode = ESP32_SHA_INIT; + break; + } /* switch (ctx->mode) */ + + /* reminder: always start isfirstblock = 1 (true) when using HW engine */ + /* we're always on the first block at init time (not zero-based!) */ + ctx->isfirstblock = true; + ctx->lockDepth = 0; /* new objects will always start with lock depth = 0 */ + + return 0; /* Always return success. We assume all issues handled, above. */ +} /* esp_sha_init_ctx */ + +/* +** internal SHA ctx copy for ESP HW +*/ +int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) +{ + int ret; + if (src->ctx.mode == ESP32_SHA_HW) { + /* this is an interesting situation to copy HW digest to SW */ + ESP_LOGV(TAG, "esp_sha_ctx_copy esp_sha_digest_process"); + + /* Get a copy of the HW digest, but don't process it. */ + ret = esp_sha_digest_process(dst, 0); + if (ret == 0) { + /* note we arrived here only because the src is already in HW mode */ + dst->ctx.mode = ESP32_SHA_HW_COPY; /* provide init hint to SW revert */ + + /* initializer will be set during init */ + ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA); + if (ret != 0) { + ESP_LOGE(TAG, "Error during esp_sha_ctx_copy in esp_sha_init."); + } + } + else { + ESP_LOGE(TAG, "Error during esp_sha_ctx_copy in esp_sha_digest_process."); + } + + if (dst->ctx.mode == ESP32_SHA_SW) { + /* The normal revert to SW in copy is expected */ + ESP_LOGV(TAG, "Confirmed SHA Copy set to SW"); + } + else { + /* However NOT reverting to SW is not right. + ** This should never happen. */ + ESP_LOGW(TAG, "SHA Copy NOT set to SW"); + } + } /* (src->ctx.mode == ESP32_SHA_HW */ + else { /* src not in HW mode, ok to copy. */ + /* + ** reminder XMEMCOPY, above: dst->ctx = src->ctx; + ** No special HW init needed in SW mode. + ** but we need to set our initializer breadcrumb: */ + dst->ctx.initializer = &(dst->ctx); /* assign new breadcrumb to dst */ + ret = 0; + } + + return ret; +} /* esp_sha_ctx_copy */ + +/* +** internal sha224 ctx copy (no ESP HW) +*/ +int esp_sha224_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) +{ + /* There's no 224 hardware on ESP32 */ + dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ + + /* always set to SW, as there's no ESP32 HW for SHA224. + ** TODO: add support for ESP32-S2. ESP32-S3, ESP32-C3 here. + */ + dst->ctx.mode = ESP32_SHA_SW; + return 0; +} /* esp_sha224_ctx_copy */ + +/* +** internal sha256 ctx copy for ESP HW +*/ +int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) +{ + int ret; + if (src->ctx.mode == ESP32_SHA_HW) { + /* Get a copy of the HW digest, but don't process it. */ + ESP_LOGI(TAG, "esp_sha256_ctx_copy esp_sha512_digest_process"); + ret = esp_sha256_digest_process(dst, 0); + + if (ret == 0) { + /* provide init hint to possibly SW revert */ + dst->ctx.mode = ESP32_SHA_HW_COPY; + + /* initializer breadcrumb will be set during init */ + ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA256 ); + } + + if (dst->ctx.mode == ESP32_SHA_SW) { + ESP_LOGV(TAG, "Confirmed wc_Sha256 Copy set to SW"); + } + else { + ESP_LOGW(TAG, "wc_Sha256 Copy NOT set to SW"); + } + } /* (src->ctx.mode == ESP32_SHA_HW) */ + else { + ret = 0; + /* + ** reminder this happened in XMEMCOPY: dst->ctx = src->ctx; + ** No special HW init needed in SW mode. + ** but we need to set our initializer: */ + dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ + } /* not (src->ctx.mode == ESP32_SHA_HW) */ + + return ret; +} /* esp_sha256_ctx_copy */ + +/* +** internal sha384 ctx copy for ESP HW +*/ +int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) +{ + int ret; + if (src->ctx.mode == ESP32_SHA_HW) { + /* Get a copy of the HW digest, but don't process it. */ + ESP_LOGI(TAG, "esp_sha384_ctx_copy esp_sha512_digest_process"); + ret = esp_sha512_digest_process(dst, 0); + if (ret == 0) { + /* provide init hint to SW revert */ + dst->ctx.mode = ESP32_SHA_HW_COPY; + + /* initializer will be set during init */ + ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA384); + if (ret != 0) { + ESP_LOGE(TAG, "Error during esp_sha384_ctx_copy in esp_sha_init."); + } + } + else { + ESP_LOGE(TAG, "Error during esp_sha384_ctx_copy in esp_sha512_digest_process."); + } + + /* just some diagnostic runtime info */ + if (dst->ctx.mode == ESP32_SHA_SW) { + ESP_LOGV(TAG, "Confirmed wc_Sha512 Copy set to SW"); + } + else { + ESP_LOGW(TAG, "wc_Sha512 Copy NOT set to SW"); + } + } /* src->ctx.mode == ESP32_SHA_HW */ + else { + ret = 0; + /* + ** reminder this happened in XMEMCOPY, above: dst->ctx = src->ctx; + ** No special HW init needed in SW mode. + ** but we need to set our initializer: */ + dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ + } /* not (src->ctx.mode == ESP32_SHA_HW) */ + + return ret; +} /* esp_sha384_ctx_copy */ + +/* +** Internal sha512 ctx copy for ESP HW. +** If HW already active, fall back to SW for this ctx. +*/ +int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) +{ + int ret; + if (src->ctx.mode == ESP32_SHA_HW) { + /* Get a copy of the HW digest, but don't process it. */ + ESP_LOGI(TAG, "esp_sha512_ctx_copy esp_sha512_digest_process"); + ret = esp_sha512_digest_process(dst, 0); + + if (ret == 0) { + /* provide init hint to SW revert */ + dst->ctx.mode = ESP32_SHA_HW_COPY; + + /* initializer will be set during init + ** reminder we should never arrive here for + ** ESP32 SHA512/224 or SHA512/224, as there's no HW */ + ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA512); + } + + if (dst->ctx.mode == ESP32_SHA_SW) { + ESP_LOGV(TAG, "Confirmed wc_Sha512 Copy set to SW"); + } + else { + ESP_LOGW(TAG, "wc_Sha512 Copy NOT set to SW"); + } + } /* src->ctx.mode == ESP32_SHA_HW */ + else { + ret = 0; + /* reminder this happened in XMEMCOPY, above: dst->ctx = src->ctx; + ** No special HW init needed when not in active HW mode. + ** but we need to set our initializer breadcrumb: */ + dst->ctx.initializer = &dst->ctx; /*breadcrumb is this ctx address */ + } + + return ret; +} /* esp_sha512_ctx_copy */ + /* -* wait until all engines becomes idle +** determine the digest size, depending on SHA type. +** +** See FIPS PUB 180-4, Instruction Section 1. +** +** see ESP32 shah.h for values: +** +** enum SHA_TYPE { +** SHA1 = 0, +** SHA2_256, +** SHA2_384, +** SHA2_512, +** SHA_INVALID = -1, +** }; +** +** given the SHA_TYPE (see Espressif sha.h) return WC digest size. +** +** Returns zero for bad digest size type request. +** */ -static void wc_esp_wait_until_idle() +static word32 wc_esp_sha_digest_size(enum SHA_TYPE type) { - while((DPORT_REG_READ(SHA_1_BUSY_REG) != 0) || - (DPORT_REG_READ(SHA_256_BUSY_REG) != 0) || - (DPORT_REG_READ(SHA_384_BUSY_REG) != 0) || - (DPORT_REG_READ(SHA_512_BUSY_REG) != 0)) { + int ret = 0; + ESP_LOGV(TAG, " esp_sha_digest_size"); + + switch (type) { + #ifndef NO_SHA + case SHA1: /* typically 20 bytes */ + ret = WC_SHA_DIGEST_SIZE; + break; +#endif + #ifdef WOLFSSL_SHA224 + /* + no SHA224 HW at this time. + case SHA2_224: + ret = WC_SHA224_DIGEST_SIZE; + break; + */ + #endif + #ifndef NO_SHA256 + case SHA2_256: /* typically 32 bytes */ + ret = WC_SHA256_DIGEST_SIZE; + break; +#endif + #ifdef WOLFSSL_SHA384 + case SHA2_384: + ret = WC_SHA384_DIGEST_SIZE; + break; +#endif + #ifdef WOLFSSL_SHA512 + case SHA2_512: /* typically 64 bytes */ + ret = WC_SHA512_DIGEST_SIZE; + break; +#endif + default: + ESP_LOGE(TAG, "Bad SHA type in wc_esp_sha_digest_size"); + ret = 0; + break; + } + + return ret; /* Return value is a size, not an error code. */ +} /* wc_esp_sha_digest_size */ + +/* +** wait until all engines becomes idle +*/ +static int wc_esp_wait_until_idle(void) +{ + int ret = 0; /* assume success */ + +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ +#elif defined(CONFIG_IDF_TARGET_ESP32S3) + while (REG_READ(SHA_BUSY_REG)) { + /* do nothing while waiting. */ + } +#else + while ((DPORT_REG_READ(SHA_1_BUSY_REG) != 0) || + (DPORT_REG_READ(SHA_256_BUSY_REG) != 0) || + (DPORT_REG_READ(SHA_384_BUSY_REG) != 0) || + (DPORT_REG_READ(SHA_512_BUSY_REG) != 0)) { /* do nothing while waiting. */ } -} +#endif + + return ret; +} /* wc_esp_wait_until_idle */ /* - * hack alert. there really should have been something implemented - * in periph_ctrl.c to detect ref_counts[periph] depth. - * - * since there is not at this time, we have this brute-force method. - * - * when trying to unwrap an arbitrary depth of peripheral-enable(s), - * we'll check the register upon *enable* to see if we actually did. - * - * Note that enable / disable only occurs when ref_counts[periph] == 0 - * - * TODO: check if this works with other ESP32 platforms ESP32-C3, ESP32-S3, etc - */ +** hack alert. there really should have been something implemented +** in Espressif periph_ctrl.c to detect ref_counts[periph] depth. +** +** since there is not at this time, we have this brute-force method. +** +** when trying to unwrap an arbitrary depth of peripheral-enable(s), +** we'll check the register upon *enable* to see if we actually did. +** +** Note that enable / disable only occurs when ref_counts[periph] == 0 +** +** TODO: check if this works with other ESP32 platforms ESP32-C3, +** ESP32-S3, etc. (A: generally, no. RISC-V has different HW accelerator.) +*/ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) { /* if we end up here, there was a prior unexpected fail and * we need to unroll enables */ int ret = 0; /* assume success unless proven otherwise */ - uint32_t this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */ int actual_unroll_count = 0; int max_unroll_count = 1000; /* never get stuck in a hardware wait loop */ - this_sha_mask = periph_ll_get_clk_en_mask(PERIPH_SHA_MODULE); +#if defined(CONFIG_IDF_TARGET_ESP32) + uint32_t this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */ +#endif + + if (ctx == NULL) { + ESP_LOGE(TAG, "esp_unroll_sha_module_enable called with null ctx."); + return BAD_FUNC_ARG; + } + +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* RISC-V Architecture: TODO */ +#else + /* Xtensa Architecture */ /* unwind prior calls to THIS ctx. decrement ref_counts[periph] */ /* only when ref_counts[periph] == 0 does something actually happen */ /* once the value we read is a 0 in the DPORT_PERI_CLK_EN_REG bit * then we have fully unrolled the enables via ref_counts[periph]==0 */ +#if CONFIG_IDF_TARGET_ESP32S3 + /* once the value we read is a 0 in the DPORT_PERI_CLK_EN_REG bit + * then we have fully unrolled the enables via ref_counts[periph]==0 */ + while (periph_ll_periph_enabled(PERIPH_SHA_MODULE)) { +#else + /* this is the bit-mask for our SHA CLK_EN_REG */ + this_sha_mask = periph_ll_get_clk_en_mask(PERIPH_SHA_MODULE); + asm volatile("memw"); while ((this_sha_mask & *(uint32_t*)DPORT_PERI_CLK_EN_REG) != 0) { +#endif /* CONFIG_IDF_TARGET_ESP32S3 */ periph_module_disable(PERIPH_SHA_MODULE); + asm volatile("memw"); actual_unroll_count++; ESP_LOGI(TAG, "unroll not yet successful. try #%d", actual_unroll_count); @@ -173,38 +634,45 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) break; } } - +#endif /* else; not RISC-V */ if (ret == 0) { if (ctx->lockDepth != actual_unroll_count) { /* this could be a warning of wonkiness in RTOS environment. - * we were successful, but not expected depth count*/ - - ESP_LOGV(TAG, "warning lockDepth mismatch."); + ** we were successful, but not expected depth count. + ** + ** This should never happen unless someone else called + ** periph_module_disable() or threading not working properly. + **/ + ESP_LOGW(TAG, "warning lockDepth mismatch."); } ctx->lockDepth = 0; ctx->mode = ESP32_SHA_INIT; } else { + /* This should never occur. Something must have gone seriously + ** wrong. Check for non-wolfSSL outside calls that may have enabled HW. + */ ESP_LOGE(TAG, "Failed to unroll after %d attempts.", - actual_unroll_count); + actual_unroll_count); + ESP_LOGI(TAG, "Setting ctx->mode = ESP32_SHA_SW"); ctx->mode = ESP32_SHA_SW; } return ret; -} +} /* esp_unroll_sha_module_enable */ /* -* lock hw engine. -* this should be called before using engine. +** lock HW engine. +** this should be called before using engine. */ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) { int ret = 0; - ESP_LOGV(TAG, "enter esp_sha_hw_lock"); + ESP_LOGV(TAG, "enter esp_sha_hw_lock %x", (int)ctx->initializer); if (ctx == NULL) { ESP_LOGE(TAG, " esp_sha_try_hw_lock called with NULL ctx"); - return -1; + return BAD_FUNC_ARG; } /* Init mutex @@ -214,8 +682,8 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) * engine being busy or not. **/ #if defined(SINGLE_THREADED) - if(ctx->mode == ESP32_SHA_INIT) { - if(!InUse) { + if (ctx->mode == ESP32_SHA_INIT) { + if (!InUse) { ctx->mode = ESP32_SHA_HW; InUse = 1; } @@ -230,55 +698,70 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) } #else /* not defined(SINGLE_THREADED) */ /* - * there's only one SHA engine for all the hash types - * so when any hash is in use, no others can use it. - * fall back to SW. - **/ + ** there's only one SHA engine for all the hash types + ** so when any hash is in use, no others can use it. + ** fall back to SW. + ** + ** here is some sample code to test the unrolling of SHA enables: + ** - /* - * here is some sample code to test the unrolling of sha enables: - * periph_module_enable(PERIPH_SHA_MODULE); ctx->lockDepth++; periph_module_enable(PERIPH_SHA_MODULE); ctx->lockDepth++; ctx->mode = ESP32_FAIL_NEED_INIT; + ** */ - if (espsha_CryptHwMutexInit == 0) { - ESP_LOGV(TAG, "set esp_CryptHwMutexInit"); + if (sha_mutex == NULL) { + ESP_LOGV(TAG, "Initializing sha_mutex"); + + /* created, but not yet locked */ ret = esp_CryptHwMutexInit(&sha_mutex); if (ret == 0) { - espsha_CryptHwMutexInit = 1; + ESP_LOGV(TAG, "esp_CryptHwMutexInit sha_mutex init success."); } else { - ESP_LOGE(TAG, " mutex initialization failed. revert to software"); + ESP_LOGE(TAG, "esp_CryptHwMutexInit sha_mutex failed."); + sha_mutex = 0; + + ESP_LOGI(TAG, "Revert to ctx->mode = ESP32_SHA_SW."); ctx->mode = ESP32_SHA_SW; - /* espsha_CryptHwMutexInit is still zero */ return 0; /* success, just not using HW */ } } - /* check if this sha has been operated as sw or hw, or not yet init */ + /* check if this SHA has been operated as SW or HW, or not yet init */ if (ctx->mode == ESP32_SHA_INIT) { - /* try to lock the hw engine */ + /* try to lock the HW engine */ ESP_LOGV(TAG, "ESP32_SHA_INIT\n"); /* we don't wait: - * either the engine is free, or we fall back to SW - */ + ** either the engine is free, or we fall back to SW + **/ if (esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) { /* check to see if we had a prior fail and need to unroll enables */ ret = esp_unroll_sha_module_enable(ctx); - ESP_LOGV(TAG, "Hardware Mode, lock depth = %d", ctx->lockDepth); + ESP_LOGV(TAG, "Hardware Mode, lock depth = %d, %x", + ctx->lockDepth, (int)ctx->initializer); + + if (ctx->lockDepth > 0) { + /* it is unlikely that this would ever occur, + ** as the mutex should be gate keeping */ + ESP_LOGW(TAG, "WARNING: Hardware Mode " + "interesting lock depth = %d, %x", + ctx->lockDepth, (int)ctx->initializer); + } } else { - ESP_LOGV(TAG, ">>>> Hardware in use; Mode REVERT to ESP32_SHA_SW"); + /* We should have otherwise anticipated this; how did we get here? + ** This code should rarely, ideally never be reached. */ + ESP_LOGI(TAG, "\nHardware in use; Mode REVERT to ESP32_SHA_SW\n"); ctx->mode = ESP32_SHA_SW; return 0; /* success, but revert to SW */ } - } + } /* (ctx->mode == ESP32_SHA_INIT) */ else { /* this should not happen: called during mode != ESP32_SHA_INIT */ ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock."); @@ -286,37 +769,37 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) } #endif /* not defined(SINGLE_THREADED) */ +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ +#else if (ret == 0) { ctx->lockDepth++; /* depth for THIS ctx (there could be others!) */ periph_module_enable(PERIPH_SHA_MODULE); ctx->mode = ESP32_SHA_HW; } else { - ESP_LOGI(TAG, ">>>> Other problem; Mode REVERT to ESP32_SHA_SW"); + ESP_LOGW(TAG, ">>>> Other problem; Mode REVERT to ESP32_SHA_SW"); ctx->mode = ESP32_SHA_SW; } - +#endif ESP_LOGV(TAG, "leave esp_sha_hw_lock"); + return ret; } /* esp_sha_try_hw_lock */ /* -* release hw engine. when we don't have it locked, SHA module is DISABLED +** release HW engine. when we don't have it locked, SHA module is DISABLED */ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) { ESP_LOGV(TAG, "enter esp_sha_hw_unlock"); +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ +#else /* Disable AES hardware */ periph_module_disable(PERIPH_SHA_MODULE); - - #if defined(SINGLE_THREADED) - InUse = 0; - #else - /* unlock hw engine for next use */ - esp_CryptHwMutexUnLock(&sha_mutex); - #endif - +#endif /* we'll keep track of our lock depth. * in case of unexpected results, all the periph_module_disable() calls * and periph_module_disable() need to be unwound. @@ -329,24 +812,86 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) ctx->lockDepth = 0; } - ESP_LOGV(TAG, "leave esp_sha_hw_unlock"); +#if defined(SINGLE_THREADED) + InUse = 0; +#else + /* unlock HW engine for next use */ + esp_CryptHwMutexUnLock(&sha_mutex); +#endif + ESP_LOGV(TAG, "leave esp_sha_hw_unlock, %x", (int)ctx->initializer); return 0; } /* esp_sha_hw_unlock */ /* -* start sha process by using hw engine. -* assumes register already loaded. +* Start SHA process by using HW engine. +* Assumes register already loaded. +* Returns a negative value error code upon failure. */ static int esp_sha_start_process(WC_ESP32SHA* sha) { int ret = 0; +#if defined(CONFIG_IDF_TARGET_ESP32S3) + uint8_t HardwareAlgorithm; +#endif + if (sha == NULL) { - return -1; + return BAD_FUNC_ARG; } ESP_LOGV(TAG, " enter esp_sha_start_process"); - if(sha->isfirstblock){ + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ + #elif defined(CONFIG_IDF_TARGET_ESP32S3) + + /* Translate from Wolf SHA type to hardware algorithm. */ + HardwareAlgorithm = 0; + switch (sha->sha_type) { + case SHA1: + HardwareAlgorithm = 0; + break; + case SHA2_256: + HardwareAlgorithm = 2; + break; + #if defined(WOLFSSL_SHA384) + case SHA2_384: + uHardwareAlgorithm = 3; + break; + #endif + #if defined(WOLFSSL_SHA512) + case SHA2_512: + HardwareAlgorithm = 4; + break; + #endif + default: + /* Unsupported SHA mode. */ + sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; + return -1; + } + + REG_WRITE(SHA_MODE_REG, HardwareAlgorithm); + + if (sha->isfirstblock) { + REG_WRITE(SHA_START_REG, 1); + sha->isfirstblock = false; + + ESP_LOGV(TAG, " set sha->isfirstblock = 0"); + + #if defined(DEBUG_WOLFSSL) + this_block_num = 1; /* one-based counter, just for debug info */ + #endif + } /* first block */ + else { + REG_WRITE(SHA_CONTINUE_REG, 1); + + #if defined(DEBUG_WOLFSSL) + this_block_num++; /* one-based counter */ + ESP_LOGV(TAG, " continue block #%d", this_block_num); + #endif + } /* not first block */ + +#else /* not ESP32S3 */ + if (sha->isfirstblock) { /* start registers for first message block * we don't make any relational memory position assumptions. */ @@ -357,7 +902,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) case SHA2_256: DPORT_REG_WRITE(SHA_256_START_REG, 1); - break; + break; #if defined(WOLFSSL_SHA384) case SHA2_384: @@ -368,25 +913,25 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) #if defined(WOLFSSL_SHA512) case SHA2_512: DPORT_REG_WRITE(SHA_512_START_REG, 1); - break; + break; #endif default: sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; ret = -1; break; - } + } - sha->isfirstblock = 0; + sha->isfirstblock = false; ESP_LOGV(TAG, " set sha->isfirstblock = 0"); - #if defined(DEBUG_WOLFSSL) - this_block_num = 1; /* one-based counter, just for debug info */ - #endif + #if defined(DEBUG_WOLFSSL) + this_block_num = 1; /* one-based counter, just for debug info */ + #endif } else { - /* continue */ + /* continue registers for next message block. * we don't make any relational memory position assumptions * for future chip architecture changes. @@ -398,7 +943,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) case SHA2_256: DPORT_REG_WRITE(SHA_256_CONTINUE_REG, 1); - break; + break; #if defined(WOLFSSL_SHA384) case SHA2_384: @@ -409,7 +954,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) #if defined(WOLFSSL_SHA512) case SHA2_512: DPORT_REG_WRITE(SHA_512_CONTINUE_REG, 1); - break; + break; #endif default: @@ -417,85 +962,154 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) sha->mode = ESP32_SHA_FAIL_NEED_UNROLL; ret = -1; break; - } + } + } + #endif + #if defined(DEBUG_WOLFSSL) this_block_num++; /* one-based counter */ ESP_LOGV(TAG, " continue block #%d", this_block_num); #endif - } - ESP_LOGV(TAG, " leave esp_sha_start_process"); return ret; } /* -* process message block +** process message block */ -static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ +static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ const word32* data, word32 len) { + int ret = 0; /* assume success */ + word32 word32_to_save = (len) / (sizeof(word32)); +#ifdef CONFIG_IDF_TARGET_ESP32S3 + uint32_t* MessageSource; + uint32_t* AcceleratorMessage; +#else int i; - int word32_to_save = (len) / (sizeof(word32)); +#endif ESP_LOGV(TAG, " enter esp_process_block"); if (word32_to_save > 0x31) { word32_to_save = 0x31; - ESP_LOGE(TAG, " ERROR esp_process_block len exceeds 0x31 words"); + ESP_LOGE(TAG, " ERROR esp_process_block length exceeds 0x31 words."); } - /* check if there are any busy engine */ - wc_esp_wait_until_idle(); + /* wait until the engine is available */ + ret = wc_esp_wait_until_idle(); + +#if CONFIG_IDF_TARGET_ESP32S3 + MessageSource = (uint32_t*)data; + AcceleratorMessage = (uint32_t*)(SHA_TEXT_BASE); + while (word32_to_save--) { + /* Must swap endianness of data loaded into hardware accelerator to produce + * correct result. Using DPORT_REG_WRITE doesn't avoid this for ESP32s3. + * Note: data sheet claims we also need to swap endianness across 64 byte words + * when doing SHA-512, but the SHA-512 result is not correct if you do that. */ + DPORT_REG_WRITE(AcceleratorMessage, __builtin_bswap32(*MessageSource)); + ++AcceleratorMessage; + ++MessageSource; + } /* (word32_to_save--) */ - /* load [len] words of message data into hw */ +#else + /* load [len] words of message data into HW */ for (i = 0; i < word32_to_save; i++) { /* by using DPORT_REG_WRITE, we avoid the need - * to call __builtin_bswap32 to address endiness + * to call __builtin_bswap32 to address endianness. * * a useful watch array cast to watch at runtime: * ((uint32_t[32]) (*(volatile uint32_t *)(SHA_TEXT_BASE))) * * Write value to DPORT register (does not require protecting) */ + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ + #else DPORT_REG_WRITE(SHA_TEXT_BASE + (i*sizeof(word32)), *(data + i)); + #endif /* memw confirmed auto inserted by compiler here */ } +#endif - /* notify hw to start process + /* notify HW to start process * see ctx->sha_type * reg data does not change until we are ready to read */ - esp_sha_start_process(ctx); + ret = esp_sha_start_process(ctx); ESP_LOGV(TAG, " leave esp_process_block"); -} + return ret; +} /* wc_esp_process_block */ /* - * retrieve sha digest from memory - */ +** retrieve SHA digest from memory +*/ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) { + word32 digestSz; + +#if CONFIG_IDF_TARGET_ESP32S3 + uint64_t* pHash64Buffer; + uint32_t* pHashDestination; + size_t szHashWords; + size_t szHash64Words; +# endif + ESP_LOGV(TAG, "enter esp_digest_state"); - if (ctx == NULL) { - return -1; + if (ctx == NULL) { + return BAD_FUNC_ARG; } /* sanity check */ - if (ctx->sha_type == SHA_INVALID) { + digestSz = wc_esp_sha_digest_size(ctx->sha_type); + if (digestSz == 0) { ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL; ESP_LOGE(TAG, "unexpected error. sha_type is invalid."); return -1; } - - if (ctx == NULL) { - return -1; +#if CONFIG_IDF_TARGET_ESP32S3 + if (ctx->isfirstblock == true) { + /* no hardware use yet. Nothing to do yet */ + return 0; } /* wait until idle */ wc_esp_wait_until_idle(); + /* read hash result into buffer & flip endianness */ + pHashDestination = (uint32_t*)hash; + szHashWords = wc_esp_sha_digest_size(ctx->sha_type) / sizeof(uint32_t); + esp_dport_access_read_buffer(pHashDestination, SHA_H_BASE, szHashWords); + + if (ctx->sha_type == SHA2_512) { + /* Although we don't have to swap endianness on 64-bit words + ** at the input, we do for the output. */ + szHash64Words = szHashWords / 2; + pHash64Buffer = (uint64_t*)pHashDestination; + while (szHash64Words--) { + *pHash64Buffer = __builtin_bswap64(*pHash64Buffer); + ++pHash64Buffer; + } + } /* (ctx->sha_type == SHA2_512) */ + else { + while (szHashWords--) { + *pHashDestination = __builtin_bswap32(*pHashDestination); + ++pHashDestination; + } + } /* not (ctx->sha_type == SHA2_512) */ + + /* end if CONFIG_IDF_TARGET_ESP32S3 */ +#else + /* not CONFIG_IDF_TARGET_ESP32S3 */ + /* wait until idle */ + wc_esp_wait_until_idle(); + /* each sha_type register is at a different location */ +#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + /* ESP32-C3 RISC-V TODO */ +#else switch (ctx->sha_type) { case SHA1: DPORT_REG_WRITE(SHA_1_LOAD_REG, 1); @@ -520,16 +1134,13 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) default: ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL; return -1; - break; } - - if(ctx->isfirstblock == 1){ + if (ctx->isfirstblock == true) { /* no hardware use yet. Nothing to do yet */ return 0; } - /* LOAD final digest */ wc_esp_wait_until_idle(); @@ -549,21 +1160,23 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) * example: * DPORT_SEQUENCE_REG_READ(address + i * 4); */ + esp_dport_access_read_buffer( #if ESP_IDF_VERSION_MAJOR >= 4 - (uint32_t*)(hash), /* the result will be found in hash upon exit */ + (uint32_t*)(hash), /* the result will be found in hash upon exit */ #else - (word32*)(hash), /* the result will be found in hash upon exit */ + (word32*)(hash), /* the result will be found in hash upon exit */ #endif - SHA_TEXT_BASE, /* there's a fixed reg addy for all SHA */ - wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32) /* # 4-byte */ + SHA_TEXT_BASE, /* there's a fixed reg addr for all SHA */ + digestSz / sizeof(word32) /* # 4-byte */ ); +#endif #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) if (ctx->sha_type == SHA2_384 || ctx->sha_type == SHA2_512) { word32 i; word32* pwrd1 = (word32*)(hash); - /* swap value */ + /* swap 32 bit words in 64 bit values */ for (i = 0; i < WC_SHA512_DIGEST_SIZE / 4; i += 2) { pwrd1[i] ^= pwrd1[i + 1]; pwrd1[i + 1] ^= pwrd1[i]; @@ -571,14 +1184,15 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } } #endif +#endif /* not CONFIG_IDF_TARGET_ESP32S3 */ ESP_LOGV(TAG, "leave esp_digest_state"); return 0; -} +} /* wc_esp_digest_state */ #ifndef NO_SHA /* -* sha1 process +** sha1 process */ int esp_sha_process(struct wc_Sha* sha, const byte* data) { @@ -589,11 +1203,12 @@ int esp_sha_process(struct wc_Sha* sha, const byte* data) wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA_BLOCK_SIZE); ESP_LOGV(TAG, "leave esp_sha_process"); + return ret; -} +} /* esp_sha_process */ /* -* retrieve sha1 digest +** retrieve sha1 digest */ int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess) { @@ -605,20 +1220,20 @@ int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess) wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA_BLOCK_SIZE); } - wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); + ret = wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); ESP_LOGV(TAG, "leave esp_sha_digest_process"); return ret; -} +} /* esp_sha_digest_process */ #endif /* NO_SHA */ #ifndef NO_SHA256 /* -* sha256 process -* -* repeatedly call this for [N] blocks of [WC_SHA256_BLOCK_SIZE] bytes of data +** sha256 process +** +** repeatedly call this for [N] blocks of [WC_SHA256_BLOCK_SIZE] bytes of data */ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) { @@ -628,12 +1243,12 @@ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) if ((&sha->ctx)->sha_type == SHA2_256) { #if defined(DEBUG_WOLFSSL_VERBOSE) - ESP_LOGV(TAG, " confirmed sha type call match"); + ESP_LOGV(TAG, " confirmed SHA type call match"); #endif } else { ret = -1; - ESP_LOGE(TAG, " ERROR sha type call mismatch"); + ESP_LOGE(TAG, " ERROR SHA type call mismatch"); } wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA256_BLOCK_SIZE); @@ -641,13 +1256,13 @@ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) ESP_LOGV(TAG, " leave esp_sha256_process"); return ret; -} +} /* esp_sha256_process */ /* -* retrieve sha256 digest -* -* note that wc_Sha256Final() in sha256.c expects to need to reverse byte -* order, even though we could have returned them in the right order. +** retrieve sha256 digest +** +** note that wc_Sha256Final() in sha256.c expects to need to reverse byte +** order, even though we could have returned them in the right order. */ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess) { @@ -655,8 +1270,7 @@ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess) ESP_LOGV(TAG, "enter esp_sha256_digest_process"); - if(blockprocess) { - + if (blockprocess) { wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA256_BLOCK_SIZE); } @@ -664,50 +1278,58 @@ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess) ESP_LOGV(TAG, "leave esp_sha256_digest_process"); return ret; -} +} /* esp_sha256_digest_process */ #endif /* NO_SHA256 */ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) /* -* sha512 process. this is used for sha384 too. +** sha512 process. this is used for sha384 too. */ -void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal) +int esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal) { + int ret = 0; /* assume success */ ESP_LOGV(TAG, "enter esp_sha512_block"); /* start register offset */ - if(sha->ctx.mode == ESP32_SHA_SW){ - ByteReverseWords64(sha->buffer, sha->buffer, - WC_SHA512_BLOCK_SIZE); - if(isfinal) { + /* note that in SW mode, wolfSSL uses 64 bit words */ + if (sha->ctx.mode == ESP32_SHA_SW) { + ByteReverseWords64(sha->buffer, + sha->buffer, + WC_SHA512_BLOCK_SIZE); + if (isfinal) { sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha->hiLen; sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha->loLen; } - } else { - ByteReverseWords((word32*)sha->buffer, (word32*)sha->buffer, - WC_SHA512_BLOCK_SIZE); - if(isfinal){ + /* when we are in HW mode, Espressif uses 32 bit words */ + ByteReverseWords((word32*)sha->buffer, + (word32*)sha->buffer, + WC_SHA512_BLOCK_SIZE); + + if (isfinal) { sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = rotlFixed64(sha->hiLen, 32U); sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = rotlFixed64(sha->loLen, 32U); } - wc_esp_process_block(&sha->ctx, data, WC_SHA512_BLOCK_SIZE); + ret = wc_esp_process_block(&sha->ctx, data, WC_SHA512_BLOCK_SIZE); } ESP_LOGV(TAG, "leave esp_sha512_block"); -} + return ret; +} /* esp_sha512_block */ + /* -* sha512 process. this is used for sha384 too. +** sha512 process. this is used for sha384 too. */ int esp_sha512_process(struct wc_Sha512* sha) { + int ret = 0; /* assume success */ word32 *data = (word32*)sha->buffer; ESP_LOGV(TAG, "enter esp_sha512_process"); @@ -715,26 +1337,32 @@ int esp_sha512_process(struct wc_Sha512* sha) esp_sha512_block(sha, data, 0); ESP_LOGV(TAG, "leave esp_sha512_process"); - return 0; + return ret; } + /* -* retrieve sha512 digest. this is used for sha384 too. +** retrieve sha512 digest. this is used for sha384, sha512-224, sha512-256 too. */ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) { + int ret = 0; ESP_LOGV(TAG, "enter esp_sha512_digest_process"); - if(blockproc) { + if (blockproc) { word32* data = (word32*)sha->buffer; - esp_sha512_block(sha, data, 1); + ret = esp_sha512_block(sha, data, 1); + } + if (sha->ctx.mode == ESP32_SHA_HW) { + ret = wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); + } + else { + ESP_LOGW(TAG, "Call esp_sha512_digest_process in non-HW mode?"); } - if(sha->ctx.mode != ESP32_SHA_SW) - wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); ESP_LOGV(TAG, "leave esp_sha512_digest_process"); - return 0; -} + return ret; +} /* esp_sha512_digest_process */ #endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ #endif /* WOLFSSL_ESP32WROOM32_CRYPT */ #endif /* !defined(NO_SHA) ||... */ diff --git a/wolfcrypt/src/port/Espressif/esp32_util.c b/wolfcrypt/src/port/Espressif/esp32_util.c index 6f2ef11de7..172e661a8b 100644 --- a/wolfcrypt/src/port/Espressif/esp32_util.c +++ b/wolfcrypt/src/port/Espressif/esp32_util.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ #include +#include #if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ (!defined(NO_AES) || !defined(NO_SHA) || !defined(NO_SHA256) ||\ @@ -27,6 +28,8 @@ #include #include #include + + /* * 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 + #include "sdkconfig.h" + const char* TAG = "Version Info"; + #define WOLFSSL_VERSION_PRINTF(...) ESP_LOGI(TAG, __VA_ARGS__) +#else + #include + #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 + diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index f25039b5fb..e445251d17 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -36,6 +36,9 @@ This library contains implementation for the random number generator. http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I */ +#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5 + #include +#endif #if defined(HAVE_FIPS) && \ defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c index c7d02e10af..71fae7c8e0 100644 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -26,6 +26,14 @@ #include +#ifdef DEBUG_WOLFSSL_VERBOSE + #if defined(WOLFSSL_ESPIDF) + #include + #else + #include + #endif +#endif + #if !defined(NO_SHA) #if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) @@ -50,6 +58,29 @@ #include #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) diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 6bf666e710..0d9681504e 100644 --- a/wolfcrypt/src/sha256.c +++ b/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); diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index bffa98501d..a292953106 100644 --- a/wolfcrypt/src/sha512.c +++ b/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); diff --git a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 346ca52fdc..4f61000ae1 100644 --- a/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/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 -#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 + #else + #include + #endif -#if ESP_IDF_VERSION_MAJOR >= 4 - #include -#elif defined(CONFIG_IDF_TARGET_ESP32S3) - #include -#else - #include #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